Allow any masking to a bswap operation, as long as it involves more than
one byte.

gcc/ChangeLog:

        * gimple-ssa-store-merging.cc (is_bswap_or_nop_p): Relax masking
        restrictions to any mask.

gcc/testsuite/ChangeLog:

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

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

diff --git a/gcc/gimple-ssa-store-merging.cc b/gcc/gimple-ssa-store-merging.cc
index 922304cae50..b749c3c51e9 100644
--- a/gcc/gimple-ssa-store-merging.cc
+++ b/gcc/gimple-ssa-store-merging.cc
@@ -1009,7 +1009,6 @@ is_bswap_or_nop_p (const uint8_t *n, const uint8_t 
*cmpxchg,
                   const uint8_t *cmpnop, uint64_t* mask,
                   bool* bswap)
 {
-  const uint64_t byte_mask = ((uint64_t) 1 << BITS_PER_UNIT) - 1;
   *mask = ~(uint64_t) 0;
   if (memcmp (n, cmpnop, MAX_SYM_BITS) == 0)
     *bswap = false;
@@ -1018,15 +1017,15 @@ is_bswap_or_nop_p (const uint8_t *n, const uint8_t 
*cmpxchg,
   else
     {
       int set = 0;
-      for (unsigned int i = 0; i < MAX_SYM_BITS; i += BITS_PER_UNIT)
-       if (sym_is_range_zero (n, i, BITS_PER_UNIT))
-         *mask &= ~(byte_mask << i);
-       else if (memcmp (&n[i], &cmpxchg[i], BITS_PER_UNIT) == 0)
+      for (unsigned int i = 0; i < MAX_SYM_BITS; i++)
+       if (n[i] == 0)
+         *mask &= ~((uint64_t) 1 << i);
+       else if (n[i] == cmpxchg[i])
          set++;
        else
          return false;
 
-      if (set < 2)
+      if (set < 2 * BITS_PER_UNIT)
        return false;
       *bswap = true;
     }
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-9.c 
b/gcc/testsuite/gcc.dg/optimize-bswapsi-9.c
new file mode 100644
index 00000000000..9092f538c09
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/optimize-bswapsi-9.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Test bswap + masking, where the mask is (almost) arbitrary.  */
+
+#include <stdint.h>
+
+uint32_t
+partial_swap (uint32_t a)
+{
+  a = (a & 0x000000C3) << 24 |
+      (a & 0x0000F000) << 8  |
+      (a & 0x003F0000) >> 8  |
+      (a & 0x7F000000) >> 24;
+  return a;
+}
+
+/* { dg-final { scan-tree-dump-times "= __builtin_bswap32 \\\(" 1 "optimized" 
} } */
-- 
2.55.0

Reply via email to