re PR tree-optimization/63266 (Test regression: gcc.target/sh/pr53568-1.c)
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Wed, 24 Sep 2014 08:27:21 +0000 (08:27 +0000)
committerThomas Preud'homme <thopre01@gcc.gnu.org>
Wed, 24 Sep 2014 08:27:21 +0000 (08:27 +0000)
2014-09-24  Thomas Preud'homme  <thomas.preudhomme@arm.com>

    gcc/
    PR tree-optimization/63266
    * tree-ssa-math-opts.c (struct symbolic_number): Add comment about
    marker for unknown byte value.
    (MARKER_MASK): New macro.
    (MARKER_BYTE_UNKNOWN): New macro.
    (HEAD_MARKER): New macro.
    (do_shift_rotate): Mark bytes with unknown values due to sign
    extension when doing an arithmetic right shift. Replace hardcoded
    mask for marker by new MARKER_MASK macro.
    (find_bswap_or_nop_1): Likewise and adjust ORing of two symbolic
    numbers accordingly.

    gcc/testsuite/
    PR tree-optimization/63266
    * gcc.dg/optimize-bswapsi-1.c (swap32_d): New bswap pass test.

From-SVN: r215546

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/optimize-bswapsi-1.c
gcc/tree-ssa-math-opts.c

index c227481021c2e54bf92975d3816b4414b53d36fa..d5f1b1ba5993fe6d5c46018081226be32adb58c9 100644 (file)
@@ -1,3 +1,17 @@
+2014-09-24  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       PR tree-optimization/63266
+       * tree-ssa-math-opts.c (struct symbolic_number): Add comment about
+       marker for unknown byte value.
+       (MARKER_MASK): New macro.
+       (MARKER_BYTE_UNKNOWN): New macro.
+       (HEAD_MARKER): New macro.
+       (do_shift_rotate): Mark bytes with unknown values due to sign
+       extension when doing an arithmetic right shift. Replace hardcoded
+       mask for marker by new MARKER_MASK macro.
+       (find_bswap_or_nop_1): Likewise and adjust ORing of two symbolic
+       numbers accordingly.
+
 2014-09-24  Alexander Ivchenko  <alexander.ivchenko@intel.com>
            Maxim Kuznetsov  <maxim.kuznetsov@intel.com>
            Anna Tikhonova  <anna.tikhonova@intel.com>
index a3f51b36d7e1e97eddbd19ae7e44e8e6de8ab36b..69d9b3d12c0d5d9496d10ef461682453ad7ac861 100644 (file)
@@ -1,3 +1,8 @@
+2014-09-24  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       PR tree-optimization/63266
+       * gcc.dg/optimize-bswapsi-1.c (swap32_d): New bswap pass test.
+
 2014-09-24  Zhenqiang Chen  <zhenqiang.chen@arm.com>
 
        * gcc.target/arm/pr63210.c: New test.
index ebfca6077b9f33e7118fed829e3aecea529ec318..580e6e0fee2cc5ffbe14f5e688bb86bd66abcbc5 100644 (file)
@@ -49,5 +49,20 @@ swap32_c (SItype u)
          | (((u) & 0x000000ff) << 24));
 }
 
-/* { dg-final { scan-tree-dump-times "32 bit bswap implementation found at" 3 "bswap" } } */
+/* This variant comes from gcc.target/sh/pr53568-1.c.  It requires to track
+   which bytes have an unpredictable value (eg. due to sign extension) to
+   make sure that the final expression have only well defined byte values.  */
+
+SItype
+swap32_d (SItype in)
+{
+  /* 1x swap.w
+     2x swap.b  */
+  return (((in >> 0) & 0xFF) << 24)
+        | (((in >> 8) & 0xFF) << 16)
+        | (((in >> 16) & 0xFF) << 8)
+        | (((in >> 24) & 0xFF) << 0);
+}
+
+/* { dg-final { scan-tree-dump-times "32 bit bswap implementation found at" 4 "bswap" } } */
 /* { dg-final { cleanup-tree-dump "bswap" } } */
index c1c2c82e9aecc3ea3f6fe33a82935744a4054069..3c6e9355fff6fa33f69ea5bb1b0d808f8bf5043e 100644 (file)
@@ -1603,6 +1603,7 @@ make_pass_cse_sincos (gcc::context *ctxt)
    consisting of octet sized markers:
 
    0    - target byte has the value 0
+   FF   - target byte has an unknown value (eg. due to sign extension)
    1..size - marker value is the target byte index minus one.
 
    To detect permutations on memory sources (arrays and structures), a symbolic
@@ -1629,6 +1630,10 @@ struct symbolic_number {
 };
 
 #define BITS_PER_MARKER 8
