aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-math-opts.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@redhat.com>2016-02-16 14:42:59 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2016-02-16 14:42:59 +0000
commit6d87c306c6a44f8db81a9a9f2f5de4d943d5e57f (patch)
treedbf7d36597ac5ae73d49e21deb2e911e80dc3d48 /gcc/tree-ssa-math-opts.c
parent8f3304d019bd1f9a8eb08b9dba3a430a59f52994 (diff)
downloadgcc-6d87c306c6a44f8db81a9a9f2f5de4d943d5e57f.zip
gcc-6d87c306c6a44f8db81a9a9f2f5de4d943d5e57f.tar.gz
gcc-6d87c306c6a44f8db81a9a9f2f5de4d943d5e57f.tar.bz2
Fix bswap optimization on big-endian (PR69714, 67781).
PR tree-optimization/69714 * tree-ssa-math-opts.c (find_bswap_or_nop): Revert previous change. Return NULL if we have irrelevant high bytes on BIG_ENDIAN. testsuite/ PR tree-optimization/69714 * gcc.dg/torture/pr69714.c: New test. From-SVN: r233452
Diffstat (limited to 'gcc/tree-ssa-math-opts.c')
-rw-r--r--gcc/tree-ssa-math-opts.c46
1 files changed, 17 insertions, 29 deletions
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 3aa4a07..2215b4d 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -2449,11 +2449,9 @@ 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. */
+ /* 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. */
uint64_t cmpxchg = CMPXCHG;
uint64_t cmpnop = CMPNOP;
@@ -2474,38 +2472,28 @@ 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)
- for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
- else
- rsize = n->range;
+ {
+ unsigned HOST_WIDE_INT rsize;
+ uint64_t tmpn;
- /* Zero out the bits corresponding to untouched bytes in original gimple
- expression. */
+ for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
+ if (BYTES_BIG_ENDIAN && n->range != rsize)
+ /* This implies an offset, which is currently not handled by
+ bswap_replace. */
+ return NULL;
+ n->range = rsize;
+ }
+
+ /* Zero out the extra bits of N and CMP*. */
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. */