diff options
author | Bernd Schmidt <bernds@redhat.com> | 2016-02-16 14:42:59 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2016-02-16 14:42:59 +0000 |
commit | 6d87c306c6a44f8db81a9a9f2f5de4d943d5e57f (patch) | |
tree | dbf7d36597ac5ae73d49e21deb2e911e80dc3d48 /gcc/tree-ssa-math-opts.c | |
parent | 8f3304d019bd1f9a8eb08b9dba3a430a59f52994 (diff) | |
download | gcc-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.c | 46 |
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. */ |