[gcc(refs/users/marxin/heads/marxin-gcc-benchmark-branch)] sccvn: Handle non-byte aligned offset or size for memset (, 123, ) [PR93945]

Martin Liska marxin@gcc.gnu.org
Mon Mar 30 10:24:50 GMT 2020


https://gcc.gnu.org/g:5f9cd512c4278621435cce486dd00248ea2e821c

commit 5f9cd512c4278621435cce486dd00248ea2e821c
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Feb 27 10:12:52 2020 +0100

    sccvn: Handle non-byte aligned offset or size for memset (, 123, ) [PR93945]
    
    The following is the last spot in vn_reference_lookup_3 that didn't allow
    non-byte aligned offsets or sizes.  To be precise, it did allow size that
    wasn't multiple of byte size and that caused a wrong-code issue on
    big-endian, as the pr93945.c testcase shows, so for GCC 9 we should add
    && multiple_p (ref->size, BITS_PER_UNIT) check instead.
    For the memset with SSA_NAME middle-argument, it still requires byte-aligned
    offset, as we'd otherwise need to rotate the value at runtime.
    
    2020-02-27  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/93582
            PR tree-optimization/93945
            * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle memset with
            non-zero INTEGER_CST second argument and ref->offset or ref->size
            not a multiple of BITS_PER_UNIT.
    
            * gcc.dg/tree-ssa/pr93582-9.c: New test.
            * gcc.c-torture/execute/pr93945.c: New test.

Diff:
---
 gcc/ChangeLog                                 |  8 +++++
 gcc/testsuite/ChangeLog                       |  7 +++++
 gcc/testsuite/gcc.c-torture/execute/pr93945.c | 45 +++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c     | 23 ++++++++++++++
 gcc/tree-ssa-sccvn.c                          | 42 +++++++++++++++++++++----
 5 files changed, 119 insertions(+), 6 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9665bd11dc7..38bfbb95474 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2020-02-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR tree-optimization/93582
+	PR tree-optimization/93945
+	* tree-ssa-sccvn.c (vn_reference_lookup_3): Handle memset with
+	non-zero INTEGER_CST second argument and ref->offset or ref->size
+	not a multiple of BITS_PER_UNIT.
+
 2020-02-27  Jonathan Wakely  <jwakely@redhat.com>
 
 	* doc/install.texi (Binaries): Update description of BullFreeware.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 085537d977b..70897c5f94c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2020-02-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR tree-optimization/93582
+	PR tree-optimization/93945
+	* gcc.dg/tree-ssa/pr93582-9.c: New test.
+	* gcc.c-torture/execute/pr93945.c: New test.
+
 2020-02-26  Marek Polacek  <polacek@redhat.com>
 
 	PR c++/93789 - ICE with invalid array bounds.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr93945.c b/gcc/testsuite/gcc.c-torture/execute/pr93945.c
new file mode 100644
index 00000000000..99e455cce52
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr93945.c
@@ -0,0 +1,45 @@
+/* PR tree-optimization/93945 */
+
+union U { char a[8]; struct S { unsigned int b : 8, c : 13, d : 11; } e; } u;
+
+__attribute__((noipa)) int
+foo (void)
+{
+  __builtin_memset (&u.a, 0xf4, sizeof (u.a));
+  return u.e.c;
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+  asm volatile ("" : : "g" (&u) : "memory");
+  return u.e.c;
+}
+
+__attribute__((noipa)) int
+baz (void)
+{
+  __builtin_memset (&u.a, 0xf4, sizeof (u.a));
+  return u.e.d;
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+  asm volatile ("" : : "g" (&u) : "memory");
+  return u.e.d;
+}
+
+int
+main ()
+{
+  int a = foo ();
+  int b = bar ();
+  if (a != b)
+    __builtin_abort ();
+  a = baz ();
+  b = qux ();
+  if (a != b)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c
new file mode 100644
index 00000000000..b6ad46516fd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93582-9.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/93582 */
+/* { dg-do compile { target int32 } } */
+/* { dg-options "-O2 -fdump-tree-fre1" } */
+/* { dg-final { scan-tree-dump "return 5364;" "fre1" { target le } } } */
+/* { dg-final { scan-tree-dump "return 7838;" "fre1" { target be } } } */
+/* { dg-final { scan-tree-dump "return 1959;" "fre1" { target le } } } */
+/* { dg-final { scan-tree-dump "return 1268;" "fre1" { target be } } } */
+
+union U { char a[8]; struct S { unsigned int b : 8, c : 13, d : 11; } e; } u;
+
+__attribute__((noipa)) int
+foo (void)
+{
+  __builtin_memset (&u.a, 0xf4, sizeof (u.a));
+  return u.e.c;
+}
+
+__attribute__((noipa)) int
+baz (void)
+{
+  __builtin_memset (&u.a, 0xf4, sizeof (u.a));
+  return u.e.d;
+}
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index a3fba2878f8..0487f59f13f 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -2386,7 +2386,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
   vn_reference_t vr = data->vr;
   gimple *def_stmt = SSA_NAME_DEF_STMT (vuse);
   tree base = ao_ref_base (ref);
-  HOST_WIDE_INT offseti, maxsizei;
+  HOST_WIDE_INT offseti = 0, maxsizei, sizei = 0;
   static vec<vn_reference_op_s> lhs_ops;
   ao_ref lhs_ref;
   bool lhs_ref_ok = false;
@@ -2541,9 +2541,13 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
       && (integer_zerop (gimple_call_arg (def_stmt, 1))
 	  || ((TREE_CODE (gimple_call_arg (def_stmt, 1)) == INTEGER_CST
 	       || (INTEGRAL_TYPE_P (vr->type) && known_eq (ref->size, 8)))
-	      && CHAR_BIT == 8 && BITS_PER_UNIT == 8
+	      && CHAR_BIT == 8
+	      && BITS_PER_UNIT == 8
+	      && BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN
 	      && offset.is_constant (&offseti)
-	      && offseti % BITS_PER_UNIT == 0))
+	      && ref->size.is_constant (&sizei)
+	      && (offseti % BITS_PER_UNIT == 0
+		  || TREE_CODE (gimple_call_arg (def_stmt, 1)) == INTEGER_CST)))
       && 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)) == SSA_NAME))
@@ -2604,7 +2608,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
       else
 	return (void *)-1;
       tree len = gimple_call_arg (def_stmt, 2);
-      HOST_WIDE_INT leni, offset2i, offseti;
+      HOST_WIDE_INT leni, offset2i;
       /* Sometimes the above trickery is smarter than alias analysis.  Take
          advantage of that.  */
       if (!ranges_maybe_overlap_p (offset, maxsize, offset2,
@@ -2618,7 +2622,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
 	  tree val;
 	  if (integer_zerop (gimple_call_arg (def_stmt, 1)))
 	    val = build_zero_cst (vr->type);
-	  else if (INTEGRAL_TYPE_P (vr->type) && known_eq (ref->size, 8))
+	  else if (INTEGRAL_TYPE_P (vr->type)
+		   && known_eq (ref->size, 8)
+		   && offseti % BITS_PER_UNIT == 0)
 	    {
 	      gimple_match_op res_op (gimple_match_cond::UNCOND, NOP_EXPR,
 				      vr->type, gimple_call_arg (def_stmt, 1));
@@ -2630,10 +2636,34 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
 	    }
 	  else
 	    {
-	      unsigned buflen = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (vr->type));
+	      unsigned buflen = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (vr->type)) + 1;
+	      if (INTEGRAL_TYPE_P (vr->type))
+		buflen = GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (vr->type)) + 1;
 	      unsigned char *buf = XALLOCAVEC (unsigned char, buflen);
 	      memset (buf, TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 1)),
 		      buflen);
+	      if (BYTES_BIG_ENDIAN)
+		{
+		  unsigned int amnt
+		    = (((unsigned HOST_WIDE_INT) offseti + sizei)
+		       % BITS_PER_UNIT);
+		  if (amnt)
+		    {
+		      shift_bytes_in_array_right (buf, buflen,
+						  BITS_PER_UNIT - amnt);
+		      buf++;
+		      buflen--;
+		    }
+		}
+	      else if (offseti % BITS_PER_UNIT != 0)
+		{
+		  unsigned int amnt
+		    = BITS_PER_UNIT - ((unsigned HOST_WIDE_INT) offseti
+				       % BITS_PER_UNIT);
+		  shift_bytes_in_array_left (buf, buflen, amnt);
+		  buf++;
+		  buflen--;
+		}
 	      val = native_interpret_expr (vr->type, buf, buflen);
 	      if (!val)
 		return (void *)-1;


More information about the Gcc-cvs mailing list