Message ID | 20100913135201.GA22498@kam.mff.cuni.cz |
---|---|
State | New |
Headers | show |
On Mon, 13 Sep 2010, Jan Hubicka wrote: > Hi, > here is updated patch. It bootstrapped/regtested C only, I am doing full testing now. > OK if it passes? (x86-64-linux) > > Honza > > /* { 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" } } */ > * 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. > > * testsuite/gcc.dg/torture/pr23821.c: Drop static keyword. > * testsuite/gcc.dg/tree-ssa/loop-19.c: Likewise. > Index: tree.c > =================================================================== > --- tree.c (revision 164197) > +++ tree.c (working copy) > @@ -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 > Index: tree.h > =================================================================== > --- tree.h (revision 164197) > +++ tree.h (working copy) > @@ -4038,6 +4038,7 @@ extern tree build_constructor_from_list > 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) > Index: testsuite/gcc.dg/torture/pr23821.c > =================================================================== > --- testsuite/gcc.dg/torture/pr23821.c (revision 164197) > +++ testsuite/gcc.dg/torture/pr23821.c (working copy) > @@ -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); > > Index: testsuite/gcc.dg/tree-ssa/loop-19.c > =================================================================== > --- testsuite/gcc.dg/tree-ssa/loop-19.c (revision 164197) > +++ testsuite/gcc.dg/tree-ssa/loop-19.c (working copy) > @@ -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; > Index: tree-ssa-ccp.c > =================================================================== > --- tree-ssa-ccp.c (revision 164198) > +++ tree-ssa-ccp.c (working copy) > @@ -315,7 +315,15 @@ 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 > + possibly return offset of the definition in OFFSET. > + > + 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; > - > - 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; > + if (idx) > + return NULL_TREE; > > - 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,47 +1498,24 @@ 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)) > - { > - 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; > + ctor = get_base_constructor (t, &idx); > + if (!idx) > + idx = integer_zero_node; > + > + if (ctor == error_mark_node) > + return build_zero_cst (TREE_TYPE (t)); > + > + if (ctor && !AGGREGATE_TYPE_P (TREE_TYPE (ctor)) > + && integer_zerop (TREE_OPERAND (t, 1))) That would be idx? > + { > + 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 (ctor == NULL_TREE > || (TREE_CODE (ctor) != CONSTRUCTOR > && TREE_CODE (ctor) != STRING_CST)) Spurious whitespace change. And below /* Get the byte offset. */ idx = TREE_OPERAND (t, 1); this has already been set. Ok with that fixed. Thanks, Richard.
Index: tree.c =================================================================== --- tree.c (revision 164197) +++ tree.c (working copy) @@ -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 Index: tree.h =================================================================== --- tree.h (revision 164197) +++ tree.h (working copy) @@ -4038,6 +4038,7 @@ extern tree build_constructor_from_list 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) Index: testsuite/gcc.dg/torture/pr23821.c =================================================================== --- testsuite/gcc.dg/torture/pr23821.c (revision 164197) +++ testsuite/gcc.dg/torture/pr23821.c (working copy) @@ -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); Index: testsuite/gcc.dg/tree-ssa/loop-19.c =================================================================== --- testsuite/gcc.dg/tree-ssa/loop-19.c (revision 164197) +++ testsuite/gcc.dg/tree-ssa/loop-19.c (working copy) @@ -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; Index: tree-ssa-ccp.c =================================================================== --- tree-ssa-ccp.c (revision 164198) +++ tree-ssa-ccp.c (working copy) @@ -315,7 +315,15 @@ 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)