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.  */

Reply via email to