Commit 6d87c306 by Bernd Schmidt Committed by Bernd Schmidt

Fix bswap optimization on big-endian (PR69714, 67781).

	PR tree-optimization/69714
	* tree-ssa-math-opts.c (find_bswap_or_nop): Revert previous change.
	Return NULL if we have irrelevant high bytes on BIG_ENDIAN.

testsuite/
	PR tree-optimization/69714
	* gcc.dg/torture/pr69714.c: New test.

From-SVN: r233452
parent 8f3304d0
2016-02-16 Bernd Schmidt <bschmidt@redhat.com>
PR tree-optimization/69714
* tree-ssa-math-opts.c (find_bswap_or_nop): Revert previous change.
Return NULL if we have irrelevant high bytes on BIG_ENDIAN.
2016-02-16 Claudiu Zissulescu <claziss@synopsys.com> 2016-02-16 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc-modes.def (CC_FPU, CC_FPU_UNEQ): New modes. * config/arc/arc-modes.def (CC_FPU, CC_FPU_UNEQ): New modes.
......
2016-02-16 Bernd Schmidt <bschmidt@redhat.com>
PR tree-optimization/69714
* gcc.dg/torture/pr69714.c: New test.
2016-02-16 Jakub Jelinek <jakub@redhat.com> 2016-02-16 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/69802 PR tree-optimization/69802
...@@ -152,7 +157,7 @@ ...@@ -152,7 +157,7 @@
2016-02-12 Bernd Schmidt <bschmidt@redhat.com> 2016-02-12 Bernd Schmidt <bschmidt@redhat.com>
PR c/69522 PR c/69522
gcc.dg/pr69522.c: New test. * gcc.dg/pr69522.c: New test.
2016-02-12 Patrick Palka <ppalka@gcc.gnu.org> 2016-02-12 Patrick Palka <ppalka@gcc.gnu.org>
......
/* { dg-do run } */
/* { dg-options "-fno-strict-aliasing" } */
#include <stdint.h>
#include <stdio.h>
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define av_le2ne32(x) (x)
#else
#define av_le2ne32(x) av_bswap32(x)
#endif
static __attribute__((always_inline)) inline __attribute__((const)) uint32_t av_bswap32(uint32_t x)
{
return ((((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff)) << 16 | ((((x) >> 16) << 8 & 0xff00) | (((x) >> 16) >> 8 & 0x00ff)));
}
typedef uint32_t AVCRC;
typedef enum {
AV_CRC_8_ATM,
AV_CRC_16_ANSI,
AV_CRC_16_CCITT,
AV_CRC_32_IEEE,
AV_CRC_32_IEEE_LE,
AV_CRC_16_ANSI_LE,
AV_CRC_24_IEEE = 12,
AV_CRC_MAX,
} AVCRCId;
int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size);
uint32_t av_crc(const AVCRC *ctx, uint32_t crc,
const uint8_t *buffer, size_t length) __attribute__((pure));
static struct {
uint8_t le;
uint8_t bits;
uint32_t poly;
} av_crc_table_params[AV_CRC_MAX] = {
[AV_CRC_8_ATM] = { 0, 8, 0x07 },
[AV_CRC_16_ANSI] = { 0, 16, 0x8005 },
[AV_CRC_16_CCITT] = { 0, 16, 0x1021 },
[AV_CRC_24_IEEE] = { 0, 24, 0x864CFB },
[AV_CRC_32_IEEE] = { 0, 32, 0x04C11DB7 },
[AV_CRC_32_IEEE_LE] = { 1, 32, 0xEDB88320 },
[AV_CRC_16_ANSI_LE] = { 1, 16, 0xA001 },
};
static AVCRC av_crc_table[AV_CRC_MAX][1024];
int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size)
{
unsigned i, j;
uint32_t c;
if (bits < 8 || bits > 32 || poly >= (1LL << bits))
return -1;
if (ctx_size != sizeof(AVCRC) * 257 && ctx_size != sizeof(AVCRC) * 1024)
return -1;
for (i = 0; i < 256; i++) {
if (le) {
for (c = i, j = 0; j < 8; j++)
c = (c >> 1) ^ (poly & (-(c & 1)));
ctx[i] = c;
} else {
for (c = i << 24, j = 0; j < 8; j++)
c = (c << 1) ^ ((poly << (32 - bits)) & (((int32_t) c) >> 31));
ctx[i] = av_bswap32(c);
}
}
ctx[256] = 1;
if (ctx_size >= sizeof(AVCRC) * 1024)
for (i = 0; i < 256; i++)
for (j = 0; j < 3; j++)
ctx[256 *(j + 1) + i] =
(ctx[256 * j + i] >> 8) ^ ctx[ctx[256 * j + i] & 0xFF];
return 0;
}
const AVCRC *av_crc_get_table(AVCRCId crc_id)
{
if (!av_crc_table[crc_id][(sizeof(av_crc_table[crc_id]) / sizeof((av_crc_table[crc_id])[0])) - 1])
if (av_crc_init(av_crc_table[crc_id],
av_crc_table_params[crc_id].le,
av_crc_table_params[crc_id].bits,
av_crc_table_params[crc_id].poly,
sizeof(av_crc_table[crc_id])) < 0)
return ((void *)0);
return av_crc_table[crc_id];
}
uint32_t av_crc(const AVCRC *ctx, uint32_t crc,
const uint8_t *buffer, size_t length)
{
const uint8_t *end = buffer + length;
if (!ctx[256]) {
while (((intptr_t) buffer & 3) && buffer < end)
crc = ctx[((uint8_t) crc) ^ *buffer++] ^ (crc >> 8);
while (buffer < end - 3) {
crc ^= av_le2ne32(*(const uint32_t *) buffer); buffer += 4;
crc = ctx[3 * 256 + ( crc & 0xFF)] ^
ctx[2 * 256 + ((crc >> 8 ) & 0xFF)] ^
ctx[1 * 256 + ((crc >> 16) & 0xFF)] ^
ctx[0 * 256 + ((crc >> 24) )];
}
}
while (buffer < end)
crc = ctx[((uint8_t) crc) ^ *buffer++] ^ (crc >> 8);
return crc;
}
int main(void)
{
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
uint8_t buf[1999];
int i;
unsigned
p[6][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 },
{ AV_CRC_32_IEEE , 0x04C11DB7, 0xE0BAF5C0 },
{ AV_CRC_24_IEEE , 0x864CFB , 0x326039 },
{ AV_CRC_16_ANSI_LE, 0xA001 , 0xBFD8 },
{ AV_CRC_16_ANSI , 0x8005 , 0xBB1F },
{ AV_CRC_8_ATM , 0x07 , 0xE3 }
};
const AVCRC *ctx;
for (i = 0; i < sizeof(buf); i++)
buf[i] = i + i * i;
for (i = 0; i < 6; i++) {
int id = p[i][0];
uint32_t result;
ctx = av_crc_get_table (id);
result = av_crc(ctx, 0, buf, sizeof(buf));
if (result != p[i][2])
__builtin_abort ();
}
#endif
return 0;
}
...@@ -2449,11 +2449,9 @@ find_bswap_or_nop_1 (gimple *stmt, struct symbolic_number *n, int limit) ...@@ -2449,11 +2449,9 @@ 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; /* The number which the find_bswap_or_nop_1 result should match in order
uint64_t tmpn, mask; to have a full byte swap. The number is shifted to the right
/* The number which the find_bswap_or_nop_1 result should match in order according to the size of the symbolic number before using it. */
to have a full byte swap. The number is shifted to the right
according to the size of the symbolic number before using it. */
uint64_t cmpxchg = CMPXCHG; uint64_t cmpxchg = CMPXCHG;
uint64_t cmpnop = CMPNOP; uint64_t cmpnop = CMPNOP;
...@@ -2474,38 +2472,28 @@ find_bswap_or_nop (gimple *stmt, struct symbolic_number *n, bool *bswap) ...@@ -2474,38 +2472,28 @@ 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++); {
else unsigned HOST_WIDE_INT rsize;
rsize = n->range; uint64_t tmpn;
/* Zero out the bits corresponding to untouched bytes in original gimple for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
expression. */ if (BYTES_BIG_ENDIAN && n->range != rsize)
/* This implies an offset, which is currently not handled by
bswap_replace. */
return NULL;
n->range = rsize;
}
/* 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. */
......
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