re PR tree-optimization/79737 (wrong code at -O2 and -O3 on x86_64-linux-gnu (in...
authorJakub Jelinek <jakub@redhat.com>
Tue, 28 Feb 2017 22:39:11 +0000 (23:39 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 28 Feb 2017 22:39:11 +0000 (23:39 +0100)
PR tree-optimization/79737
* gimple-ssa-store-merging.c (encode_tree_to_bitpos): If bitlen is
a multiple of BITS_PER_UNIT and !BYTES_BIG_ENDIAN, clear
tmpbuf[byte_size - 1].  Call natice_encode_expr with byte_size - 1
instead of byte_size.  Formatting fix.
(shift_bytes_in_array_right): Formatting fix.

* gcc.c-torture/execute/pr79737-1.c: New test.
* gcc.c-torture/execute/pr79737-2.c: New test.

From-SVN: r245795

gcc/ChangeLog
gcc/gimple-ssa-store-merging.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr79737-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr79737-2.c [new file with mode: 0644]

index 51cb8abc1d28729c0bab3ed4962eb6cb3f8b60f0..dc29c09fd9069c48cc7674b5873fd1d529046451 100644 (file)
@@ -1,3 +1,12 @@
+2017-02-28  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/79737
+       * gimple-ssa-store-merging.c (encode_tree_to_bitpos): If bitlen is
+       a multiple of BITS_PER_UNIT and !BYTES_BIG_ENDIAN, clear
+       tmpbuf[byte_size - 1].  Call natice_encode_expr with byte_size - 1
+       instead of byte_size.  Formatting fix.
+       (shift_bytes_in_array_right): Formatting fix.
+
 2017-02-28  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR target/79749
index c59fdcbdf382ca014fad059147d83df72b45fc4d..17ac94ab2a7b696add647b33f11a47378612afd1 100644 (file)
@@ -253,9 +253,9 @@ shift_bytes_in_array_right (unsigned char *ptr, unsigned int sz,
       unsigned prev_carry_over = carry_over;
       carry_over = ptr[i] & carry_mask;
 
-     carry_over <<= (unsigned char) BITS_PER_UNIT - amnt;
-     ptr[i] >>= amnt;
-     ptr[i] |= prev_carry_over;
+      carry_over <<= (unsigned char) BITS_PER_UNIT - amnt;
+      ptr[i] >>= amnt;
+      ptr[i] |= prev_carry_over;
     }
 }
 
@@ -352,8 +352,9 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos,
 {
   unsigned int first_byte = bitpos / BITS_PER_UNIT;
   tree tmp_int = expr;
-  bool sub_byte_op_p = (bitlen % BITS_PER_UNIT) || (bitpos % BITS_PER_UNIT)
-                       || mode_for_size (bitlen, MODE_INT, 0) == BLKmode;
+  bool sub_byte_op_p = ((bitlen % BITS_PER_UNIT)
+                       || (bitpos % BITS_PER_UNIT)
+                       || mode_for_size (bitlen, MODE_INT, 0) == BLKmode);
 
   if (!sub_byte_op_p)
     return (native_encode_expr (tmp_int, ptr + first_byte, total_bytes, 0)
@@ -407,7 +408,7 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos,
   memset (tmpbuf, '\0', byte_size);
   /* The store detection code should only have allowed constants that are
      accepted by native_encode_expr.  */
-  if (native_encode_expr (expr, tmpbuf, byte_size, 0) == 0)
+  if (native_encode_expr (expr, tmpbuf, byte_size - 1, 0) == 0)
     gcc_unreachable ();
 
   /* The native_encode_expr machinery uses TYPE_MODE to determine how many
@@ -418,25 +419,27 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos,
      contain a sign bit due to sign-extension).  */
   unsigned int padding
     = byte_size - ROUND_UP (bitlen, BITS_PER_UNIT) / BITS_PER_UNIT - 1;
-  if (padding != 0
-      || bitlen % BITS_PER_UNIT != 0)
+  /* On big-endian the padding is at the 'front' so just skip the initial
+     bytes.  */
+  if (BYTES_BIG_ENDIAN)
+    tmpbuf += padding;
+
+  byte_size -= padding;
+
+  if (bitlen % BITS_PER_UNIT != 0)
     {
-      /* On big-endian the padding is at the 'front' so just skip the initial
-        bytes.  */
       if (BYTES_BIG_ENDIAN)
-       tmpbuf += padding;
-
-      byte_size -= padding;
-      if (bitlen % BITS_PER_UNIT != 0)
-       {
-         if (BYTES_BIG_ENDIAN)
-           clear_bit_region_be (tmpbuf, BITS_PER_UNIT - 1,
-                                BITS_PER_UNIT - (bitlen % BITS_PER_UNIT));
-         else
-           clear_bit_region (tmpbuf, bitlen,
-                             byte_size * BITS_PER_UNIT - bitlen);
-       }
+       clear_bit_region_be (tmpbuf, BITS_PER_UNIT - 1,
+                            BITS_PER_UNIT - (bitlen % BITS_PER_UNIT));
+      else
+       clear_bit_region (tmpbuf, bitlen,
+                         byte_size * BITS_PER_UNIT - bitlen);
     }
+  /* Left shifting relies on the last byte being clear if bitlen is
+     a multiple of BITS_PER_UNIT, which might not be clear if
+     there are padding bytes.  */
+  else if (!BYTES_BIG_ENDIAN)
+    tmpbuf[byte_size - 1] = '\0';
 
   /* Clear the bit region in PTR where the bits from TMPBUF will be
      inserted into.  */
index 4aab63a4e5d7f42f4ccf3897f63be979c6cbfaf7..483e9030905ddfb73b11b56ceed54e94435a84ce 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-28  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/79737
+       * gcc.c-torture/execute/pr79737-1.c: New test.
+       * gcc.c-torture/execute/pr79737-2.c: New test.
+
 2017-02-28  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.target/sparc/20170228-1.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr79737-1.c b/gcc/testsuite/gcc.c-torture/execute/pr79737-1.c
new file mode 100644 (file)
index 0000000..05e392c
--- /dev/null
@@ -0,0 +1,37 @@
+/* PR tree-optimization/79737 */
+
+#pragma pack(1)
+struct S
+{
+  int b:18;
+  int c:1;
+  int d:24;
+  int e:15;
+  int f:14;
+} i;
+int g, j, k;
+static struct S h;
+
+void
+foo ()
+{
+  for (j = 0; j < 6; j++)
+    k = 0;
+  for (; k < 3; k++)
+    {
+      struct S m = { 5, 0, -5, 9, 5 };
+      h = m;
+      if (g)
+       i = m;
+      h.e = 0;
+    }
+}
+
+int
+main ()
+{
+  foo ();
+  if (h.e != 0)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr79737-2.c b/gcc/testsuite/gcc.c-torture/execute/pr79737-2.c
new file mode 100644 (file)
index 0000000..37b991e
--- /dev/null
@@ -0,0 +1,41 @@
+/* PR tree-optimization/79737 */
+
+#pragma pack(1)
+struct S
+{
+  int b:18;
+  int c:1;
+  int d:24;
+  int e:15;
+  int f:14;
+} i, j;
+
+void
+foo ()
+{
+  i.e = 0;
+  i.b = 5;
+  i.c = 0;
+  i.d = -5;
+  i.f = 5;
+}
+
+void
+bar ()
+{
+  j.b = 5;
+  j.c = 0;
+  j.d = -5;
+  j.e = 0;
+  j.f = 5;
+}
+
+int
+main ()
+{
+  foo ();
+  bar ();
+  asm volatile ("" : : : "memory");
+  if (i.b != j.b || i.c != j.c || i.d != j.d || i.e != j.e || i.f != j.f)
+    __builtin_abort ();
+}