The following fixes PR63916 teaching SCCVN (when not used by PRE) to
aggressively forward-propagate addresses (even with variable indexes)
into its memory reference representation.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2015-06-03  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/63916
        * tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
        Forward-propagate non-invariant addresses by splicing their
        reference ops if the result isn't going to be used by PRE.
        (vn_reference_lookup_3): Remove pointless assert.

        * gcc.dg/tree-ssa/ssa-fre-45.c: New testcase.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c        (revision 223979)
--- gcc/tree-ssa-sccvn.c        (working copy)
*************** along with GCC; see the file COPYING3.
*** 144,149 ****
--- 144,153 ----
  */
  
  
+ static tree *last_vuse_ptr;
+ static vn_lookup_kind vn_walk_kind;
+ static vn_lookup_kind default_vn_walk_kind;
+ 
  /* vn_nary_op hashtable helpers.  */
  
  struct vn_nary_op_hasher : typed_noop_remove <vn_nary_op_s>
*************** vn_reference_maybe_forwprop_address (vec
*** 1259,1264 ****
--- 1263,1287 ----
        addr = gimple_assign_rhs1 (def_stmt);
        addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
                                                 &addr_offset);
+       /* If that didn't work because the address isn't invariant propagate
+          the reference tree from the address operation in case the current
+        dereference isn't offsetted.  */
+       if (!addr_base
+         && *i_p == ops->length () - 1
+         && off == 0
+         /* This makes us disable this transform for PRE where the
+            reference ops might be also used for code insertion which
+            is invalid.  */
+         && default_vn_walk_kind == VN_WALKREWRITE)
+       {
+         auto_vec<vn_reference_op_s, 32> tem;
+         copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem);
+         ops->pop ();
+         ops->pop ();
+         ops->safe_splice (tem);
+         --*i_p;
+         return;
+       }
        if (!addr_base
          || TREE_CODE (addr_base) != MEM_REF)
        return;
*************** vn_reference_lookup_1 (vn_reference_t vr
*** 1557,1566 ****
    return NULL_TREE;
  }
  
- static tree *last_vuse_ptr;
- static vn_lookup_kind vn_walk_kind;
- static vn_lookup_kind default_vn_walk_kind;
- 
  /* Callback for walk_non_aliased_vuses.  Adjusts the vn_reference_t VR_
     with the current VUSE and performs the expression lookup.  */
  
--- 1580,1585 ----
*************** vn_reference_lookup_3 (ao_ref *ref, tree
*** 1649,1663 ****
    /* First try to disambiguate after value-replacing in the definitions LHS.  
*/
    if (is_gimple_assign (def_stmt))
      {
-       vec<vn_reference_op_s> tem;
        tree lhs = gimple_assign_lhs (def_stmt);
        bool valueized_anything = false;
        /* Avoid re-allocation overhead.  */
        lhs_ops.truncate (0);
        copy_reference_ops_from_ref (lhs, &lhs_ops);
-       tem = lhs_ops;
        lhs_ops = valueize_refs_1 (lhs_ops, &valueized_anything);
-       gcc_assert (lhs_ops == tem);
        if (valueized_anything)
        {
          lhs_ref_ok = ao_ref_init_from_vn_reference (&lhs_ref,
--- 1668,1679 ----
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-45.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-45.c  (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-45.c  (working copy)
***************
*** 0 ****
--- 1,16 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre1" } */
+ 
+ struct S { float a, b; };
+ 
+ float
+ foo (int x, float y)
+ {
+   struct S z[1024];
+   z[x].a = y;
+   struct S *p = &z[x];
+   float *q = (float *) p;
+   return *q;
+ }
+ 
+ /* { dg-final { scan-tree-dump "return y_\\d\+\\(D\\);" "fre1" } } */

Reply via email to