+#define MARKER_MASK ((1 << BITS_PER_MARKER) - 1)
+#define MARKER_BYTE_UNKNOWN MARKER_MASK
+#define HEAD_MARKER(n, size) \
+  ((n) & ((uint64_t) MARKER_MASK << (((size) - 1) * BITS_PER_MARKER)))
 
 /* The number which the find_bswap_or_nop_1 result should match in
    order to have a nop.  The number is masked according to the size of
@@ -1651,7 +1656,8 @@ do_shift_rotate (enum tree_code code,
                 struct symbolic_number *n,
                 int count)
 {
-  int size = TYPE_PRECISION (n->type) / BITS_PER_UNIT;
+  int i, size = TYPE_PRECISION (n->type) / BITS_PER_UNIT;
+  unsigned head_marker;
 
   if (count % BITS_PER_UNIT != 0)
     return false;
@@ -1668,11 +1674,13 @@ do_shift_rotate (enum tree_code code,
       n->n <<= count;
       break;
     case RSHIFT_EXPR:
-      /* Arithmetic shift of signed type: result is dependent on the value.  */
-      if (!TYPE_UNSIGNED (n->type)
-         && (n->n & ((uint64_t) 0xff << ((size - 1) * BITS_PER_MARKER))))
-       return false;
+      head_marker = HEAD_MARKER (n->n, size);
       n->n >>= count;
+      /* Arithmetic shift of signed type: result is dependent on the value.  */
+      if (!TYPE_UNSIGNED (n->type) && head_marker)
+       for (i = 0; i < count / BITS_PER_MARKER; i++)
+         n->n |= (uint64_t) MARKER_BYTE_UNKNOWN
+                 << ((size - 1 - i) * BITS_PER_MARKER);
       break;
     case LROTATE_EXPR:
       n->n = (n->n << count) | (n->n >> ((size * BITS_PER_MARKER) - count));
@@ -1878,7 +1886,7 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
              if ((val & tmp) != 0 && (val & tmp) != tmp)
                return NULL;
              else if (val & tmp)
-               mask |= (uint64_t) 0xff << (i * BITS_PER_MARKER);
+               mask |= (uint64_t) MARKER_MASK << (i * BITS_PER_MARKER);
 
            n->n &= mask;
          }
@@ -1892,7 +1900,7 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
          break;
        CASE_CONVERT:
          {
-           int type_size, old_type_size;
+           int i, type_size, old_type_size;
            tree type;
 
            type = gimple_expr_type (stmt);
@@ -1905,11 +1913,10 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
 
            /* Sign extension: result is dependent on the value.  */
            old_type_size = TYPE_PRECISION (n->type) / BITS_PER_UNIT;
-           if (!TYPE_UNSIGNED (n->type)
-               && type_size > old_type_size
-               && n->n & ((uint64_t) 0xff << ((old_type_size - 1)
-                                              * BITS_PER_MARKER)))
-             return NULL;
+           if (!TYPE_UNSIGNED (n->type) && type_size > old_type_size
+               && HEAD_MARKER (n->n, old_type_size))
+             for (i = 0; i < type_size - old_type_size; i++)
+               n->n |= MARKER_BYTE_UNKNOWN << (type_size - 1 - i);
 
            if (type_size < 64 / BITS_PER_MARKER)
              {
@@ -1968,7 +1975,7 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
          if (gimple_assign_rhs1 (source_stmt1)
              != gimple_assign_rhs1 (source_stmt2))
            {
-             int64_t inc, mask;
+             int64_t inc;
              HOST_WIDE_INT off_sub;
              struct symbolic_number *n_ptr;
 
@@ -2002,15 +2009,15 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
                 bigger weight according to target endianness.  */
              inc = BYTES_BIG_ENDIAN ? off_sub + n2.range - n1.range : off_sub;
              size = TYPE_PRECISION (n1.type) / BITS_PER_UNIT;
-             mask = 0xff;
              if (BYTES_BIG_ENDIAN)
                n_ptr = &n1;
              else
                n_ptr = &n2;
-             for (i = 0; i < size; i++, inc <<= BITS_PER_MARKER,
-                                        mask <<= BITS_PER_MARKER)
+             for (i = 0; i < size; i++, inc <<= BITS_PER_MARKER)
                {
-                 if (n_ptr->n & mask)
+                 unsigned marker =
+                   (n_ptr->n >> (i * BITS_PER_MARKER)) & MARKER_MASK;
+                 if (marker && marker != MARKER_BYTE_UNKNOWN)
                    n_ptr->n += inc;
                }
            }
@@ -2028,7 +2035,8 @@ find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
          n->bytepos = n1.bytepos;
          n->type = n1.type;
          size = TYPE_PRECISION (n->type) / BITS_PER_UNIT;
-         for (i = 0, mask = 0xff; i < size; i++, mask <<= BITS_PER_MARKER)
+         for (i = 0, mask = MARKER_MASK; i < size;
+              i++, mask <<= BITS_PER_MARKER)
            {
              uint64_t masked1, masked2;