]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/67781 (wrong code generated on big-endian with -O1 -fexpensiv...
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Fri, 8 Jan 2016 09:21:19 +0000 (09:21 +0000)
committerThomas Preud'homme <thopre01@gcc.gnu.org>
Fri, 8 Jan 2016 09:21:19 +0000 (09:21 +0000)
2016-01-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>

    gcc/
    PR tree-optimization/67781
    * tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg
    and cmpnop in two steps: first the ones not accessed in original
    gimple expression in a endian independent way and then the ones not
    accessed in the final result in an endian-specific way.

    gcc/testsuite/
    PR tree-optimization/67781
    * gcc.c-torture/execute/pr67781.c: New file.

From-SVN: r232154

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr67781.c [new file with mode: 0644]
gcc/tree-ssa-math-opts.c

index 5402c36b3783828c0fd8399c5faa42c05c6080f6..b9c6daf55fb5464dcbaed03ed352fc3f99286e06 100644 (file)
@@ -1,3 +1,11 @@
+2016-01-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       PR tree-optimization/67781
+       * tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg
+       and cmpnop in two steps: first the ones not accessed in original
+       gimple expression in a endian independent way and then the ones not
+       accessed in the final result in an endian-specific way.
+
 2016-01-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/69083
index 63a6e88f32ee324c1deacf72a4d1f2fbef235859..6b30af01e567b9ec71e0d38b4c1816f4f97f850d 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       PR tree-optimization/67781
+       * gcc.c-torture/execute/pr67781.c: New file.
+
 2016-01-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/69083
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr67781.c b/gcc/testsuite/gcc.c-torture/execute/pr67781.c
new file mode 100644 (file)
index 0000000..bf50aa2
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef __UINT32_TYPE__
+typedef __UINT32_TYPE__ uint32_t;
+#else
+typedef unsigned uint32_t;
+#endif
+
+#ifdef __UINT8_TYPE__
+typedef __UINT8_TYPE__ uint8_t;
+#else
+typedef unsigned char uint8_t;
+#endif
+
+struct
+{
+  uint32_t a;
+  uint8_t b;
+} s = { 0x123456, 0x78 };
+
+int pr67781()
+{
+  uint32_t c = (s.a << 8) | s.b;
+  return c;
+}
+
+int
+main ()
+{
+  if (sizeof (uint32_t) * __CHAR_BIT__ != 32)
+    return 0;
+
+  if (pr67781 () != 0x12345678)
+    __builtin_abort ();
+  return 0;
+}
index 90baaac9fb02190418701ac1175d9445fc423c4e..abd77e76dce4e90f49dec2a7522ecd6894bb7457 100644 (file)
@@ -2449,6 +2449,8 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit)
 static gimple *
 find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap)
 {
+  unsigned rsize;
+  uint64_t tmpn, mask;
 /* The number which the find_bswap_or_nop_1 result should match in order
    to have a full byte swap.  The number is shifted to the right
    according to the size of the symbolic number before using it.  */
@@ -2472,24 +2474,38 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap)
 
   /* Find real size of result (highest non-zero byte).  */
   if (n->base_addr)
-    {
-      int rsize;
-      uint64_t tmpn;
-
-      for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
-      n->range = rsize;
-    }
+    for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
+  else
+    rsize = n->range;
 
-  /* Zero out the extra bits of N and CMP*.  */
+  /* Zero out the bits corresponding to untouched bytes in original gimple
+     expression.  */
   if (n->range < (int) sizeof (int64_t))
     {
-      uint64_t mask;
-
       mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1;
       cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER;
       cmpnop &= mask;
     }
 
+  /* Zero out the bits corresponding to unused bytes in the result of the
+     gimple expression.  */
+  if (rsize < n->range)
+    {
+      if (BYTES_BIG_ENDIAN)
+       {
+         mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1;
+         cmpxchg &= mask;
+         cmpnop >>= (n->range - rsize) * BITS_PER_MARKER;
+       }
+      else
+       {
+         mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1;
+         cmpxchg >>= (n->range - rsize) * BITS_PER_MARKER;
+         cmpnop &= mask;
+       }
+      n->range = rsize;
+    }
+
   /* A complete byte swap should make the symbolic number to start with
      the largest digit in the highest order byte. Unchanged symbolic
      number indicates a read with same endianness as target architecture.  */