aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-ccp.c
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/tree-ssa-ccp.c
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/tree-ssa-ccp.c')
-rw-r--r--gcc/tree-ssa-ccp.c188
1 files changed, 89 insertions, 99 deletions
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)
{