| Submitter | Jan Hubicka |
|---|---|
| Date | Sept. 13, 2010, 1:52 p.m. |
| Message ID | <20100913135201.GA22498@kam.mff.cuni.cz> |
| Download | mbox | patch |
| Permalink | /patch/64604/ |
| State | New |
| Headers | show |
Comments
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.
Patch
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)
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. } } +/* 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))) + { + 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))