}
+/* The regular is_gimple_min_invariant does a shallow test of the object.
+ It assumes that full gimplification has happened, or will happen on the
+ object. For a value coming from DECL_INITIAL, this is not true, so we
+ have to be more strict outselves. */
+
+static bool
+ccp_decl_initial_min_invariant (tree t)
+{
+ if (!is_gimple_min_invariant (t))
+ return false;
+ if (TREE_CODE (t) == ADDR_EXPR)
+ {
+ /* Inline and unroll is_gimple_addressable. */
+ while (1)
+ {
+ t = TREE_OPERAND (t, 0);
+ if (is_gimple_id (t))
+ return true;
+ if (!handled_component_p (t))
+ return false;
+ }
+ }
+ return true;
+}
+
+
/* Compute a default value for variable VAR and store it in the
CONST_VAL array. The following rules are used to get default
values:
else if (TREE_STATIC (sym)
&& TREE_READONLY (sym)
&& DECL_INITIAL (sym)
- && is_gimple_min_invariant (DECL_INITIAL (sym)))
+ && ccp_decl_initial_min_invariant (DECL_INITIAL (sym)))
{
/* Globals and static variables declared 'const' take their
initial value. */
&& TREE_CODE (stmt) != SWITCH_EXPR)
return VARYING;
+ if (is_gimple_min_invariant (get_rhs (stmt)))
+ return CONSTANT;
+
found_constant = false;
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE|SSA_OP_VUSE)
{
&& val2->lattice_val == CONSTANT
&& simple_cst_equal (val1->value, val2->value) == 1
&& (!do_store_ccp
- || simple_cst_equal (val1->mem_ref, val2->mem_ref) == 1))
+ || (val1->mem_ref && val2->mem_ref
+ && operand_equal_p (val1->mem_ref, val2->mem_ref, 0))))
{
/* Ci M Cj = Ci if (i == j)
Ci M Cj = VARYING if (i != j)
/* If the RHS is a memory load, see if the VUSEs associated with
it are a valid constant for that memory load. */
prop_value_t *val = get_value_loaded_by (stmt, const_val);
- if (val && simple_cst_equal (val->mem_ref, rhs) == 1)
+ if (val && val->mem_ref
+ && operand_equal_p (val->mem_ref, rhs, 0))
return val->value;
else
return NULL_TREE;
op0 = get_value (op0, true)->value;
}
+ if ((code == NOP_EXPR || code == CONVERT_EXPR)
+ && tree_ssa_useless_type_conversion_1 (TREE_TYPE (rhs),
+ TREE_TYPE (op0)))
+ return op0;
return fold_unary (code, TREE_TYPE (rhs), op0);
}
fold_const_aggregate_ref (tree t)
{
prop_value_t *value;
- tree base, ctor, idx, field, elt;
+ tree base, ctor, idx, field;
+ unsigned HOST_WIDE_INT cnt;
+ tree cfield, cval;
switch (TREE_CODE (t))
{
}
/* 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);
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+ if (tree_int_cst_equal (cfield, idx))
+ return cval;
break;
case COMPONENT_REF:
field = TREE_OPERAND (t, 1);
- for (elt = CONSTRUCTOR_ELTS (ctor); elt; elt = TREE_CHAIN (elt))
- if (TREE_PURPOSE (elt) == field
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+ if (cfield == field
/* FIXME: Handle bit-fields. */
- && ! DECL_BIT_FIELD (TREE_PURPOSE (elt)))
- return TREE_VALUE (elt);
+ && ! DECL_BIT_FIELD (cfield))
+ return cval;
break;
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ {
+ tree c = fold_const_aggregate_ref (TREE_OPERAND (t, 0));
+ if (c && TREE_CODE (c) == COMPLEX_CST)
+ return fold_build1 (TREE_CODE (t), TREE_TYPE (t), c);
+ break;
+ }
+
default:
break;
}
/* The statement produced a nonconstant value. If the statement
had UNDEFINED operands, then the result of the statement
should be UNDEFINED. Otherwise, the statement is VARYING. */
- val.lattice_val = (likelyvalue == UNDEFINED) ? UNDEFINED : VARYING;
+ if (likelyvalue == UNDEFINED || likelyvalue == UNKNOWN_VAL)
+ val.lattice_val = likelyvalue;
+ else
+ val.lattice_val = VARYING;
+
val.value = NULL_TREE;
}
we can propagate the value on the RHS. */
prop_value_t *nval = get_value_loaded_by (stmt, const_val);
- if (nval && simple_cst_equal (nval->mem_ref, rhs) == 1)
+ if (nval && nval->mem_ref
+ && operand_equal_p (nval->mem_ref, rhs, 0))
val = *nval;
else
val = evaluate_stmt (stmt);
for (i = 0, mask = 0; i < field_size; i++)
mask |= ((HOST_WIDE_INT) 1) << i;
- wide_val = build2 (BIT_AND_EXPR, TREE_TYPE (var), val,
- build_int_cst (TREE_TYPE (var), mask));
+ wide_val = fold_build2 (BIT_AND_EXPR, TREE_TYPE (var), val,
+ build_int_cst (TREE_TYPE (var), mask));
}
else
{
for (i = 0, mask = 0; i < (var_size - field_size); i++)
mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1);
- wide_val = build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
- build_int_cst (TREE_TYPE (var), mask));
+ wide_val = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
+ build_int_cst (TREE_TYPE (var), mask));
}
- return fold (wide_val);
+ return wide_val;
}
if (!integer_zerop (elt_offset))
idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0);
- return build (ARRAY_REF, orig_type, base, idx, min_idx,
- size_int (tree_low_cst (elt_size, 1)
- / (TYPE_ALIGN_UNIT (elt_type))));
+ return build4 (ARRAY_REF, orig_type, base, idx, min_idx,
+ size_int (tree_low_cst (elt_size, 1)
+ / (TYPE_ALIGN_UNIT (elt_type))));
}
{
if (base_is_ptr)
base = build1 (INDIRECT_REF, record_type, base);
- t = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
+ t = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
return t;
}
nonzero offset into them. Recurse and hope for a valid match. */
if (base_is_ptr)
base = build1 (INDIRECT_REF, record_type, base);
- base = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
+ base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
if (t)
/* Fold away CONST_DECL to its value, if the type is scalar. */
if (TREE_CODE (base) == CONST_DECL
- && is_gimple_min_invariant (DECL_INITIAL (base)))
+ && ccp_decl_initial_min_invariant (DECL_INITIAL (base)))
return DECL_INITIAL (base);
/* Try folding *(&B+O) to B[X]. */
}
-/* Fold the statement pointed by STMT_P. In some cases, this function may
+/* Fold the statement pointed to by STMT_P. In some cases, this function may
replace the whole statement with a new one. Returns true iff folding
makes any changes. */
return changed;
new_rhs = fold (rhs);
+ STRIP_USELESS_TYPE_CONVERSION (new_rhs);
if (new_rhs == rhs)
return changed;
gcc_assert (ok);
}
}
- update_stmt (*stmtp);
+ mark_new_vars_to_rename (*stmtp);
if (maybe_clean_or_replace_eh_stmt (old_stmt, *stmtp)
&& tree_purge_dead_eh_edges (bb))
cfg_changed = true;