re PR tree-optimization/66142 (Loop is not vectorized because not sufficient support...
authorRichard Biener <rguenther@suse.de>
Fri, 18 Sep 2015 07:57:00 +0000 (07:57 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 18 Sep 2015 07:57:00 +0000 (07:57 +0000)
2015-09-18  Richard Biener  <rguenther@suse.de>

PR tree-optimization/66142
* fold-const.c (operand_equal_p): When OEP_ADDRESS_OF
treat MEM[&x] and x the same.
* tree-ssa-sccvn.h (vn_reference_fold_indirect): Remove.
* tree-ssa-sccvn.c (vn_reference_fold_indirect): Return true
when we simplified sth.
(vn_reference_maybe_forwprop_address): Likewise.
(valueize_refs_1): When we simplified through
vn_reference_fold_indirect or vn_reference_maybe_forwprop_address
set valueized_anything to true.
(vn_reference_lookup_3): Use stmt_kills_ref_p to see whether
one ref kills the other instead of just a offset-based test.
* tree-ssa-alias.c (stmt_kills_ref_p): Use OEP_ADDRESS_OF
for the operand_equal_p test to compare bases and also compare
sizes.

From-SVN: r227896

gcc/ChangeLog
gcc/fold-const.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-sccvn.h

index 0faf86b48783f25516ab92b4cfdaacfeb91f0590..3ee1a2d589c2cdb8966c6d46d51dfdc9bd22323f 100644 (file)
@@ -1,3 +1,21 @@
+2015-09-18  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/66142
+       * fold-const.c (operand_equal_p): When OEP_ADDRESS_OF
+       treat MEM[&x] and x the same.
+       * tree-ssa-sccvn.h (vn_reference_fold_indirect): Remove.
+       * tree-ssa-sccvn.c (vn_reference_fold_indirect): Return true
+       when we simplified sth.
+       (vn_reference_maybe_forwprop_address): Likewise.
+       (valueize_refs_1): When we simplified through
+       vn_reference_fold_indirect or vn_reference_maybe_forwprop_address
+       set valueized_anything to true.
+       (vn_reference_lookup_3): Use stmt_kills_ref_p to see whether
+       one ref kills the other instead of just a offset-based test.
+       * tree-ssa-alias.c (stmt_kills_ref_p): Use OEP_ADDRESS_OF
+       for the operand_equal_p test to compare bases and also compare
+       sizes.
+
 2015-09-17  Christian Bruel  <christian.bruel@st.com>
 
        * config/arm/arm.md (*call_value_symbol): Fix operand for interworking.
index a27ef2256abd62e529d3591d50c7b8b72fb10d18..ce2c4690d61db526d95ccad1c70598999ae66515 100644 (file)
@@ -2752,10 +2752,33 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                                   TREE_OPERAND (arg1, 0), flags);
     }
 
-  if (TREE_CODE (arg0) != TREE_CODE (arg1)
+  if (TREE_CODE (arg0) != TREE_CODE (arg1))
+    {
       /* NOP_EXPR and CONVERT_EXPR are considered equal.  */
-      && !(CONVERT_EXPR_P (arg0) && CONVERT_EXPR_P (arg1)))
-    return 0;
+      if (CONVERT_EXPR_P (arg0) && CONVERT_EXPR_P (arg1))
+       ;
+      else if (flags & OEP_ADDRESS_OF)
+       {
+         /* If we are interested in comparing addresses ignore
+            MEM_REF wrappings of the base that can appear just for
+            TBAA reasons.  */
+         if (TREE_CODE (arg0) == MEM_REF
+             && DECL_P (arg1)
+             && TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR
+             && TREE_OPERAND (TREE_OPERAND (arg0, 0), 0) == arg1
+             && integer_zerop (TREE_OPERAND (arg0, 1)))
+           return 1;
+         else if (TREE_CODE (arg1) == MEM_REF
+                  && DECL_P (arg0)
+                  && TREE_CODE (TREE_OPERAND (arg1, 0)) == ADDR_EXPR
+                  && TREE_OPERAND (TREE_OPERAND (arg1, 0), 0) == arg0
+                  && integer_zerop (TREE_OPERAND (arg1, 1)))
+           return 1;
+         return 0;
+       }
+      else
+       return 0;
+    }
 
   /* This is needed for conversions and for COMPONENT_REF.
      Might as well play it safe and always test this.  */
index 044505268a51351d1969d1611ab37949d450d2d8..bc4b52583adb42bca913604c9b196c3c9eb116d1 100644 (file)
@@ -2282,9 +2282,16 @@ stmt_kills_ref_p (gimple stmt, ao_ref *ref)
              if (saved_lhs0)
                TREE_OPERAND (lhs, 0) = saved_lhs0;
            }
-         /* Finally check if lhs is equal or equal to the base candidate
-            of the access.  */
-         if (operand_equal_p (lhs, base, 0))
+         /* Finally check if the lhs has the same address and size as the
+            base candidate of the access.  */
+         if (lhs == base
+             || (((TYPE_SIZE (TREE_TYPE (lhs))
+                   == TYPE_SIZE (TREE_TYPE (base)))
+                  || (TYPE_SIZE (TREE_TYPE (lhs))
+                      && TYPE_SIZE (TREE_TYPE (base))
+                      && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
+                                          TYPE_SIZE (TREE_TYPE (base)), 0)))
+                 && operand_equal_p (lhs, base, OEP_ADDRESS_OF)))
            return true;
        }
 
