diff options
author | Jan Hubicka <jh@suse.cz> | 2010-09-13 18:37:06 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2010-09-13 16:37:06 +0000 |
commit | e196b22163a6c1a723648b3f09501ebd586fa1c0 (patch) | |
tree | be54f7c64c42685735916f091dcaff628b5c5255 /gcc | |
parent | ac42c96090394e592af5e835412b73db6e424594 (diff) | |
download | gcc-e196b22163a6c1a723648b3f09501ebd586fa1c0.zip gcc-e196b22163a6c1a723648b3f09501ebd586fa1c0.tar.gz gcc-e196b22163a6c1a723648b3f09501ebd586fa1c0.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr23821.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/loop-19.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 188 | ||||
-rw-r--r-- | gcc/tree.c | 12 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
8 files changed, 131 insertions, 101 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8d47a83..9341f89e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index efcecb6..59118c2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.dg/torture/pr23821.c b/gcc/testsuite/gcc.dg/torture/pr23821.c index 7d42583..7632d84 100644 --- a/gcc/testsuite/gcc.dg/torture/pr23821.c +++ b/gcc/testsuite/gcc.dg/torture/pr23821.c @@ -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); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c new file mode 100644 index 0000000..b416d37 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c index 4dfd227..80f2e60 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c @@ -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; diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 0bc90ad..42b8a58 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -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; - - 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; - - case ARRAY_REF: - case COMPONENT_REF: - ctor = fold_const_aggregate_ref (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) @@ -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)) - { - 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 = get_base_constructor (t, &idx); - ctor = DECL_INITIAL (base); - break; - - case STRING_CST: - case CONSTRUCTOR: - ctor = base; - break; + if (ctor == error_mark_node) + return build_zero_cst (TREE_TYPE (t)); - default: - return NULL_TREE; + if (ctor && !AGGREGATE_TYPE_P (TREE_TYPE (ctor)) + && !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 (!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) { @@ -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 @@ -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) |