diff options
author | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-08 21:22:21 +0000 |
---|---|---|
committer | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-08 21:22:21 +0000 |
commit | 8782adcf1c5f6047fa912890d7b74d7636484f30 (patch) | |
tree | 751ebfba0a9f270074f551246f3c4caa2f64e963 /gcc/tree-ssa-ccp.c | |
parent | b564cd78d4b9d35879e97661dcd540bc9a70655c (diff) | |
download | gcc-8782adcf1c5f6047fa912890d7b74d7636484f30.tar.gz |
gcc/
PR tree-optimization/14841, tree-optimization/15838
* tree-ssa-ccp.c (fold_const_aggregate_ref): New.
(evaluate_stmt): Call it.
testsuite/
PR tree-optimization/14841, tree-optimization/15838
* gcc.dg/tree-ssa/pr14841.c: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99410 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r-- | gcc/tree-ssa-ccp.c | 131 |
1 files changed, 128 insertions, 3 deletions
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 2d16957a120..58b8c2c01be 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -209,6 +209,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tree-pass.h" #include "tree-ssa-propagate.h" #include "langhooks.h" +#include "target.h" /* Possible lattice values. */ @@ -970,6 +971,127 @@ ccp_fold (tree stmt) } +/* 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. */ + +static tree +fold_const_aggregate_ref (tree t) +{ + prop_value_t *value; + tree base, ctor, idx, field, elt; + + 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 VAR_DECL: + if (!TREE_READONLY (base) + || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE + || !targetm.binds_local_p (base)) + return NULL_TREE; + + ctor = DECL_INITIAL (base); + break; + + case ARRAY_REF: + case COMPONENT_REF: + ctor = fold_const_aggregate_ref (base); + break; + + default: + return NULL_TREE; + } + + if (ctor == NULL_TREE + || TREE_CODE (ctor) != CONSTRUCTOR + || !TREE_STATIC (ctor)) + return NULL_TREE; + + /* Get the index. If we have an SSA_NAME, try to resolve it + with the current lattice value for the SSA_NAME. */ + idx = TREE_OPERAND (t, 1); + switch (TREE_CODE (idx)) + { + case SSA_NAME: + if ((value = get_value (idx, true)) + && value->lattice_val == CONSTANT + && TREE_CODE (value->value) == INTEGER_CST) + idx = value->value; + else + return NULL_TREE; + break; + + case INTEGER_CST: + break; + + default: + return NULL_TREE; + } + + /* Whoo-hoo! I'll fold ya baby. Yeah! */ + for (elt = CONSTRUCTOR_ELTS (ctor); + (elt && !tree_int_cst_equal (TREE_PURPOSE (elt), idx)); + elt = TREE_CHAIN (elt)) + ; + + if (elt) + return TREE_VALUE (elt); + break; + + case COMPONENT_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 VAR_DECL: + if (!TREE_READONLY (base) + || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE + || !targetm.binds_local_p (base)) + return NULL_TREE; + + ctor = DECL_INITIAL (base); + break; + + case ARRAY_REF: + case COMPONENT_REF: + ctor = fold_const_aggregate_ref (base); + break; + + default: + return NULL_TREE; + } + + if (ctor == NULL_TREE + || TREE_CODE (ctor) != CONSTRUCTOR + || !TREE_STATIC (ctor)) + return NULL_TREE; + + field = TREE_OPERAND (t, 1); + + for (elt = CONSTRUCTOR_ELTS (ctor); elt; elt = TREE_CHAIN (elt)) + if (TREE_PURPOSE (elt) == field + /* FIXME: Handle bit-fields. */ + && ! DECL_BIT_FIELD (TREE_PURPOSE (elt))) + return TREE_VALUE (elt); + break; + + default: + break; + } + + return NULL_TREE; +} + /* Evaluate statement STMT. */ static prop_value_t @@ -989,10 +1111,13 @@ evaluate_stmt (tree stmt) bother folding the statement. */ else if (likelyvalue == VARYING) simplified = get_rhs (stmt); - /* Otherwise the statement is likely to have an UNDEFINED value and - there will be nothing to do. */ + /* If the statement is an ARRAY_REF or COMPONENT_REF into constant + aggregates, extract the referenced constant. Otherwise the + statement is likely to have an UNDEFINED value, and there will be + nothing to do. Note that fold_const_aggregate_ref returns + NULL_TREE if the first case does not match. */ else - simplified = NULL_TREE; + simplified = fold_const_aggregate_ref (get_rhs (stmt)); if (simplified && is_gimple_min_invariant (simplified)) { |