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