backport: [multiple changes]
2013-02-04 Richard Biener <rguenther@suse.de> Backport from mainline 2012-07-04 Richard Guenther <rguenther@suse.de> PR tree-optimization/53844 * tree-ssa-dse.c (dse_possible_dead_store_p): Properly handle the loop virtual PHI. * g++.dg/tree-ssa/pr53844.C: New testcase. 2012-12-13 Richard Biener <rguenther@suse.de> PR lto/55660 * tree-streamer.c (record_common_node): Check that we are not recursively pre-loading nodes we want to skip. Handle char_type_node appearing as part of va_list_type_node. * gcc.dg/lto/pr55660_0.c: New testcase. * gcc.dg/lto/pr55660_1.c: Likewise. 2013-02-04 Richard Biener <rguenther@suse.de> PR middle-end/55890 * gimple.h (gimple_call_builtin_class_p): New function. * gimple.c (validate_call): New function. (gimple_call_builtin_class_p): Likewise. * tree-ssa-structalias.c (find_func_aliases_for_builtin_call): Use gimple_call_builtin_class_p. (find_func_clobbers): Likewise. * tree-ssa-strlen.c (adjust_last_stmt): Likewise. (strlen_optimize_stmt): Likewise. * gcc.dg/torture/pr55890-1.c: New testcase. * gcc.dg/torture/pr55890-2.c: Likewise. From-SVN: r195708
This commit is contained in:
parent
2a2f32d780
commit
093e572b55
|
@ -1,3 +1,31 @@
|
|||
2013-02-04 Richard Biener <rguenther@suse.de>
|
||||
|
||||
Backport from mainline
|
||||
2012-07-04 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/53844
|
||||
* tree-ssa-dse.c (dse_possible_dead_store_p): Properly handle
|
||||
the loop virtual PHI.
|
||||
|
||||
2012-12-13 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR lto/55660
|
||||
* tree-streamer.c (record_common_node): Check that we are not
|
||||
recursively pre-loading nodes we want to skip. Handle
|
||||
char_type_node appearing as part of va_list_type_node.
|
||||
|
||||
2013-02-04 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR middle-end/55890
|
||||
* gimple.h (gimple_call_builtin_class_p): New function.
|
||||
* gimple.c (validate_call): New function.
|
||||
(gimple_call_builtin_class_p): Likewise.
|
||||
* tree-ssa-structalias.c (find_func_aliases_for_builtin_call):
|
||||
Use gimple_call_builtin_class_p.
|
||||
(find_func_clobbers): Likewise.
|
||||
* tree-ssa-strlen.c (adjust_last_stmt): Likewise.
|
||||
(strlen_optimize_stmt): Likewise.
|
||||
|
||||
2013-02-01 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
Backported from mainline
|
||||
|
|
55
gcc/gimple.c
55
gcc/gimple.c
|
@ -5464,16 +5464,61 @@ gimple_decl_printable_name (tree decl, int verbosity)
|
|||
return IDENTIFIER_POINTER (DECL_NAME (decl));
|
||||
}
|
||||
|
||||
/* Return true when STMT is builtins call to CODE. */
|
||||
/* Return true when STMTs arguments match those of FNDECL. */
|
||||
|
||||
static bool
|
||||
validate_call (gimple stmt, tree fndecl)
|
||||
{
|
||||
tree arg, targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
|
||||
unsigned nargs = gimple_call_num_args (stmt);
|
||||
unsigned i;
|
||||
for (i = 0; i < nargs; ++i)
|
||||
{
|
||||
/* Variadic args follow. */
|
||||
if (!targs)
|
||||
return true;
|
||||
arg = gimple_call_arg (stmt, i);
|
||||
if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
|
||||
&& INTEGRAL_TYPE_P (TREE_VALUE (targs)))
|
||||
;
|
||||
else if (POINTER_TYPE_P (TREE_TYPE (arg))
|
||||
&& POINTER_TYPE_P (TREE_VALUE (targs)))
|
||||
;
|
||||
else if (TREE_CODE (TREE_TYPE (arg))
|
||||
!= TREE_CODE (TREE_VALUE (targs)))
|
||||
return false;
|
||||
targs = TREE_CHAIN (targs);
|
||||
}
|
||||
if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return true when STMT is builtins call to CLASS. */
|
||||
|
||||
bool
|
||||
gimple_call_builtin_class_p (gimple stmt, enum built_in_class klass)
|
||||
{
|
||||
tree fndecl;
|
||||
if (is_gimple_call (stmt)
|
||||
&& (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
|
||||
&& DECL_BUILT_IN_CLASS (fndecl) == klass)
|
||||
return validate_call (stmt, fndecl);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return true when STMT is builtins call to CODE of CLASS. */
|
||||
|
||||
bool
|
||||
gimple_call_builtin_p (gimple stmt, enum built_in_function code)
|
||||
{
|
||||
tree fndecl;
|
||||
return (is_gimple_call (stmt)
|
||||
&& (fndecl = gimple_call_fndecl (stmt)) != NULL
|
||||
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
|
||||
&& DECL_FUNCTION_CODE (fndecl) == code);
|
||||
if (is_gimple_call (stmt)
|
||||
&& (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
|
||||
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
|
||||
&& DECL_FUNCTION_CODE (fndecl) == code)
|
||||
return validate_call (stmt, fndecl);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return true if STMT clobbers memory. STMT is required to be a
|
||||
|
|
|
@ -1023,6 +1023,7 @@ extern bool walk_stmt_load_store_ops (gimple, void *,
|
|||
bool (*)(gimple, tree, void *),
|
||||
bool (*)(gimple, tree, void *));
|
||||
extern bool gimple_ior_addresses_taken (bitmap, gimple);
|
||||
extern bool gimple_call_builtin_class_p (gimple, enum built_in_class);
|
||||
extern bool gimple_call_builtin_p (gimple, enum built_in_function);
|
||||
extern bool gimple_asm_clobbers_memory_p (const_gimple);
|
||||
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
2013-02-04 Richard Biener <rguenther@suse.de>
|
||||
|
||||
Backport from mainline
|
||||
2012-07-04 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/53844
|
||||
* g++.dg/tree-ssa/pr53844.C: New testcase.
|
||||
|
||||
2012-12-13 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR lto/55660
|
||||
* gcc.dg/lto/pr55660_0.c: New testcase.
|
||||
* gcc.dg/lto/pr55660_1.c: Likewise.
|
||||
|
||||
2013-02-04 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR middle-end/55890
|
||||
* gcc.dg/torture/pr55890-1.c: New testcase.
|
||||
* gcc.dg/torture/pr55890-2.c: Likewise.
|
||||
|
||||
2013-02-02 Thomas Koenig <tkoenig@gcc.gnu.org>
|
||||
|
||||
Backport from trunk
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-O2 -fdump-tree-optimized-vops" }
|
||||
|
||||
struct VBase;
|
||||
|
||||
//Very minimal numeric vector class where Base provides the policy
|
||||
template<typename Base=VBase>
|
||||
struct Vector : public Base{
|
||||
|
||||
inline Vector(const Base& b)
|
||||
:Base(b)
|
||||
{
|
||||
}
|
||||
|
||||
//Assignment from any other sort of Vector
|
||||
template<typename Base2>
|
||||
void operator= (const Vector<Base2>& from)
|
||||
{
|
||||
for(int i=0; i<100; i++){
|
||||
(*this)[i]=from[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Base class to represent pointer as a Vector
|
||||
struct VBase{
|
||||
double * const my_data;
|
||||
|
||||
double& operator[](int i) {
|
||||
return my_data[i];
|
||||
}
|
||||
|
||||
const double& operator[](int i) const {
|
||||
return my_data[i];
|
||||
}
|
||||
};
|
||||
|
||||
//Base class providing very minimalistic expression template
|
||||
template<class B2> struct ScalarMulExpr
|
||||
{
|
||||
const int& mul;
|
||||
const Vector<B2>& vec;
|
||||
|
||||
int size() const
|
||||
{
|
||||
return vec.size();
|
||||
}
|
||||
|
||||
double operator[](int i) const
|
||||
{
|
||||
return vec[i]*mul;
|
||||
}
|
||||
|
||||
ScalarMulExpr(const Vector<B2>& vec_, const int& m)
|
||||
:mul(m),vec(vec_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//Allow vector to be multiplied by a scalar
|
||||
template<class B2>
|
||||
Vector<ScalarMulExpr<B2> > operator*(const Vector<B2>& lhs, const int& rhs)
|
||||
{
|
||||
return ScalarMulExpr<B2>(lhs, rhs);
|
||||
}
|
||||
|
||||
//Test function producing suboptimal asm code
|
||||
void test(const Vector<>& in, Vector<>& out, int i)
|
||||
{
|
||||
out=in*1*1*1*1*1*1*1*1*1*1*1;
|
||||
}
|
||||
|
||||
// There should be a single store remaining, inside the loops. All
|
||||
// dead stores to unused temporaries should have been removed.
|
||||
|
||||
// { dg-final { scan-tree-dump-times "VDEF" 1 "optimized" } }
|
||||
// { dg-final { cleanup-tree-dump "optimized" } }
|
|
@ -0,0 +1,11 @@
|
|||
/* { dg-lto-do run } */
|
||||
/* { dg-extra-ld-options { -funsigned-char } } */
|
||||
|
||||
char n[3] = {'a','b','c'};
|
||||
int foo(char *x)
|
||||
{
|
||||
if (*x == 'b')
|
||||
return (int)*x;
|
||||
*x = 'y';
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
extern int foo (char*);
|
||||
extern void abort (void);
|
||||
|
||||
extern char n[3];
|
||||
|
||||
int main ()
|
||||
{
|
||||
int i, m = 0;
|
||||
for (i = 0; i < 3; i++)
|
||||
m += foo(&n[i]);
|
||||
|
||||
if (m != 'b')
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
extern void *memmove(void *, void *, __SIZE_TYPE__);
|
||||
typedef int (*_TEST_fun_) ();
|
||||
static _TEST_fun_ i = (_TEST_fun_) memmove;
|
||||
main() { i(); }
|
|
@ -0,0 +1,4 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
extern void *memcpy();
|
||||
main() { memcpy(); }
|
|
@ -94,7 +94,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
|
|||
temp = stmt;
|
||||
do
|
||||
{
|
||||
gimple use_stmt;
|
||||
gimple use_stmt, defvar_def;
|
||||
imm_use_iterator ui;
|
||||
bool fail = false;
|
||||
tree defvar;
|
||||
|
@ -108,6 +108,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
|
|||
defvar = PHI_RESULT (temp);
|
||||
else
|
||||
defvar = gimple_vdef (temp);
|
||||
defvar_def = temp;
|
||||
temp = NULL;
|
||||
FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
|
||||
{
|
||||
|
@ -139,7 +140,14 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
|
|||
fail = true;
|
||||
BREAK_FROM_IMM_USE_STMT (ui);
|
||||
}
|
||||
temp = use_stmt;
|
||||
/* Do not consider the PHI as use if it dominates the
|
||||
stmt defining the virtual operand we are processing,
|
||||
we have processed it already in this case. */
|
||||
if (gimple_bb (defvar_def) != gimple_bb (use_stmt)
|
||||
&& !dominated_by_p (CDI_DOMINATORS,
|
||||
gimple_bb (defvar_def),
|
||||
gimple_bb (use_stmt)))
|
||||
temp = use_stmt;
|
||||
}
|
||||
/* If the statement is a use the store is not dead. */
|
||||
else if (ref_maybe_used_by_stmt_p (use_stmt,
|
||||
|
|
|
@ -812,10 +812,10 @@ adjust_last_stmt (strinfo si, gimple stmt, bool is_strcat)
|
|||
|
||||
if (!is_gimple_call (last.stmt))
|
||||
return;
|
||||
callee = gimple_call_fndecl (last.stmt);
|
||||
if (callee == NULL_TREE || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
|
||||
if (!gimple_call_builtin_class_p (last.stmt, BUILT_IN_NORMAL))
|
||||
return;
|
||||
|
||||
callee = gimple_call_fndecl (last.stmt);
|
||||
switch (DECL_FUNCTION_CODE (callee))
|
||||
{
|
||||
case BUILT_IN_MEMCPY:
|
||||
|
@ -1753,7 +1753,7 @@ strlen_optimize_stmt (gimple_stmt_iterator *gsi)
|
|||
if (is_gimple_call (stmt))
|
||||
{
|
||||
tree callee = gimple_call_fndecl (stmt);
|
||||
if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
|
||||
if (gimple_call_builtin_class_p (stmt, BUILT_IN_NORMAL))
|
||||
switch (DECL_FUNCTION_CODE (callee))
|
||||
{
|
||||
case BUILT_IN_STRLEN:
|
||||
|
|
|
@ -4029,8 +4029,7 @@ find_func_aliases_for_builtin_call (gimple t)
|
|||
VEC(ce_s, heap) *rhsc = NULL;
|
||||
varinfo_t fi;
|
||||
|
||||
if (fndecl != NULL_TREE
|
||||
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
|
||||
if (gimple_call_builtin_class_p (t, BUILT_IN_NORMAL))
|
||||
/* ??? All builtins that are handled here need to be handled
|
||||
in the alias-oracle query functions explicitly! */
|
||||
switch (DECL_FUNCTION_CODE (fndecl))
|
||||
|
@ -4771,8 +4770,7 @@ find_func_clobbers (gimple origt)
|
|||
|
||||
/* For builtins we do not have separate function info. For those
|
||||
we do not generate escapes for we have to generate clobbers/uses. */
|
||||
if (decl
|
||||
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
|
||||
if (gimple_call_builtin_class_p (t, BUILT_IN_NORMAL))
|
||||
switch (DECL_FUNCTION_CODE (decl))
|
||||
{
|
||||
/* The following functions use and clobber memory pointed to
|
||||
|
|
|
@ -251,6 +251,16 @@ streamer_tree_cache_get (struct streamer_tree_cache_d *cache, unsigned ix)
|
|||
static void
|
||||
record_common_node (struct streamer_tree_cache_d *cache, tree node)
|
||||
{
|
||||
/* If we recursively end up at nodes we do not want to preload simply don't.
|
||||
??? We'd want to verify that this doesn't happen, or alternatively
|
||||
do not recurse at all. */
|
||||
if (node == char_type_node)
|
||||
return;
|
||||
|
||||
gcc_checking_assert (node != boolean_type_node
|
||||
&& node != boolean_true_node
|
||||
&& node != boolean_false_node);
|
||||
|
||||
/* We have to make sure to fill exactly the same number of
|
||||
elements for all frontends. That can include NULL trees.
|
||||
As our hash table can't deal with zero entries we'll simply stream
|
||||
|
|
Loading…
Reference in New Issue