aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Baylis <charles.baylis@linaro.org>2016-01-27 15:38:45 +0000
committerLinaro Code Review <review@review.linaro.org>2016-02-04 14:39:53 +0000
commit5c396c068ea497f58494239b49c1122d123d8733 (patch)
treee1fbb5a3847903f8d6018bde1b424c3faa13c703
parenta34627ef9d4fd6b541505a64fee177e27e3820cc (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.c34
-rw-r--r--gcc/tree-ssa-math-opts.c36
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. */