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
This commit is contained in:
Thomas Preud'homme 2016-01-08 09:21:19 +00:00 committed by Thomas Preud'homme
parent 262a363ff9
commit 80e9b3aaac
4 changed files with 73 additions and 10 deletions

View File

@ -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> 2016-01-08 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/69083 PR tree-optimization/69083

View File

@ -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> 2016-01-08 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/69083 PR tree-optimization/69083

View File

@ -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;
}

View File

@ -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)
/* 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++); /* Zero out the bits corresponding to untouched bytes in original gimple
n->range = rsize; expression. */
}
/* Zero out the extra bits of N and CMP*. */
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. */