diff options
author | Charles Baylis <charles.baylis@linaro.org> | 2016-01-27 15:38:45 +0000 |
---|---|---|
committer | Linaro Code Review <review@review.linaro.org> | 2016-02-04 14:39:53 +0000 |
commit | 5c396c068ea497f58494239b49c1122d123d8733 (patch) | |
tree | e1fbb5a3847903f8d6018bde1b424c3faa13c703 | |
parent | a34627ef9d4fd6b541505a64fee177e27e3820cc (diff) |
gcc/
Backport from trunk r232154.
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.
gcc/testsuite/
Backport from trunk r232154.
2016-01-08 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/67781
* gcc.c-torture/execute/pr67781.c: New file.
Change-Id: I342f01fc0148d2209d46476301674d8be7ab5fad
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr67781.c | 34 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 36 |
2 files changed, 60 insertions, 10 deletions
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 00000000000..bf50aa2f6c3 --- /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 d7fc91167dd..b1853c299d4 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2433,6 +2433,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. */ @@ -2456,24 +2458,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. */ |