index f7904e2d3ce832d62799320d257c40e7f6ac9725..ef477e1e4efb1c2422ddb072c9246b83ba33e306 100644 (file)
@@ -1184,7 +1184,7 @@ copy_reference_ops_from_call (gcall *call,
 
 /* Fold *& at position *I_P in a vn_reference_op_s vector *OPS.  Updates
    *I_P to point to the last element of the replacement.  */
-void
+static bool
 vn_reference_fold_indirect (vec<vn_reference_op_s> *ops,
                            unsigned int *i_p)
 {
@@ -1210,12 +1210,14 @@ vn_reference_fold_indirect (vec<vn_reference_op_s> *ops,
        mem_op->off = tree_to_shwi (mem_op->op0);
       else
        mem_op->off = -1;
+      return true;
     }
+  return false;
 }
 
 /* Fold *& at position *I_P in a vn_reference_op_s vector *OPS.  Updates
    *I_P to point to the last element of the replacement.  */
-static void
+static bool
 vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
                                     unsigned int *i_p)
 {
@@ -1228,12 +1230,12 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
 
   def_stmt = SSA_NAME_DEF_STMT (op->op0);
   if (!is_gimple_assign (def_stmt))
-    return;
+    return false;
 
   code = gimple_assign_rhs_code (def_stmt);
   if (code != ADDR_EXPR
       && code != POINTER_PLUS_EXPR)
-    return;
+    return false;
 
   off = offset_int::from (mem_op->op0, SIGNED);
 
@@ -1265,11 +1267,11 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
          ops->pop ();
          ops->safe_splice (tem);
          --*i_p;
-         return;
+         return true;
        }
       if (!addr_base
          || TREE_CODE (addr_base) != MEM_REF)
-       return;
+       return false;
 
       off += addr_offset;
       off += mem_ref_offset (addr_base);
@@ -1282,7 +1284,7 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
       ptroff = gimple_assign_rhs2 (def_stmt);
       if (TREE_CODE (ptr) != SSA_NAME
          || TREE_CODE (ptroff) != INTEGER_CST)
-       return;
+       return false;
 
       off += wi::to_offset (ptroff);
       op->op0 = ptr;
@@ -1303,6 +1305,7 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
     vn_reference_maybe_forwprop_address (ops, i_p);
   else if (TREE_CODE (op->op0) == ADDR_EXPR)
     vn_reference_fold_indirect (ops, i_p);
+  return true;
 }
 
 /* Optimize the reference REF to a constant if possible or return
@@ -1475,11 +1478,17 @@ valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything)
          && vro->op0
          && TREE_CODE (vro->op0) == ADDR_EXPR
          && orig[i - 1].opcode == MEM_REF)
-       vn_reference_fold_indirect (&orig, &i);
+       {
+         if (vn_reference_fold_indirect (&orig, &i))
+           *valueized_anything = true;
+       }
       else if (i > 0
               && vro->opcode == SSA_NAME
               && orig[i - 1].opcode == MEM_REF)
-       vn_reference_maybe_forwprop_address (&orig, &i);
+       {
+         if (vn_reference_maybe_forwprop_address (&orig, &i))
+           *valueized_anything = true;
+       }
       /* If it transforms a non-constant ARRAY_REF into a constant
         one, adjust the constant offset.  */
       else if (vro->opcode == ARRAY_REF
@@ -1880,7 +1889,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
               || handled_component_p (gimple_assign_rhs1 (def_stmt))))
     {
       tree base2;
-      HOST_WIDE_INT offset2, size2, maxsize2;
+      HOST_WIDE_INT maxsize2;
       int i, j;
       auto_vec<vn_reference_op_s> rhs;
       vn_reference_op_t vro;
@@ -1891,8 +1900,6 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
 
       /* See if the assignment kills REF.  */
       base2 = ao_ref_base (&lhs_ref);
-      offset2 = lhs_ref.offset;
-      size2 = lhs_ref.size;
       maxsize2 = lhs_ref.max_size;
       if (maxsize2 == -1
          || (base != base2
@@ -1901,8 +1908,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
                  || TREE_OPERAND (base, 0) != TREE_OPERAND (base2, 0)
                  || !tree_int_cst_equal (TREE_OPERAND (base, 1),
                                          TREE_OPERAND (base2, 1))))
-         || offset2 > offset
-         || offset2 + size2 < offset + maxsize)
+         || !stmt_kills_ref_p (def_stmt, ref))
        return (void *)-1;
 
       /* Find the common base of ref and the lhs.  lhs_ops already
index 41d14afdcbaa2adb1bfe4bb4a10f5d3d5816cca0..704663d538ec46c84d72b7120f8aa9836c4e08a4 100644 (file)
@@ -204,8 +204,6 @@ vn_nary_op_t vn_nary_op_insert (tree, tree);
 vn_nary_op_t vn_nary_op_insert_stmt (gimple, tree);
 vn_nary_op_t vn_nary_op_insert_pieces (unsigned int, enum tree_code,
                                       tree, tree *, tree, unsigned int);
-void vn_reference_fold_indirect (vec<vn_reference_op_s> *,
-                                unsigned int *);
 bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, tree,
                                    vec<vn_reference_op_s> );
 tree vn_reference_lookup_pieces (tree, alias_set_type, tree,