Commit 73984f84 by Thomas Preud'homme Committed by Thomas Preud'homme

re PR tree-optimization/54733 (Missing opportunity to optimize endian independent load/store)

2014-05-23  Thomas Preud'homme  <thomas.preudhomme@arm.com>

	PR tree-optimization/54733
gcc/
	* tree-ssa-math-opts.c (nop_stats): New "bswap_stats" structure.
	(CMPNOP): Define.
	(find_bswap_or_nop_load): New.
	(find_bswap_1): Renamed to ...
	(find_bswap_or_nop_1): This. Also add support for memory source.
	(find_bswap): Renamed to ...
	(find_bswap_or_nop): This. Also add support for memory source and
	detection of bitwise operations equivalent to load in host endianness.
	(execute_optimize_bswap): Likewise. Also move its leading comment back
	in place and split statement transformation into ...
	(bswap_replace): This.

gcc/testsuite
	* gcc.dg/optimize-bswapdi-3.c: New test to check extension of bswap
	optimization to support memory sources and bitwise operations
	equivalent to load in host endianness.
	* gcc.dg/optimize-bswaphi-1.c: Likewise.
	* gcc.dg/optimize-bswapsi-2.c: Likewise.
	* gcc.c-torture/execute/bswap-2.c: Likewise.

