aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2010-09-13 18:37:06 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2010-09-13 16:37:06 +0000
commite196b22163a6c1a723648b3f09501ebd586fa1c0 (patch)
treebe54f7c64c42685735916f091dcaff628b5c5255 /gcc
parentac42c96090394e592af5e835412b73db6e424594 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr23821.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loop-19.c2
-rw-r--r--gcc/tree-ssa-ccp.c188
-rw-r--r--gcc/tree.c12
-rw-r--r--gcc/tree.h1
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)
{
diff --git a/gcc/tree.c b/gcc/tree.c
index c20d3b6..fd593e3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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
diff --git a/gcc/tree.h b/gcc/tree.h
index a75a852..d261c3f 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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)