https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80155
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- Ah, the patches do not fix the testcase because the testcase is _not_ the PRE-creates-IV case. It's indeed simply hoisting/PRE at work transforming # a_14 = PHI <a_10(, a_5(D)> if (!b) a_8 = a_14 + 1; # a_2 = PHI <a_14(10), a_8(4)> a_10 = a_2 + 1; ... = *(a_2 + 1); to # a_14 = PHI <prephimp_12, a_5(D)> _4 = a_14 + 1; if (b) _3 = _4 + 1; # a_2 = PHI <a_14, _4> # prephitmp_12 = PHI <_4, _3> ... = *(a_2 + 1); increasing register pressure mainly because nothing figures that a_2 + 1 in the dereference can be replaced by prephitmp_12 ... So this is a missed SLSR opportunity or, in this simple form, a missed PRE/CSE opportunity. Fixing that with the following (otherwise untested) restores good code generation for the testcase: Index: gcc/tree-ssa-pre.c =================================================================== --- gcc/tree-ssa-pre.c (revision 246414) +++ gcc/tree-ssa-pre.c (working copy) @@ -4636,6 +4610,35 @@ eliminate_dom_walker::before_dom_childre } } + if (gimple_has_ops (stmt)) + for (unsigned i = 0; i < gimple_num_ops (stmt); ++i) + { + tree op = gimple_op (stmt, i); + if (op) + op = get_base_address (op); + if (op + && TREE_CODE (op) == MEM_REF + && ! integer_zerop (TREE_OPERAND (op, 1))) + { + tree ops[2]; + vn_nary_op_t nary; + ops[0] = TREE_OPERAND (op, 0); + ops[1] = TREE_OPERAND (op, 1); + tree res = vn_nary_op_lookup_pieces (2, POINTER_PLUS_EXPR, + TREE_TYPE (ops[0]), + ops, &nary); + if (res && TREE_CODE (res) == SSA_NAME) + res = eliminate_avail (res); + if (res) + { + TREE_OPERAND (op, 0) = res; + TREE_OPERAND (op, 1) + = build_int_cst (TREE_TYPE (TREE_OPERAND (op, 1)), 0); + gimple_set_modified (stmt, true); + } + } + } + if (gimple_modified_p (stmt)) { /* If a formerly non-invariant ADDR_EXPR is turned into an note that in general optimzing q = p + 1; = ...*(p + 1); "back" to *q will be undone by forwprop/stmt folding later but in this case the feeding stmt is a PHI node and not a pointer-plus. It still means that the change might be a bit too disruptive at this point (we could restricit it a bit by only handling the case where we don't replace with a pointer-plus result).