tree.c (build_zero_cst): New.

* tree.c (build_zero_cst): New.
	* tree.h (build_zero_cst): Declare.
	* tree-ssa-ccp.c (get_constant_value): Accept general operands.
	(get_base_constructor): Break out from ...
	(fold_const_aggregate_ref): Here; handle empty constructors.

	* gcc.dg/torture/pr23821.c: Drop static keyword.
	* gcc.dg/tree-ssa/loop-19.c: Likewise.
	* gcc.dg/tree-ssa/foldconst-4.c: New.

From-SVN: r164250
This commit is contained in:
Jan Hubicka 2010-09-13 18:37:06 +02:00 committed by Jan Hubicka
parent ac42c96090
commit e196b22163
8 changed files with 132 additions and 102 deletions

View File

@ -1,3 +1,11 @@
2010-09-13 Jan Hubicka <jh@suse.cz>
* tree.c (build_zero_cst): New.
* tree.h (build_zero_cst): Declare.
* tree-ssa-ccp.c (get_constant_value): Accept general operands.
(get_base_constructor): Break out from ...
(fold_const_aggregate_ref): Here; handle empty constructors.
2010-09-13 Marcus Shawcroft <marcus.shawcroft@arm.com>
* config/arm/arm.md: (define_attr "conds"): Update comment.

View File

@ -1,3 +1,9 @@
2010-09-13 Jan Hubicka <jh@suse.cz>
* gcc.dg/torture/pr23821.c: Drop static keyword.
* gcc.dg/tree-ssa/loop-19.c: Likewise.
* gcc.dg/tree-ssa/foldconst-4.c: New testcase.
2010-09-13 Marcus Shawcroft <marcus.shawcroft@arm.com>
* gcc.target/arm/sync-1.c: New.

View File

@ -5,7 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-O1" } { "" } } */
/* { dg-options "-fdump-tree-ivcanon-details" } */
static int a[199];
int a[199];
extern void abort (void);

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-ccp2" } */
struct a {int a,b;};
const static struct a a;
static int b[10];
int c;
test()
{
return a.a+b[c];
}
/* { dg-final { scan-tree-dump "return 0;" "ccp2" } } */
/* { dg-final { cleanup-tree-dump "ccp2" } } */

View File

