This massages the GIMPLE reassoc pass to associate constant offsets into a invariant base. For one of the testcases in PR63184 this does
i.0_1 = i; _2 = i.0_1 * 4; _3 = (sizetype) _2; - _4 = _3 + 4; - _5 = &a[1] + _4; + _4 = _3; + _5 = &MEM[(void *)&a + 8B] + _4; this performs sth that RTL expansion does already with -ftree-ter. In it's own it isn't enough to fix PR63184 thus I'm not sure it is worth it at this point. Without swapping SLSR and late reassoc we still end up with i.0_1 = i; _2 = i.0_1 * 4; _3 = (sizetype) _2; _5 = &MEM[(void *)&a + 8B] + _3; _6 = i.0_1 + 2; _12 = (sizetype) _6; _13 = _3 + 8; _7 = &a + _13; swapping makes late rassoc perform the same trick again and then DOM figures out the equivalency. In the end the issue is address canonicalization, either directly in the IL or in passes doing VN or folding. More aggressively using infrastructure like tree-affine would be another solution here (but tree-affine comes at a cost so I'm worrying to use that from say match.pd patterns). Bootstrapped & tested on x86_64-unknown-linux-gnu. Posting here mainly for reference. I'll see if I can try a tree-affine match.pd pattern tomorrow. Richard. 2018-12-06 Richard Biener <rguent...@suse.de> PR tree-optimization/63184 * tree-ssa-reassoc.c (reassociate_bb): Forward a constant into a single-use in a POINTER_PLUS_EXPR invariant address base. diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index a9f45bfd891..fb1f8014633 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -5988,6 +5988,31 @@ reassociate_bb (basic_block bb) } } + /* If the association chain is used in a single + POINTER_PLUS_EXPR with an invariant first operand + then combine a constant element with the invariant + address. */ + use_operand_p use_p; + gimple *use_stmt; + if (ops.length () > 1 + && rhs_code == PLUS_EXPR + && TREE_CODE (ops.last ()->op) == INTEGER_CST + && single_imm_use (lhs, &use_p, &use_stmt) + && is_gimple_assign (use_stmt) + && gimple_assign_rhs_code (use_stmt) == POINTER_PLUS_EXPR + && TREE_CODE (gimple_assign_rhs1 (use_stmt)) == ADDR_EXPR) + { + last = ops.pop (); + tree addr = gimple_assign_rhs1 (use_stmt); + addr = build1 (ADDR_EXPR, TREE_TYPE (addr), + fold_build2 (MEM_REF, + TREE_TYPE (TREE_TYPE (addr)), + addr, + fold_convert (ptr_type_node, + last->op))); + gimple_assign_set_rhs1 (use_stmt, addr); + } + tree new_lhs = lhs; /* If the operand vector is now empty, all operands were consumed by the __builtin_powi optimization. */