Commit 80e9b3aa by Thomas Preud'homme Committed by Thomas Preud'homme

re PR tree-optimization/67781 (wrong code generated on big-endian with -O1…

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
parent 262a363f
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> 2016-01-08 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/69083 PR tree-optimization/69083
......
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> 2016-01-08 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/69083 PR tree-optimization/69083
......
#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;
}
...@@ -2449,6 +2449,8 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit) ...@@ -2449,6 +2449,8 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit)
static gimple * static gimple *
find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap) 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 /* 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 to have a full byte swap. The number is shifted to the right
according to the size of the symbolic number before using it. */ 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) ...@@ -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). */ /* Find real size of result (highest non-zero byte). */
if (n->base_addr) if (n->base_addr)
{ for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
int rsize; else
uint64_t tmpn; rsize = n->range;
for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
n->range = rsize;
}
/* 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)) if (n->range < (int) sizeof (int64_t))
{ {
uint64_t mask;
mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1; mask = ((uint64_t) 1 << (n->range * BITS_PER_MARKER)) - 1;
cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER; cmpxchg >>= (64 / BITS_PER_MARKER - n->range) * BITS_PER_MARKER;
cmpnop &= mask; 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 /* A complete byte swap should make the symbolic number to start with
the largest digit in the highest order byte. Unchanged symbolic the largest digit in the highest order byte. Unchanged symbolic
number indicates a read with same endianness as target architecture. */ number indicates a read with same endianness as target architecture. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment