Improve memset handling in value-numbering

Message ID alpine.LSU.2.20.1805171404550.24704@zhemvz.fhfr.qr
State New
Headers show
Series
  • Improve memset handling in value-numbering
Related show

Commit Message

Richard Biener May 17, 2018, 12:05 p.m.
Noticed in PR63185.

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

Richard.

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.

Comments

H.J. Lu May 20, 2018, 12:54 p.m. | #1
On Thu, May 17, 2018 at 5:05 AM, Richard Biener <rguenther@suse.de> wrote:
>
> Noticed in PR63185.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
>
> Richard.
>
> 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.
>

This caused:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85849
Richard Biener May 20, 2018, 1:10 p.m. | #2
On May 20, 2018 2:54:46 PM GMT+02:00, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>On Thu, May 17, 2018 at 5:05 AM, Richard Biener <rguenther@suse.de>
>wrote:
>>
>> Noticed in PR63185.
>>
>> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
>>
>> Richard.
>>
>> 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.
>>
>
>This caused:
>
>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85849

It'll take me until Tuesday to look at this due to public holidays. 

Sorry for the inconvenience,
Richard.

Patch

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
index 00000000000..39e8c08cef9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-63.c
@@ -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" } } */
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 1463c1d4116..39de866a8ce 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -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);
 	}