===================================================================
@@ -4870,6 +4870,7 @@ extern void dump_gimple_statistics (void
/* In gimple-fold.c. */
void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
tree gimple_fold_builtin (gimple);
+tree fold_const_array_ref (tree, tree, tree);
bool fold_stmt (gimple_stmt_iterator *);
bool fold_stmt_inplace (gimple);
tree maybe_fold_offset_to_address (location_t, tree, tree, tree);
===================================================================
@@ -1109,24 +1109,56 @@ fully_constant_vn_reference_p (vn_refere
return folded;
}
}
-
- /* Simplify reads from constant strings. */
+ else if (op->opcode == VAR_DECL
+ || op->opcode == CONST_DECL)
+ return get_symbol_constant_value (op->op0);
else if (op->opcode == ARRAY_REF
- && TREE_CODE (op->op0) == INTEGER_CST
- && integer_zerop (op->op1)
&& VEC_length (vn_reference_op_s, operands) == 2)
{
vn_reference_op_t arg0;
+ tree ctor = NULL_TREE;
+ tree op0;
+
arg0 = VEC_index (vn_reference_op_s, operands, 1);
- if (arg0->opcode == STRING_CST
- && (TYPE_MODE (op->type)
- == TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0->op0))))
- && GET_MODE_CLASS (TYPE_MODE (op->type)) == MODE_INT
- && GET_MODE_SIZE (TYPE_MODE (op->type)) == 1
- && compare_tree_int (op->op0, TREE_STRING_LENGTH (arg0->op0)) < 0)
- return build_int_cst_type (op->type,
- (TREE_STRING_POINTER (arg0->op0)
- [TREE_INT_CST_LOW (op->op0)]));
+ op0 = arg0->op0;
+
+ switch (arg0->opcode)
+ {
+ case MEM_REF:
+ /* ??? We could handle this case. */
+ if (!integer_zerop (TREE_OPERAND (op0, 1)))
+ return NULL_TREE;
+ op0 = get_base_address (op0);
+ if (!op0
+ || TREE_CODE (op0) != VAR_DECL)
+ return NULL_TREE;
+
+ /* Fallthru. */
+ case VAR_DECL:
+ if (!TREE_READONLY (op0)
+ || TREE_CODE (TREE_TYPE (op0)) != ARRAY_TYPE
+ || ((TREE_STATIC (op0) || DECL_EXTERNAL (op0))
+ && !varpool_get_node (op0)->const_value_known))
+ return NULL_TREE;
+
+ ctor = DECL_INITIAL (op0);
+ break;
+
+ case ARRAY_REF:
+ case COMPONENT_REF:
+ gcc_unreachable ();
+ break;
+
+ case STRING_CST:
+ case CONSTRUCTOR:
+ ctor = op0;
+ break;
+
+ default:
+ break;
+ }
+ if (ctor)
+ return fold_const_array_ref (op->type, ctor, op->op0);
}
return NULL_TREE;
===================================================================
@@ -1310,6 +1310,62 @@ ccp_fold (gimple stmt)
}
}
+/* Fold array reference of TYPE into a variable with known value CTOR
+ with known index IDX. */
+tree
+fold_const_array_ref (tree type, tree ctor, tree idx)
+{
+ unsigned HOST_WIDE_INT cnt;
+ tree cfield, cval;
+ tree tem;
+
+ if (ctor == NULL_TREE
+ || (TREE_CODE (ctor) != CONSTRUCTOR
+ && TREE_CODE (ctor) != STRING_CST)
+ || !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. */
+ switch (TREE_CODE (idx))
+ {
+ case SSA_NAME:
+ if ((tem = get_constant_value (idx))
+ && TREE_CODE (tem) == INTEGER_CST)
+ idx = tem;
+ else
+ return NULL_TREE;
+ break;
+
+ case INTEGER_CST:
+ break;
+
+ default:
+ return NULL_TREE;
+ }
+
+ /* Fold read from constant string. */
+ if (TREE_CODE (ctor) == STRING_CST)
+ {
+ if ((TYPE_MODE (type)
+ == TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
+ && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
+ == MODE_INT)
+ && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) == 1
+ && compare_tree_int (idx, TREE_STRING_LENGTH (ctor)) < 0)
+ return build_int_cst_type (type,
+ (TREE_STRING_POINTER (ctor)
+ [TREE_INT_CST_LOW (idx)]));
+ return NULL_TREE;
+ }
+
+ /* Whoo-hoo! I'll fold ya baby. Yeah! */
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+ if (tree_int_cst_equal (cfield, idx))
+ return canonicalize_constructor_val (cval);
+ 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. */
@@ -1332,11 +1388,11 @@ fold_const_aggregate_ref (tree t)
switch (TREE_CODE (t))
{
case ARRAY_REF:
+ base = TREE_OPERAND (t, 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. */
- base = TREE_OPERAND (t, 0);
switch (TREE_CODE (base))
{
case MEM_REF:
@@ -1373,51 +1429,9 @@ fold_const_aggregate_ref (tree t)
return NULL_TREE;
}
- if (ctor == NULL_TREE
- || (TREE_CODE (ctor) != CONSTRUCTOR
- && TREE_CODE (ctor) != STRING_CST)
- || !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 ((tem = get_constant_value (idx))
- && TREE_CODE (tem) == INTEGER_CST)
- idx = tem;
- else
- return NULL_TREE;
- break;
-
- case INTEGER_CST:
- break;
-
- default:
- return NULL_TREE;
- }
-
- /* Fold read from constant string. */
- if (TREE_CODE (ctor) == STRING_CST)
- {
- if ((TYPE_MODE (TREE_TYPE (t))
- == TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
- && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
- == MODE_INT)
- && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) == 1
- && compare_tree_int (idx, TREE_STRING_LENGTH (ctor)) < 0)
- return build_int_cst_type (TREE_TYPE (t),
- (TREE_STRING_POINTER (ctor)
- [TREE_INT_CST_LOW (idx)]));
- return NULL_TREE;
- }
-
- /* Whoo-hoo! I'll fold ya baby. Yeah! */
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
- if (tree_int_cst_equal (cfield, idx))
- return canonicalize_constructor_val (cval);
+ return fold_const_array_ref (TREE_TYPE (t),
+ ctor,
+ TREE_OPERAND (t, 1));
break;
case COMPONENT_REF: