if (CONSTANT_CLASS_P (op))
return true;
+ /* Get at the actual SSA operand. */
+ if (handled_component_p (op)
+ && TREE_CODE (TREE_OPERAND (op, 0)) == SSA_NAME)
+ op = TREE_OPERAND (op, 0);
+
/* We can still fold accesses to constant arrays when index is known. */
if (TREE_CODE (op) != SSA_NAME)
{
tree ev = analyze_scalar_evolution (loop, op);
if (chrec_contains_undetermined (ev)
|| chrec_contains_symbols (ev))
- return false;
+ {
+ if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (op)))
+ {
+ gassign *ass = nullptr;
+ gphi *phi = nullptr;
+ if (is_a <gassign *> (SSA_NAME_DEF_STMT (op)))
+ {
+ ass = as_a <gassign *> (SSA_NAME_DEF_STMT (op));
+ if (TREE_CODE (gimple_assign_rhs1 (ass)) == SSA_NAME)
+ phi = dyn_cast <gphi *>
+ (SSA_NAME_DEF_STMT (gimple_assign_rhs1 (ass)));
+ }
+ else if (is_a <gphi *> (SSA_NAME_DEF_STMT (op)))
+ {
+ phi = as_a <gphi *> (SSA_NAME_DEF_STMT (op));
+ if (gimple_bb (phi) == loop->header)
+ {
+ tree def = gimple_phi_arg_def_from_edge
+ (phi, loop_latch_edge (loop));
+ if (TREE_CODE (def) == SSA_NAME
+ && is_a <gassign *> (SSA_NAME_DEF_STMT (def)))
+ ass = as_a <gassign *> (SSA_NAME_DEF_STMT (def));
+ }
+ }
+ if (ass && phi)
+ {
+ tree rhs1 = gimple_assign_rhs1 (ass);
+ if (gimple_assign_rhs_class (ass) == GIMPLE_BINARY_RHS
+ && CONSTANT_CLASS_P (gimple_assign_rhs2 (ass))
+ && rhs1 == gimple_phi_result (phi)
+ && gimple_bb (phi) == loop->header
+ && (gimple_phi_arg_def_from_edge (phi, loop_latch_edge (loop))
+ == gimple_assign_lhs (ass))
+ && (CONSTANT_CLASS_P (gimple_phi_arg_def_from_edge
+ (phi, loop_preheader_edge (loop)))))
+ return true;
+ }
+ }
+ return false;
+ }
return true;
}