diff options
author | Thomas Preud'homme <thomas.preudhomme@arm.com> | 2016-01-08 09:21:19 +0000 |
---|---|---|
committer | Thomas Preud'homme <thopre01@gcc.gnu.org> | 2016-01-08 09:21:19 +0000 |
commit | 80e9b3aaac461dac31b8a3990ac6e820d5bce54d (patch) | |
tree | d1c49541c8f65f13e5506de1ce8fd3b3535f1404 | |
parent | 262a363ff9f03262fe5a8420fa53bd10cb4306d6 (diff) | |
download | gcc-80e9b3aaac461dac31b8a3990ac6e820d5bce54d.zip gcc-80e9b3aaac461dac31b8a3990ac6e820d5bce54d.tar.gz gcc-80e9b3aaac461dac31b8a3990ac6e820d5bce54d.tar.bz2 |
re PR tree-optimization/67781 (wrong code generated on big-endian with -O1 -fexpensive-optimizations)
2016-01-08 Thomas Preud'homme <thomas.preudhomme@arm.com>
gcc/
PR tree-optimization/67781
* tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg
and cmpnop in two steps: first the ones not accessed in original
gimple expression in a endian independent way and then the ones not
accessed in the final result in an endian-specific way.
gcc/testsuite/
PR tree-optimization/67781
* gcc.c-torture/execute/pr67781.c: New file.
From-SVN: r232154
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr67781.c | 34 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 36 |
4 files changed, 73 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5402c36..b9c6daf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-01-08 Thomas Preud'homme <thomas.preudhomme@arm.com> + + PR tree-optimization/67781 + * tree-ssa-math-opts.c (find_bswap_or_nop): Zero out bytes in cmpxchg + and cmpnop in two steps: first the ones not accessed in original + gimple expression in a endian independent way and then the ones not + accessed in the final result in an endian-specific way. + 2016-01-08 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/69083 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 63a6e88..6b30af0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-01-08 Thomas Preud'homme <thomas.preudhomme@arm.com> + + PR tree-optimization/67781 + * gcc.c-torture/execute/pr67781.c: New file. + 2016-01-08 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/69083 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr67781.c b/gcc/testsuite/gcc.c-torture/execute/pr67781.c new file mode 100644 index 0000000..bf50aa2 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr67781.c @@ -0,0 +1,34 @@ +#ifdef __UINT32_TYPE__ +typedef __UINT32_TYPE__ uint32_t; +#else +typedef unsigned uint32_t; +#endif + +#ifdef __UINT8_TYPE__ +typedef __UINT8_TYPE__ uint8_t; +#else +typedef unsigned char uint8_t; +#endif + +struct +{ + uint32_t a; + uint8_t b; +} s = { 0x123456, 0x78 }; + +int pr67781() +{ + uint32_t c = (s.a << 8) | s.b; + return c; +} + +int +main () +{ + if (sizeof (uint32_t) * __CHAR_BIT__ != 32) + return 0; + + if (pr67781 () != 0x12345678) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 90baaac..abd77e7 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2449,6 +2449,8 @@ 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. */ @@ -2472,24 +2474,38 @@ 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) - { - int rsize; - uint64_t tmpn; - - for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++); - n->range = rsize; - } + for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++); + else + rsize = n->range; - /* Zero out the extra bits of N and CMP*. */ + /* Zero out the bits corresponding to untouched bytes in original gimple + expression. */ 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. */ |