@ -9,7 +9,7 @@
/* { dg-options "-O3 -fno-prefetch-loop-arrays -fdump-tree-optimized" } */
# define N 2000000
static double a[N],c[N];
double a[N],c[N];
void tuned_STREAM_Copy()
{
int j;

View File

@ -315,7 +315,14 @@ get_value (tree var)
static inline tree
get_constant_value (tree var)
{
prop_value_t *val = get_value (var);
prop_value_t *val;
if (TREE_CODE (var) != SSA_NAME)
{
if (is_gimple_min_invariant (var))
return var;
return NULL_TREE;
}
val = get_value (var);
if (val
&& val->lattice_val == CONSTANT
&& (TREE_CODE (val->value) != INTEGER_CST
@ -1308,6 +1315,62 @@ ccp_fold (gimple stmt)
}
}
/* See if we can find constructor defining value of BASE.
As a special case, return error_mark_node when constructor
is not explicitly available, but it is known to be zero
such as 'static const int a;'. */
static tree
get_base_constructor (tree base, tree *offset)
{
*offset = NULL;
if (TREE_CODE (base) == MEM_REF)
{
if (!integer_zerop (TREE_OPERAND (base, 1)))
*offset = TREE_OPERAND (base, 1);
base = get_constant_value (TREE_OPERAND (base, 0));
if (!base || TREE_CODE (base) != ADDR_EXPR)
return NULL_TREE;
base = TREE_OPERAND (base, 0);
}
/* Get a CONSTRUCTOR. If BASE is a VAR_DECL, get its
DECL_INITIAL. If BASE is a nested reference into another
ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
the inner reference. */
switch (TREE_CODE (base))
{
case VAR_DECL:
if (!TREE_READONLY (base)
|| ((TREE_STATIC (base) || DECL_EXTERNAL (base))
&& !varpool_get_node (base)->const_value_known))
return NULL_TREE;
/* Fallthru. */
case CONST_DECL:
if (!DECL_INITIAL (base)
&& (TREE_STATIC (base) || DECL_EXTERNAL (base)))
return error_mark_node;
return DECL_INITIAL (base);
break;
case ARRAY_REF:
case COMPONENT_REF:
return fold_const_aggregate_ref (base);
break;
case STRING_CST:
case CONSTRUCTOR:
return base;
break;
default:
return NULL_TREE;
}
}
/* Return the tree representing the element referenced by T if T is an
ARRAY_REF or COMPONENT_REF into constant aggregates. Return
NULL_TREE otherwise. */
@ -1315,7 +1378,7 @@ ccp_fold (gimple stmt)
tree
fold_const_aggregate_ref (tree t)
{
tree base, ctor, idx, field;
tree ctor, idx, field;
unsigned HOST_WIDE_INT cnt;
tree cfield, cval;
tree tem;
@ -1330,46 +1393,13 @@ fold_const_aggregate_ref (tree t)
switch (TREE_CODE (t))
{
case ARRAY_REF:
/* Get a CONSTRUCTOR. If BASE is a VAR_DECL, get its
DECL_INITIAL. If BASE is a nested reference into another
ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
the inner reference. */
base = TREE_OPERAND (t, 0);
switch (TREE_CODE (base))
{
case MEM_REF:
/* ??? We could handle this case. */
if (!integer_zerop (TREE_OPERAND (base, 1)))
return NULL_TREE;
base = get_base_address (base);
if (!base
|| TREE_CODE (base) != VAR_DECL)
return NULL_TREE;
ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
/* Fallthru. */
case VAR_DECL:
if (!TREE_READONLY (base)
|| TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
|| ((TREE_STATIC (base) || DECL_EXTERNAL (base))
&& !varpool_get_node (base)->const_value_known))
return NULL_TREE;
if (idx)
return NULL_TREE;
ctor = DECL_INITIAL (base);
break;
case ARRAY_REF:
case COMPONENT_REF:
ctor = fold_const_aggregate_ref (base);
break;
case STRING_CST:
case CONSTRUCTOR:
ctor = base;
break;
default:
return NULL_TREE;
}
if (ctor == error_mark_node)
return build_zero_cst (TREE_TYPE (t));
if (ctor == NULL_TREE
|| (TREE_CODE (ctor) != CONSTRUCTOR
@ -1436,27 +1466,13 @@ fold_const_aggregate_ref (tree t)
DECL_INITIAL. If BASE is a nested reference into another
ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
the inner reference. */
base = TREE_OPERAND (t, 0);
switch (TREE_CODE (base))
{
case VAR_DECL:
if (!TREE_READONLY (base)
|| TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
|| ((TREE_STATIC (base) || DECL_EXTERNAL (base))
&& !varpool_get_node (base)->const_value_known))
return NULL_TREE;
ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
ctor = DECL_INITIAL (base);
break;
if (idx)
return NULL_TREE;
case ARRAY_REF:
case COMPONENT_REF:
ctor = fold_const_aggregate_ref (base);
break;
default:
return NULL_TREE;
}
if (ctor == error_mark_node)
return build_zero_cst (TREE_TYPE (t));
if (ctor == NULL_TREE
|| TREE_CODE (ctor) != CONSTRUCTOR)
@ -1482,55 +1498,29 @@ fold_const_aggregate_ref (tree t)
}
case MEM_REF:
/* Get the base object we are accessing. */
base = TREE_OPERAND (t, 0);
if (TREE_CODE (base) == SSA_NAME
&& (tem = get_constant_value (base)))
base = tem;
if (TREE_CODE (base) != ADDR_EXPR)
return NULL_TREE;
base = TREE_OPERAND (base, 0);
switch (TREE_CODE (base))
ctor = get_base_constructor (t, &idx);
if (ctor == error_mark_node)
return build_zero_cst (TREE_TYPE (t));
if (ctor && !AGGREGATE_TYPE_P (TREE_TYPE (ctor))
&& !idx)
{
case VAR_DECL:
if (DECL_P (base)
&& !AGGREGATE_TYPE_P (TREE_TYPE (base))
&& integer_zerop (TREE_OPERAND (t, 1)))
{
tree res = get_symbol_constant_value (base);
if (res
&& !useless_type_conversion_p
(TREE_TYPE (t), TREE_TYPE (res)))
res = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), res);
return res;
}
if (!TREE_READONLY (base)
|| TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
|| ((TREE_STATIC (base) || DECL_EXTERNAL (base))
&& !varpool_get_node (base)->const_value_known))
return NULL_TREE;
ctor = DECL_INITIAL (base);
break;
case STRING_CST:
case CONSTRUCTOR:
ctor = base;
break;
default:
return NULL_TREE;
if (ctor
&& !useless_type_conversion_p
(TREE_TYPE (t), TREE_TYPE (ctor)))
ctor = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), ctor);
return ctor;
}
if (!idx)
idx = integer_zero_node;
if (ctor == NULL_TREE
|| (TREE_CODE (ctor) != CONSTRUCTOR
&& TREE_CODE (ctor) != STRING_CST))
return NULL_TREE;
/* Get the byte offset. */
idx = TREE_OPERAND (t, 1);
/* Fold read from constant string. */
if (TREE_CODE (ctor) == STRING_CST)
{

View File

@ -1583,6 +1583,18 @@ build_one_cst (tree type)
}
}
/* Build 0 constant of type TYPE. This is used by constructor folding and thus
the constant should correspond zero in memory representation. */
tree
build_zero_cst (tree type)
{
if (!AGGREGATE_TYPE_P (type))
return fold_convert (type, integer_zero_node);
return build_constructor (type, NULL);
}
/* Build a BINFO with LEN language slots. */
tree

View File

@ -4038,6 +4038,7 @@ extern tree build_constructor_from_list (tree, tree);
extern tree build_real_from_int_cst (tree, const_tree);
extern tree build_complex (tree, tree, tree);
extern tree build_one_cst (tree);
extern tree build_zero_cst (tree);
extern tree build_string (int, const char *);
extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
#define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)