From-SVN: r210843
parent eaa33a6a
2014-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/54733
* tree-ssa-math-opts.c (nop_stats): New "bswap_stats" structure.
(CMPNOP): Define.
(find_bswap_or_nop_load): New.
(find_bswap_1): Renamed to ...
(find_bswap_or_nop_1): This. Also add support for memory source.
(find_bswap): Renamed to ...
(find_bswap_or_nop): This. Also add support for memory source and
detection of bitwise operations equivalent to load in host endianness.
(execute_optimize_bswap): Likewise. Also move its leading comment back
in place and split statement transformation into ...
(bswap_replace): This.
2014-05-22 Vladimir Makarov <vmakarov@redhat.com> 2014-05-22 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/61215 PR rtl-optimization/61215
......
2014-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com> 2014-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/54733
* gcc.dg/optimize-bswapdi-3.c: New test to check extension of bswap
optimization to support memory sources and bitwise operations
equivalent to load in host endianness.
* gcc.dg/optimize-bswaphi-1.c: Likewise.
* gcc.dg/optimize-bswapsi-2.c: Likewise.
* gcc.c-torture/execute/bswap-2.c: Likewise.
2014-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
* lib/target-supports.exp: New effective targets for architectures * lib/target-supports.exp: New effective targets for architectures
capable of performing byte swap. capable of performing byte swap.
* gcc.dg/optimize-bswapdi-1.c: Convert to new bswap target. * gcc.dg/optimize-bswapdi-1.c: Convert to new bswap target.
......
#ifdef __UINT32_TYPE__
typedef __UINT32_TYPE__ uint32_t;
#else
typedef __UINT32_TYPE__ unsigned;
#endif
struct bitfield {
unsigned char f0:7;
unsigned char f1:7;
unsigned char f2:7;
unsigned char f3:7;
};
struct ok {
unsigned char f0;
unsigned char f1;
unsigned char f2;
unsigned char f3;
};
union bf_or_uint32 {
struct ok inval;
struct bitfield bfval;
};
__attribute__ ((noinline, noclone)) uint32_t
partial_read_le32 (union bf_or_uint32 in)
{
return in.bfval.f0 | (in.bfval.f1 << 8)
| (in.bfval.f2 << 16) | (in.bfval.f3 << 24);
}
__attribute__ ((noinline, noclone)) uint32_t
partial_read_be32 (union bf_or_uint32 in)
{
return in.bfval.f3 | (in.bfval.f2 << 8)
| (in.bfval.f1 << 16) | (in.bfval.f0 << 24);
}
__attribute__ ((noinline, noclone)) uint32_t
fake_read_le32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
*y = 1;
c2 = x[2];
c3 = x[3];
return c0 | c1 << 8 | c2 << 16 | c3 << 24;
}
__attribute__ ((noinline, noclone)) uint32_t
fake_read_be32 (char *x, char *y)
{
unsigned char c0, c1, c2, c3;
c0 = x[0];
c1 = x[1];
*y = 1;
c2 = x[2];
c3 = x[3];
return c3 | c2 << 8 | c1 << 16 | c0 << 24;
}
int
main ()
{
union bf_or_uint32 bfin;
uint32_t out;
char cin[] = { 0x83, 0x85, 0x87, 0x89 };
if (sizeof (uint32_t) * __CHAR_BIT__ != 32)
return 0;
bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
out = partial_read_le32 (bfin);
if (out != 0x09070503 && out != 0x88868482)
__builtin_abort ();
bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
out = partial_read_be32 (bfin);
if (out != 0x03050709 && out != 0x82848688)
__builtin_abort ();
out = fake_read_le32 (cin, &cin[2]);
if (out != 0x89018583)
__builtin_abort ();
out = fake_read_be32 (cin, &cin[2]);
if (out != 0x83850189)
__builtin_abort ();
return 0;
}
/* { dg-do compile } */
/* { dg-require-effective-target bswap64 } */
/* { dg-require-effective-target stdint_types } */
/* { dg-options "-O2 -fdump-tree-bswap" } */
#include <stdint.h>
unsigned char data[8];
struct uint64_st {
unsigned char u0, u1, u2, u3, u4, u5, u6, u7;
};
uint64_t read_le64_1 (void)
{
return (uint64_t) data[0] | ((uint64_t) data[1] << 8)
| ((uint64_t) data[2] << 16) | ((uint64_t) data[3] << 24)
| ((uint64_t) data[4] << 32) | ((uint64_t) data[5] << 40)
| ((uint64_t) data[6] << 48) | ((uint64_t) data[7] << 56);
}
uint64_t read_le64_2 (struct uint64_st data)
{
return (uint64_t) data.u0 | ((uint64_t) data.u1 << 8)
| ((uint64_t) data.u2 << 16) | ((uint64_t) data.u3 << 24)
| ((uint64_t) data.u4 << 32) | ((uint64_t) data.u5 << 40)
| ((uint64_t) data.u6 << 48) | ((uint64_t) data.u7 << 56);
}
uint64_t read_le64_3 (unsigned char *data)
{
return (uint64_t) *data | ((uint64_t) *(data + 1) << 8)
| ((uint64_t) *(data + 2) << 16) | ((uint64_t) *(data + 3) << 24)
| ((uint64_t) *(data + 4) << 32) | ((uint64_t) *(data + 5) << 40)
| ((uint64_t) *(data + 6) << 48) | ((uint64_t) *(data + 7) << 56);
}
uint64_t read_be64_1 (void)
{
return (uint64_t) data[7] | ((uint64_t) data[6] << 8)
| ((uint64_t) data[5] << 16) | ((uint64_t) data[4] << 24)
| ((uint64_t) data[3] << 32) | ((uint64_t) data[2] << 40)
| ((uint64_t) data[1] << 48) | ((uint64_t) data[0] << 56);
}
uint64_t read_be64_2 (struct uint64_st data)
{
return (uint64_t) data.u7 | ((uint64_t) data.u6 << 8)
| ((uint64_t) data.u5 << 16) | ((uint64_t) data.u4 << 24)
| ((uint64_t) data.u3 << 32) | ((uint64_t) data.u2 << 40)
| ((uint64_t) data.u1 << 48) | ((uint64_t) data.u0 << 56);
}
uint64_t read_be64_3 (unsigned char *data)
{
return (uint64_t) *(data + 7) | ((uint64_t) *(data + 6) << 8)
| ((uint64_t) *(data + 5) << 16) | ((uint64_t) *(data + 4) << 24)
| ((uint64_t) *(data + 3) << 32) | ((uint64_t) *(data + 2) << 40)
| ((uint64_t) *(data + 1) << 48) | ((uint64_t) *data << 56);
}
/* { dg-final { scan-tree-dump-times "64 bit load in host endianness found at" 3 "bswap" } } */
/* { dg-final { scan-tree-dump-times "64 bit bswap implementation found at" 3 "bswap" { xfail alpha*-*-* arm*-*-* } } } */
/* { dg-final { cleanup-tree-dump "bswap" } } */
/* { dg-do compile } */
/* { dg-require-effective-target bswap16 } */
/* { dg-require-effective-target stdint_types } */
/* { dg-options "-O2 -fdump-tree-bswap" } */
/* { dg-options "-O2 -fdump-tree-bswap -march=z900" { target s390-*-* } } */
#include <stdint.h>
unsigned char data[2];
struct uint16_st {
unsigned char u0, u1;
};
uint32_t read_le16_1 (void)
{
return data[0] | (data[1] << 8);
}
uint32_t read_le16_2 (struct uint16_st data)
{
return data.u0 | (data.u1 << 8);
}
uint32_t read_le16_3 (unsigned char *data)
{
return *data | (*(data + 1) << 8);
}
uint32_t read_be16_1 (void)
{
return data[1] | (data[0] << 8);
}
uint32_t read_be16_2 (struct uint16_st data)
{
return data.u1 | (data.u0 << 8);
}
uint32_t read_be16_3 (unsigned char *data)
{
return *(data + 1) | (*data << 8);
}
/* { dg-final { scan-tree-dump-times "16 bit load in host endianness found at" 3 "bswap" } } */
/* { dg-final { scan-tree-dump-times "16 bit bswap implementation found at" 3 "bswap" { xfail alpha*-*-* arm*-*-* } } } */
/* { dg-final { cleanup-tree-dump "bswap" } } */
/* { dg-do compile } */
/* { dg-require-effective-target bswap32 } */
/* { dg-require-effective-target stdint_types } */
/* { dg-options "-O2 -fdump-tree-bswap" } */
/* { dg-options "-O2 -fdump-tree-bswap -march=z900" { target s390-*-* } } */
#include <stdint.h>
extern unsigned char data[4];
struct uint32_st {
unsigned char u0, u1, u2, u3;
};
uint32_t read_le32_1 (void)
{
return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
}
uint32_t read_le32_2 (struct uint32_st data)
{
return data.u0 | (data.u1 << 8) | (data.u2 << 16) | (data.u3 << 24);
}
uint32_t read_le32_3 (unsigned char *data)
{
return *data | (*(data + 1) << 8) | (*(data + 2) << 16)
| (*(data + 3) << 24);
}
uint32_t read_be32_1 (void)
{
return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
}
uint32_t read_be32_2 (struct uint32_st data)
{
return data.u3 | (data.u2 << 8) | (data.u1 << 16) | (data.u0 << 24);
}
uint32_t read_be32_3 (unsigned char *data)
{
return *(data + 3) | (*(data + 2) << 8) | (*(data + 1) << 16)
| (*data << 24);
}
/* { dg-final { scan-tree-dump-times "32 bit load in host endianness found at" 3 "bswap" } } */
/* { dg-final { scan-tree-dump-times "32 bit bswap implementation found at" 3 "bswap" { xfail alpha*-*-* arm*-*-* } } } */
/* { dg-final { cleanup-tree-dump "bswap" } } */
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