tree-ssa-sccvn.c (vn_reference_lookup_3): Improve memset handling.
authorRichard Biener <rguenther@suse.de>
Thu, 17 May 2018 12:06:44 +0000 (12:06 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 17 May 2018 12:06:44 +0000 (12:06 +0000)
2018-05-17  Richard Biener  <rguenther@suse.de>

* tree-ssa-sccvn.c (vn_reference_lookup_3): Improve memset handling.

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

From-SVN: r260318

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c

index b80d6be1357d1d13f394e0764d98fd9d48e8a319..8a800a775ce0fbc1179939b7d0b507246a2f940f 100644 (file)
@@ -1,3 +1,7 @@
+2018-05-17  Richard Biener  <rguenther@suse.de>
+
+       * tree-ssa-sccvn.c (vn_reference_lookup_3): Improve memset handling.
+
 2018-05-17  Bin Cheng  <bin.cheng@arm.com>
            Richard Biener  <rguenther@suse.de>
 
index 69a899840ddb461b9f73da4ff79272fba046d686..2139976c9f090342435f1bf4b10b15a9bdb619b4 100644 (file)
@@ -1,3 +1,7 @@
+2018-05-17  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/ssa-fre-63.c: New testcase.
+
 2018-05-17  Bin Cheng  <bin.cheng@arm.com>
 
        PR tree-optimization/85793
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c
new file mode 100644 (file)
index 0000000..39e8c08
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-stats" } */
+
+int foo(char *x)
+{
+  __builtin_memset (&x[1], 'c', 42);
+  return x[0] + x[1] + x[42] + x[43];
+}
+
+/* We should eliminate x[1] and x[42] and their conversions to int.  */
+/* { dg-final { scan-tree-dump "Eliminated: 4" "fre1" } } */
index 1463c1d411651da649ea44ae57fec2e68572d8f1..39de866a8ce7a17a7df43f423bae82c376e8c140 100644 (file)
@@ -1958,23 +1958,75 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
      1) Memset.  */
   if (is_gimple_reg_type (vr->type)
       && gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
-      && integer_zerop (gimple_call_arg (def_stmt, 1))
+      && (integer_zerop (gimple_call_arg (def_stmt, 1))
+         || (INTEGRAL_TYPE_P (vr->type) && known_eq (ref->size, 8)))
       && poly_int_tree_p (gimple_call_arg (def_stmt, 2))
-      && TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR)
+      && (TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR
+         || TREE_CODE (gimple_call_arg (def_stmt, 0)) == SSA_NAME))
     {
-      tree ref2 = TREE_OPERAND (gimple_call_arg (def_stmt, 0), 0);
       tree base2;
       poly_int64 offset2, size2, maxsize2;
       bool reverse;
-      base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2,
-                                      &reverse);
+      tree ref2 = gimple_call_arg (def_stmt, 0);
+      if (TREE_CODE (ref2) == SSA_NAME)
+       {
+         ref2 = SSA_VAL (ref2);
+         if (TREE_CODE (ref2) == SSA_NAME
+             && (TREE_CODE (base) != MEM_REF
+                 || TREE_OPERAND (base, 0) != ref2))
+           {
+             gimple *def_stmt = SSA_NAME_DEF_STMT (ref2);
+             if (gimple_assign_single_p (def_stmt)
+                 && gimple_assign_rhs_code (def_stmt) == ADDR_EXPR)
+               ref2 = gimple_assign_rhs1 (def_stmt);
+           }
+       }
+      if (TREE_CODE (ref2) == ADDR_EXPR)
+       {
+         ref2 = TREE_OPERAND (ref2, 0);
+         base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2,
+                                          &reverse);
+         if (!known_size_p (maxsize2)
+             || !operand_equal_p (base, base2, OEP_ADDRESS_OF))
+           return (void *)-1;
+       }
+      else if (TREE_CODE (ref2) == SSA_NAME)
+       {
+         poly_int64 soff;
+         if (TREE_CODE (base) != MEM_REF
+             || !(mem_ref_offset (base) << LOG2_BITS_PER_UNIT).to_shwi (&soff))
+           return (void *)-1;
+         offset += soff;
+         offset2 = 0;
+         if (TREE_OPERAND (base, 0) != ref2)
+           {
+             gimple *def = SSA_NAME_DEF_STMT (ref2);
+             if (is_gimple_assign (def)
+                 && gimple_assign_rhs_code (def) == POINTER_PLUS_EXPR
+                 && gimple_assign_rhs1 (def) == TREE_OPERAND (base, 0)
+                 && poly_int_tree_p (gimple_assign_rhs2 (def))
+                 && (wi::to_poly_offset (gimple_assign_rhs2 (def))
+                     << LOG2_BITS_PER_UNIT).to_shwi (&offset2))
+               {
+                 ref2 = gimple_assign_rhs1 (def);
+                 if (TREE_CODE (ref2) == SSA_NAME)
+                   ref2 = SSA_VAL (ref2);
+               }
+             else
+               return (void *)-1;
+           }
+       }
+      else
+       return (void *)-1;
       tree len = gimple_call_arg (def_stmt, 2);
-      if (known_size_p (maxsize2)
-         && operand_equal_p (base, base2, 0)
-         && known_subrange_p (offset, maxsize, offset2,
-                              wi::to_poly_offset (len) << LOG2_BITS_PER_UNIT))
+      if (known_subrange_p (offset, maxsize, offset2,
+                           wi::to_poly_offset (len) << LOG2_BITS_PER_UNIT))
        {
-         tree val = build_zero_cst (vr->type);
+         tree val;
+         if (integer_zerop (gimple_call_arg (def_stmt, 1)))
+           val = build_zero_cst (vr->type);
+         else
+           val = fold_convert (vr->type, gimple_call_arg (def_stmt, 1));
          return vn_reference_lookup_or_insert_for_pieces
                   (vuse, vr->set, vr->type, vr->operands, val);
        }