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:
Richard Biener 2013-02-04 12:04:35 +00:00 committed by Richard Biener
parent 2a2f32d780
commit 093e572b55
13 changed files with 238 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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" } }

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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(); }

View File

@ -0,0 +1,4 @@
/* { dg-do compile } */
extern void *memcpy();
main() { memcpy(); }

View File

@ -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,

View File

@ -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:

View File

@ -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

View File

@ -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