Removes the restriction on the rotation amount having to be a multiple
of 8, which allows recognizing slightly more complicated bswap+rotation.

gcc/ChangeLog:

        * gimple-ssa-store-merging.cc (do_shift_rotate): Relax rotation
        constraints to allow for non-multiple of 8 rotations.
        (find_bswap_or_nop_1): Relax mask constraints similarly.
        (find_bswap_or_nop): Relax rotation amount contraints too.

gcc/testsuite/ChangeLog:

        * gcc.dg/optimize-bswapsi-8.c: New test.

Signed-off-by: David Guillen Fandos <[email protected]>
---
 gcc/gimple-ssa-store-merging.cc           | 23 +++++++----------------
 gcc/testsuite/gcc.dg/optimize-bswapsi-8.c | 21 +++++++++++++++++++++
 2 files changed, 28 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/optimize-bswapsi-8.c

diff --git a/gcc/gimple-ssa-store-merging.cc b/gcc/gimple-ssa-store-merging.cc
index 9de8e4be1cf..922304cae50 100644
--- a/gcc/gimple-ssa-store-merging.cc
+++ b/gcc/gimple-ssa-store-merging.cc
@@ -271,8 +271,7 @@ do_shift_rotate (enum tree_code code,
 
   if (size > MAX_SYM_BITS
       || count < 0
-      || count >= size
-      || count % BITS_PER_UNIT != 0)
+      || count >= size)
     return false;
 
   switch (code)
@@ -282,10 +281,9 @@ do_shift_rotate (enum tree_code code,
        newv[i] = i < count ? 0 : n->n[i - count];
       break;
     case RSHIFT_EXPR:
-      /* Arithmetic shift of signed type: result is dependent on the value.  */
+      /* Arithmetic shift of signed type: propagate sign bit..  */
       {
-       uint8_t fillv = (TYPE_UNSIGNED (n->type) || n->n[size - 1] == 0)
-                       ? 0 : MARKER_BIT_UNKNOWN;
+       uint8_t fillv = TYPE_UNSIGNED (n->type) ? 0 : n->n[size - 1];
        for (i = 0; i < size; i++)
          newv[i] = (i + count < size) ? n->n[i + count] : fillv;
       }
@@ -678,12 +676,6 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number 
*n, int limit)
          {
            int i, size = TYPE_PRECISION (n->type);
            uint64_t val = int_cst_value (rhs2);
-           uint64_t tmp = (1 << BITS_PER_UNIT) - 1;
-
-           /* Only constants masking full bytes are allowed.  */
-           for (i = 0; i < size; i += BITS_PER_UNIT, tmp <<= BITS_PER_UNIT)
-             if ((val & tmp) != 0 && (val & tmp) != tmp)
-               return NULL;
 
            for (i = 0; i < size; i++)
              if (((val >> i) & 1) == 0)
@@ -709,13 +701,12 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number 
*n, int limit)
            if (type_size > MAX_SYM_BITS)
              return NULL;
 
-           /* Sign extension: result is dependent on the value.  */
+           /* Sign extension: propagate MSB if necessary.  */
            old_type_size = TYPE_PRECISION (n->type);
            if (type_size > old_type_size)
              for (i = old_type_size; i < type_size; i++)
-               n->n[i] = (TYPE_UNSIGNED (n->type)
-                          || n->n[old_type_size - 1] == 0)
-                         ? 0 : MARKER_BIT_UNKNOWN;
+               n->n[i] = TYPE_UNSIGNED (n->type)
+                         ? 0 : n->n[old_type_size - 1];
            else
              for (i = type_size; i < old_type_size; i++)
                n->n[i] = 0;
@@ -1114,7 +1105,7 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number 
*n, bool *bswap,
              break;
            }
 
-         if (!count || count % BITS_PER_UNIT != 0)
+         if (!count)
            return NULL;
 
          memcpy (tmp2_n, tmp_n, MAX_SYM_BITS);
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-8.c 
b/gcc/testsuite/gcc.dg/optimize-bswapsi-8.c
new file mode 100644
index 00000000000..f24706e1c80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/optimize-bswapsi-8.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Test bswap + arbitrary rotation (not just multiple of 8).  */
+
+#include <stdint.h>
+
+uint32_t
+swap_and_rotate (uint32_t a)
+{
+  return (a & 0x000000FF) << 23 |
+         (a & 0x0000FF00) << 7  |
+         (a & 0x00FF0000) >> 9  |
+         (a & 0xFE000000) >> 25 |
+         (a & 0x01000000) << 7;
+}
+
+/* { dg-final { scan-tree-dump-times "= __builtin_bswap32 \\\(" 1 "optimized" 
} } */
+/* { dg-final { scan-tree-dump-times " r>> 1;" 1 "optimized" } } */
-- 
2.55.0

Reply via email to