diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-05-10 10:40:10 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-05-10 10:40:10 +0200 |
commit | cb3b8d33faa3a649b02827649f9c76e40edace15 (patch) | |
tree | 48fdd5402146ff7985941320929c5cda2e1a1c90 | |
parent | fb7f649d713491d28fd41f3ce12e474af03617df (diff) | |
download | gcc-cb3b8d33faa3a649b02827649f9c76e40edace15.tar.gz |
re PR tree-optimization/45216 (Rotate expressions not recognized at tree level)
PR tree-optimization/45216
PR tree-optimization/57157
* tree-ssa-forwprop.c (simplify_rotate): New function.
(ssa_forward_propagate_and_combine): Call it.
* c-c++-common/rotate-1.c: New test.
* c-c++-common/rotate-1a.c: New test.
* c-c++-common/rotate-2.c: New test.
* c-c++-common/rotate-2a.c: New test.
* c-c++-common/rotate-3.c: New test.
* c-c++-common/rotate-3a.c: New test.
* c-c++-common/rotate-4.c: New test.
* c-c++-common/rotate-4a.c: New test.
From-SVN: r198769
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-1.c | 389 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-1a.c | 44 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-2.c | 389 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-2a.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-3.c | 389 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-3a.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-4.c | 389 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/rotate-4a.c | 6 | ||||
-rw-r--r-- | gcc/tree-ssa-forwprop.c | 241 |
11 files changed, 1879 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c7d6db9a744..82b35a1e601 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2013-05-10 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/45216 + PR tree-optimization/57157 + * tree-ssa-forwprop.c (simplify_rotate): New function. + (ssa_forward_propagate_and_combine): Call it. + 2013-05-10 Richard Biener <rguenther@suse.de> * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Do not diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7656de9b0ab..19e0a5b5401 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2013-05-10 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/45216 + PR tree-optimization/57157 + * c-c++-common/rotate-1.c: New test. + * c-c++-common/rotate-1a.c: New test. + * c-c++-common/rotate-2.c: New test. + * c-c++-common/rotate-2a.c: New test. + * c-c++-common/rotate-3.c: New test. + * c-c++-common/rotate-3a.c: New test. + * c-c++-common/rotate-4.c: New test. + * c-c++-common/rotate-4a.c: New test. + 2013-05-10 Richard Biener <rguenther@suse.de> * gcc.target/i386/avx256-unaligned-load-2.c: Make well-defined. diff --git a/gcc/testsuite/c-c++-common/rotate-1.c b/gcc/testsuite/c-c++-common/rotate-1.c new file mode 100644 index 00000000000..ec3e90bd6fd --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-1.c @@ -0,0 +1,389 @@ +/* Check rotate pattern detection. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + +unsigned int +f1 (unsigned int x, unsigned int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f2 (unsigned int x, unsigned long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f3 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned int +f4 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x >> 1); +} + +unsigned short int +f5 (unsigned short int x, unsigned int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned short int +f6 (unsigned short int x, unsigned long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned char +f7 (unsigned char x, unsigned int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ - y)); +} + +unsigned char +f8 (unsigned char x, unsigned long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ - y)); +} + +unsigned int +f9 (unsigned int x, unsigned int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f10 (unsigned int x, unsigned long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f11 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned int +f12 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x >> 1); +} + +unsigned short int +f13 (unsigned short int x, unsigned int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned short int +f14 (unsigned short int x, unsigned long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned char +f15 (unsigned char x, unsigned int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned char +f16 (unsigned char x, unsigned long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned int +f17 (unsigned int x, unsigned int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); +} + +unsigned int +f18 (unsigned int x, unsigned long int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); +} + +unsigned int +f19 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x << 1); +} + +unsigned int +f20 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned short int +f21 (unsigned short int x, unsigned int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); +} + +unsigned short int +f22 (unsigned short int x, unsigned long int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); +} + +unsigned char +f23 (unsigned char x, unsigned int y) +{ + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); +} + +unsigned char +f24 (unsigned char x, unsigned long int y) +{ + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); +} + +unsigned int +f25 (unsigned int x, unsigned int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); +} + +unsigned int +f26 (unsigned int x, unsigned long int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); +} + +unsigned int +f27 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x << 1); +} + +unsigned int +f28 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned short int +f29 (unsigned short int x, unsigned int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); +} + +unsigned short int +f30 (unsigned short int x, unsigned long int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); +} + +unsigned char +f31 (unsigned char x, unsigned int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); +} + +unsigned char +f32 (unsigned char x, unsigned long int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); +} + +unsigned int +f33 (unsigned int x, unsigned int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f34 (unsigned int x, unsigned long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f35 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned int +f36 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x << 1); +} + +unsigned short int +f37 (unsigned short int x, unsigned int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned short int +f38 (unsigned short int x, unsigned long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned char +f39 (unsigned char x, unsigned int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ - y)); +} + +unsigned char +f40 (unsigned char x, unsigned long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ - y)); +} + +unsigned int +f41 (unsigned int x, unsigned int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f42 (unsigned int x, unsigned long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f43 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned int +f44 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x << 1); +} + +unsigned short int +f45 (unsigned short int x, unsigned int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned short int +f46 (unsigned short int x, unsigned long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned char +f47 (unsigned char x, unsigned int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned char +f48 (unsigned char x, unsigned long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned int +f49 (unsigned int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); +} + +unsigned int +f50 (unsigned int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); +} + +unsigned int +f51 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x >> 1); +} + +unsigned int +f52 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned short int +f53 (unsigned short int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); +} + +unsigned short int +f54 (unsigned short int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); +} + +unsigned char +f55 (unsigned char x, unsigned int y) +{ + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); +} + +unsigned char +f56 (unsigned char x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); +} + +unsigned int +f57 (unsigned int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); +} + +unsigned int +f58 (unsigned int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); +} + +unsigned int +f59 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x >> 1); +} + +unsigned int +f60 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned short int +f61 (unsigned short int x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); +} + +unsigned short int +f62 (unsigned short int x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); +} + +unsigned char +f63 (unsigned char x, unsigned int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); +} + +unsigned char +f64 (unsigned char x, unsigned long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); +} diff --git a/gcc/testsuite/c-c++-common/rotate-1a.c b/gcc/testsuite/c-c++-common/rotate-1a.c new file mode 100644 index 00000000000..fc838a87fcf --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-1a.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -Wno-overflow" } */ + +extern +#ifdef __cplusplus +"C" +#endif +void abort (void); + +#ifndef ROTATE_N +#define ROTATE_N "rotate-1.c" +#endif + +#include ROTATE_N + +unsigned int expected[] = { +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, +0x91a2b3c0, 0x91a2b3c0, 0x2468acf0, 0x91a2b3c, 0xb3c2, 0xb3c2, 0xc3, 0xc3, +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf, +0x2468acf, 0x2468acf, 0x91a2b3c, 0x2468acf0, 0xacf, 0xacf, 0xf, 0xf }; + +#define F(n) __typeof (f##n) f##n __attribute__((noinline, noclone)); +#define D(n) F(n##0) F(n##1) F(n##2) F(n##3) F(n##4) F(n##5) F(n##6) F(n##7) F(n##8) F(n##9) +#define ALL \ +F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8) F(9) \ +D(1) D(2) D(3) D(4) D(5) F(60) F(61) F(62) F(63) F(64) +ALL + +int +main () +{ +#if __CHAR_BIT__ != 8 || __SIZEOF_SHORT__ != 2 || __SIZEOF_INT__ != 4 + return 0; +#else +#undef F +#define F(n) if ((unsigned int) f##n (0x12345678U, 3) != expected[n - 1]) abort (); + ALL + return 0; +#endif +} diff --git a/gcc/testsuite/c-c++-common/rotate-2.c b/gcc/testsuite/c-c++-common/rotate-2.c new file mode 100644 index 00000000000..d8538667c62 --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-2.c @@ -0,0 +1,389 @@ +/* Check rotate pattern detection. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + +unsigned int +f1 (unsigned int x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f2 (unsigned int x, unsigned long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f3 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f4 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> 1); +} + +unsigned short int +f5 (unsigned short int x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned short int +f6 (unsigned short int x, unsigned long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned char +f7 (unsigned char x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned char +f8 (unsigned char x, unsigned long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned int +f9 (unsigned int x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f10 (unsigned int x, unsigned long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f11 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f12 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x >> 1); +} + +unsigned short int +f13 (unsigned short int x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned short int +f14 (unsigned short int x, unsigned long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned char +f15 (unsigned char x, unsigned int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned char +f16 (unsigned char x, unsigned long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned int +f17 (unsigned int x, unsigned int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); +} + +unsigned int +f18 (unsigned int x, unsigned long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); +} + +unsigned int +f19 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << 1); +} + +unsigned int +f20 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned short int +f21 (unsigned short int x, unsigned int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); +} + +unsigned short int +f22 (unsigned short int x, unsigned long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); +} + +unsigned char +f23 (unsigned char x, unsigned int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); +} + +unsigned char +f24 (unsigned char x, unsigned long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); +} + +unsigned int +f25 (unsigned int x, unsigned int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << y); +} + +unsigned int +f26 (unsigned int x, unsigned long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << y); +} + +unsigned int +f27 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << 1); +} + +unsigned int +f28 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned short int +f29 (unsigned short int x, unsigned int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x << y); +} + +unsigned short int +f30 (unsigned short int x, unsigned long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x << y); +} + +unsigned char +f31 (unsigned char x, unsigned int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << y); +} + +unsigned char +f32 (unsigned char x, unsigned long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << y); +} + +unsigned int +f33 (unsigned int x, unsigned int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f34 (unsigned int x, unsigned long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f35 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f36 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x << 1); +} + +unsigned short int +f37 (unsigned short int x, unsigned int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned short int +f38 (unsigned short int x, unsigned long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned char +f39 (unsigned char x, unsigned int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned char +f40 (unsigned char x, unsigned long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned int +f41 (unsigned int x, unsigned int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f42 (unsigned int x, unsigned long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f43 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f44 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x << 1); +} + +unsigned short int +f45 (unsigned short int x, unsigned int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned short int +f46 (unsigned short int x, unsigned long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned char +f47 (unsigned char x, unsigned int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned char +f48 (unsigned char x, unsigned long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned int +f49 (unsigned int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); +} + +unsigned int +f50 (unsigned int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); +} + +unsigned int +f51 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> 1); +} + +unsigned int +f52 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned short int +f53 (unsigned short int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); +} + +unsigned short int +f54 (unsigned short int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); +} + +unsigned char +f55 (unsigned char x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); +} + +unsigned char +f56 (unsigned char x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); +} + +unsigned int +f57 (unsigned int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> y); +} + +unsigned int +f58 (unsigned int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> y); +} + +unsigned int +f59 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> 1); +} + +unsigned int +f60 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned short int +f61 (unsigned short int x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x >> y); +} + +unsigned short int +f62 (unsigned short int x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x >> y); +} + +unsigned char +f63 (unsigned char x, unsigned int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> y); +} + +unsigned char +f64 (unsigned char x, unsigned long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> y); +} diff --git a/gcc/testsuite/c-c++-common/rotate-2a.c b/gcc/testsuite/c-c++-common/rotate-2a.c new file mode 100644 index 00000000000..d709c0d3680 --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-2a.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -Wno-overflow" } */ + +#define ROTATE_N "rotate-2.c" + +#include "rotate-1a.c" diff --git a/gcc/testsuite/c-c++-common/rotate-3.c b/gcc/testsuite/c-c++-common/rotate-3.c new file mode 100644 index 00000000000..a7d138f9248 --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-3.c @@ -0,0 +1,389 @@ +/* Check rotate pattern detection. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + +unsigned int +f1 (unsigned int x, int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f2 (unsigned int x, long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f3 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned int +f4 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x >> 1); +} + +unsigned short int +f5 (unsigned short int x, int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned short int +f6 (unsigned short int x, long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned char +f7 (unsigned char x, int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ - y)); +} + +unsigned char +f8 (unsigned char x, long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ - y)); +} + +unsigned int +f9 (unsigned int x, int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f10 (unsigned int x, long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f11 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned int +f12 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x >> 1); +} + +unsigned short int +f13 (unsigned short int x, int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned short int +f14 (unsigned short int x, long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned char +f15 (unsigned char x, int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned char +f16 (unsigned char x, long int y) +{ + return (x << y) | (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned int +f17 (unsigned int x, int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); +} + +unsigned int +f18 (unsigned int x, long int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x << y); +} + +unsigned int +f19 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x << 1); +} + +unsigned int +f20 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned short int +f21 (unsigned short int x, int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); +} + +unsigned short int +f22 (unsigned short int x, long int y) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x << y); +} + +unsigned char +f23 (unsigned char x, int y) +{ + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); +} + +unsigned char +f24 (unsigned char x, long int y) +{ + return (x >> (__CHAR_BIT__ - y)) ^ (x << y); +} + +unsigned int +f25 (unsigned int x, int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); +} + +unsigned int +f26 (unsigned int x, long int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x << y); +} + +unsigned int +f27 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x << 1); +} + +unsigned int +f28 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned short int +f29 (unsigned short int x, int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); +} + +unsigned short int +f30 (unsigned short int x, long int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x << y); +} + +unsigned char +f31 (unsigned char x, int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); +} + +unsigned char +f32 (unsigned char x, long int y) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x << y); +} + +unsigned int +f33 (unsigned int x, int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f34 (unsigned int x, long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)); +} + +unsigned int +f35 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned int +f36 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) | (x << 1); +} + +unsigned short int +f37 (unsigned short int x, int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned short int +f38 (unsigned short int x, long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); +} + +unsigned char +f39 (unsigned char x, int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ - y)); +} + +unsigned char +f40 (unsigned char x, long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ - y)); +} + +unsigned int +f41 (unsigned int x, int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f42 (unsigned int x, long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)); +} + +unsigned int +f43 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned int +f44 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)) | (x << 1); +} + +unsigned short int +f45 (unsigned short int x, int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned short int +f46 (unsigned short int x, long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)); +} + +unsigned char +f47 (unsigned char x, int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned char +f48 (unsigned char x, long int y) +{ + return (x >> y) | (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)); +} + +unsigned int +f49 (unsigned int x, int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); +} + +unsigned int +f50 (unsigned int x, long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) ^ (x >> y); +} + +unsigned int +f51 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) ^ (x >> 1); +} + +unsigned int +f52 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); +} + +unsigned short int +f53 (unsigned short int x, int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); +} + +unsigned short int +f54 (unsigned short int x, long int y) +{ + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) ^ (x >> y); +} + +unsigned char +f55 (unsigned char x, int y) +{ + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); +} + +unsigned char +f56 (unsigned char x, long int y) +{ + return (x << (__CHAR_BIT__ - y)) ^ (x >> y); +} + +unsigned int +f57 (unsigned int x, int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); +} + +unsigned int +f58 (unsigned int x, long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) ^ (x >> y); +} + +unsigned int +f59 (unsigned int x, int y __attribute__((unused))) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) ^ (x >> 1); +} + +unsigned int +f60 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); +} + +unsigned short int +f61 (unsigned short int x, int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); +} + +unsigned short int +f62 (unsigned short int x, long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) ^ (x >> y); +} + +unsigned char +f63 (unsigned char x, int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); +} + +unsigned char +f64 (unsigned char x, long int y) +{ + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); +} diff --git a/gcc/testsuite/c-c++-common/rotate-3a.c b/gcc/testsuite/c-c++-common/rotate-3a.c new file mode 100644 index 00000000000..450fc22d70c --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-3a.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -Wno-overflow" } */ + +#define ROTATE_N "rotate-4.c" + +#include "rotate-1a.c" diff --git a/gcc/testsuite/c-c++-common/rotate-4.c b/gcc/testsuite/c-c++-common/rotate-4.c new file mode 100644 index 00000000000..705feceabd9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-4.c @@ -0,0 +1,389 @@ +/* Check rotate pattern detection. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + +unsigned int +f1 (unsigned int x, int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f2 (unsigned int x, long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f3 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f4 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> 1); +} + +unsigned short int +f5 (unsigned short int x, int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned short int +f6 (unsigned short int x, long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned char +f7 (unsigned char x, int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned char +f8 (unsigned char x, long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned int +f9 (unsigned int x, int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f10 (unsigned int x, long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f11 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) | (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f12 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x >> 1); +} + +unsigned short int +f13 (unsigned short int x, int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned short int +f14 (unsigned short int x, long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned char +f15 (unsigned char x, int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned char +f16 (unsigned char x, long int y) +{ + return (x << y) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned int +f17 (unsigned int x, int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); +} + +unsigned int +f18 (unsigned int x, long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << y); +} + +unsigned int +f19 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << 1); +} + +unsigned int +f20 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned short int +f21 (unsigned short int x, int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); +} + +unsigned short int +f22 (unsigned short int x, long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << y); +} + +unsigned char +f23 (unsigned char x, int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); +} + +unsigned char +f24 (unsigned char x, long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << y); +} + +unsigned int +f25 (unsigned int x, int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << y); +} + +unsigned int +f26 (unsigned int x, long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << y); +} + +unsigned int +f27 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << 1); +} + +unsigned int +f28 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) ^ (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned short int +f29 (unsigned short int x, int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x << y); +} + +unsigned short int +f30 (unsigned short int x, long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x << y); +} + +unsigned char +f31 (unsigned char x, int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << y); +} + +unsigned char +f32 (unsigned char x, long int y) +{ + return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << y); +} + +unsigned int +f33 (unsigned int x, int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f34 (unsigned int x, long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f35 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned int +f36 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x << 1); +} + +unsigned short int +f37 (unsigned short int x, int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned short int +f38 (unsigned short int x, long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); +} + +unsigned char +f39 (unsigned char x, int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned char +f40 (unsigned char x, long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ - 1))); +} + +unsigned int +f41 (unsigned int x, int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f42 (unsigned int x, long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f43 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> 1) | (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned int +f44 (unsigned int x, int y __attribute__((unused))) +{ + return (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x << 1); +} + +unsigned short int +f45 (unsigned short int x, int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned short int +f46 (unsigned short int x, long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))); +} + +unsigned char +f47 (unsigned char x, int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned char +f48 (unsigned char x, long int y) +{ + return (x >> y) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))); +} + +unsigned int +f49 (unsigned int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); +} + +unsigned int +f50 (unsigned int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> y); +} + +unsigned int +f51 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> 1); +} + +unsigned int +f52 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); +} + +unsigned short int +f53 (unsigned short int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); +} + +unsigned short int +f54 (unsigned short int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> y); +} + +unsigned char +f55 (unsigned char x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); +} + +unsigned char +f56 (unsigned char x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> y); +} + +unsigned int +f57 (unsigned int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> y); +} + +unsigned int +f58 (unsigned int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> y); +} + +unsigned int +f59 (unsigned int x, int y __attribute__((unused))) +{ + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> 1); +} + +unsigned int +f60 (unsigned int x, int y __attribute__((unused))) +{ + return (x << 1) ^ (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))); +} + +unsigned short int +f61 (unsigned short int x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x >> y); +} + +unsigned short int +f62 (unsigned short int x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x >> y); +} + +unsigned char +f63 (unsigned char x, int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> y); +} + +unsigned char +f64 (unsigned char x, long int y) +{ + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> y); +} diff --git a/gcc/testsuite/c-c++-common/rotate-4a.c b/gcc/testsuite/c-c++-common/rotate-4a.c new file mode 100644 index 00000000000..450fc22d70c --- /dev/null +++ b/gcc/testsuite/c-c++-common/rotate-4a.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -Wno-overflow" } */ + +#define ROTATE_N "rotate-4.c" + +#include "rotate-1a.c" diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 715082ceefb..e714a5ef244 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -2124,6 +2124,242 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi) } +/* Recognize rotation patterns. Return true if a transformation + applied, otherwise return false. + + We are looking for X with unsigned type T with bitsize B, OP being + +, | or ^, some type T2 wider than T and + (X << CNT1) OP (X >> CNT2) iff CNT1 + CNT2 == B + ((T) ((T2) X << CNT1)) OP ((T) ((T2) X >> CNT2)) iff CNT1 + CNT2 == B + (X << Y) OP (X >> (B - Y)) + (X << (int) Y) OP (X >> (int) (B - Y)) + ((T) ((T2) X << Y)) OP ((T) ((T2) X >> (B - Y))) + ((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) (B - Y))) + (X << Y) OP (X >> ((-Y) & (B - 1))) + (X << (int) Y) OP (X >> (int) ((-Y) & (B - 1))) + ((T) ((T2) X << Y)) OP ((T) ((T2) X >> ((-Y) & (B - 1)))) + ((T) ((T2) X << (int) Y)) OP ((T) ((T2) X >> (int) ((-Y) & (B - 1)))) + + and transform these into: + X r<< CNT1 + X r<< Y + + Note, in the patterns with T2 type, the type of OP operands + might be even a signed type, but should have precision B. */ + +static bool +simplify_rotate (gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + tree arg[2], rtype, rotcnt = NULL_TREE; + tree def_arg1[2], def_arg2[2]; + enum tree_code def_code[2]; + tree lhs; + int i; + bool swapped_p = false; + gimple g; + + arg[0] = gimple_assign_rhs1 (stmt); + arg[1] = gimple_assign_rhs2 (stmt); + rtype = TREE_TYPE (arg[0]); + + /* Only create rotates in complete modes. Other cases are not + expanded properly. */ + if (!INTEGRAL_TYPE_P (rtype) + || TYPE_PRECISION (rtype) != GET_MODE_PRECISION (TYPE_MODE (rtype))) + return false; + + for (i = 0; i < 2; i++) + defcodefor_name (arg[i], &def_code[i], &def_arg1[i], &def_arg2[i]); + + /* Look through narrowing conversions. */ + if (CONVERT_EXPR_CODE_P (def_code[0]) + && CONVERT_EXPR_CODE_P (def_code[1]) + && INTEGRAL_TYPE_P (TREE_TYPE (def_arg1[0])) + && INTEGRAL_TYPE_P (TREE_TYPE (def_arg1[1])) + && TYPE_PRECISION (TREE_TYPE (def_arg1[0])) + == TYPE_PRECISION (TREE_TYPE (def_arg1[1])) + && TYPE_PRECISION (TREE_TYPE (def_arg1[0])) > TYPE_PRECISION (rtype) + && has_single_use (arg[0]) + && has_single_use (arg[1])) + { + for (i = 0; i < 2; i++) + { + arg[i] = def_arg1[i]; + defcodefor_name (arg[i], &def_code[i], &def_arg1[i], &def_arg2[i]); + } + } + + /* One operand has to be LSHIFT_EXPR and one RSHIFT_EXPR. */ + for (i = 0; i < 2; i++) + if (def_code[i] != LSHIFT_EXPR && def_code[i] != RSHIFT_EXPR) + return false; + else if (!has_single_use (arg[i])) + return false; + if (def_code[0] == def_code[1]) + return false; + + /* If we've looked through narrowing conversions before, look through + widening conversions from unsigned type with the same precision + as rtype here. */ + if (TYPE_PRECISION (TREE_TYPE (def_arg1[0])) != TYPE_PRECISION (rtype)) + for (i = 0; i < 2; i++) + { + tree tem; + enum tree_code code; + defcodefor_name (def_arg1[i], &code, &tem, NULL); + if (!CONVERT_EXPR_CODE_P (code) + || !INTEGRAL_TYPE_P (TREE_TYPE (tem)) + || TYPE_PRECISION (TREE_TYPE (tem)) != TYPE_PRECISION (rtype)) + return false; + def_arg1[i] = tem; + } + /* Both shifts have to use the same first operand. */ + if (TREE_CODE (def_arg1[0]) != SSA_NAME || def_arg1[0] != def_arg1[1]) + return false; + if (!TYPE_UNSIGNED (TREE_TYPE (def_arg1[0]))) + return false; + + /* CNT1 + CNT2 == B case above. */ + if (host_integerp (def_arg2[0], 1) + && host_integerp (def_arg2[1], 1) + && (unsigned HOST_WIDE_INT) tree_low_cst (def_arg2[0], 1) + + tree_low_cst (def_arg2[1], 1) == TYPE_PRECISION (rtype)) + rotcnt = def_arg2[0]; + else if (TREE_CODE (def_arg2[0]) != SSA_NAME + || TREE_CODE (def_arg2[1]) != SSA_NAME) + return false; + else + { + tree cdef_arg1[2], cdef_arg2[2], def_arg2_alt[2]; + enum tree_code cdef_code[2]; + /* Look through conversion of the shift count argument. + The C/C++ FE cast any shift count argument to integer_type_node. + The only problem might be if the shift count type maximum value + is equal or smaller than number of bits in rtype. */ + for (i = 0; i < 2; i++) + { + def_arg2_alt[i] = def_arg2[i]; + defcodefor_name (def_arg2[i], &cdef_code[i], + &cdef_arg1[i], &cdef_arg2[i]); + if (CONVERT_EXPR_CODE_P (cdef_code[i]) + && INTEGRAL_TYPE_P (TREE_TYPE (cdef_arg1[i])) + && TYPE_PRECISION (TREE_TYPE (cdef_arg1[i])) + > floor_log2 (TYPE_PRECISION (rtype)) + && TYPE_PRECISION (TREE_TYPE (cdef_arg1[i])) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (cdef_arg1[i])))) + { + def_arg2_alt[i] = cdef_arg1[i]; + defcodefor_name (def_arg2_alt[i], &cdef_code[i], + &cdef_arg1[i], &cdef_arg2[i]); + } + } + for (i = 0; i < 2; i++) + /* Check for one shift count being Y and the other B - Y, + with optional casts. */ + if (cdef_code[i] == MINUS_EXPR + && host_integerp (cdef_arg1[i], 0) + && tree_low_cst (cdef_arg1[i], 0) == TYPE_PRECISION (rtype) + && TREE_CODE (cdef_arg2[i]) == SSA_NAME) + { + tree tem; + enum tree_code code; + + if (cdef_arg2[i] == def_arg2[1 - i] + || cdef_arg2[i] == def_arg2_alt[1 - i]) + { + rotcnt = cdef_arg2[i]; + break; + } + defcodefor_name (cdef_arg2[i], &code, &tem, NULL); + if (CONVERT_EXPR_CODE_P (code) + && INTEGRAL_TYPE_P (TREE_TYPE (tem)) + && TYPE_PRECISION (TREE_TYPE (tem)) + > floor_log2 (TYPE_PRECISION (rtype)) + && TYPE_PRECISION (TREE_TYPE (tem)) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (tem))) + && (tem == def_arg2[1 - i] + || tem == def_arg2_alt[1 - i])) + { + rotcnt = tem; + break; + } + } + /* The above sequence isn't safe for Y being 0, + because then one of the shifts triggers undefined behavior. + This alternative is safe even for rotation count of 0. + One shift count is Y and the other (-Y) & (B - 1). */ + else if (cdef_code[i] == BIT_AND_EXPR + && host_integerp (cdef_arg2[i], 0) + && tree_low_cst (cdef_arg2[i], 0) + == TYPE_PRECISION (rtype) - 1 + && TREE_CODE (cdef_arg1[i]) == SSA_NAME) + { + tree tem; + enum tree_code code; + + defcodefor_name (cdef_arg1[i], &code, &tem, NULL); + if (CONVERT_EXPR_CODE_P (code) + && INTEGRAL_TYPE_P (TREE_TYPE (tem)) + && TYPE_PRECISION (TREE_TYPE (tem)) + > floor_log2 (TYPE_PRECISION (rtype)) + && TYPE_PRECISION (TREE_TYPE (tem)) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (tem)))) + defcodefor_name (tem, &code, &tem, NULL); + + if (code == NEGATE_EXPR) + { + if (tem == def_arg2[1 - i] || tem == def_arg2_alt[1 - i]) + { + rotcnt = tem; + break; + } + defcodefor_name (tem, &code, &tem, NULL); + if (CONVERT_EXPR_CODE_P (code) + && INTEGRAL_TYPE_P (TREE_TYPE (tem)) + && TYPE_PRECISION (TREE_TYPE (tem)) + > floor_log2 (TYPE_PRECISION (rtype)) + && TYPE_PRECISION (TREE_TYPE (tem)) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (tem))) + && (tem == def_arg2[1 - i] + || tem == def_arg2_alt[1 - i])) + { + rotcnt = tem; + break; + } + } + } + if (rotcnt == NULL_TREE) + return false; + swapped_p = i != 1; + } + + if (!useless_type_conversion_p (TREE_TYPE (def_arg2[0]), + TREE_TYPE (rotcnt))) + { + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (TREE_TYPE (def_arg2[0]), + NULL), + rotcnt, NULL_TREE); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + rotcnt = gimple_assign_lhs (g); + } + lhs = gimple_assign_lhs (stmt); + if (!useless_type_conversion_p (rtype, TREE_TYPE (def_arg1[0]))) + lhs = make_ssa_name (TREE_TYPE (def_arg1[0]), NULL); + g = gimple_build_assign_with_ops (((def_code[0] == LSHIFT_EXPR) ^ swapped_p) + ? LROTATE_EXPR : RROTATE_EXPR, + lhs, def_arg1[0], rotcnt); + if (!useless_type_conversion_p (rtype, TREE_TYPE (def_arg1[0]))) + { + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign_with_ops (NOP_EXPR, gimple_assign_lhs (stmt), + lhs, NULL_TREE); + } + gsi_replace (gsi, g, false); + return true; +} + /* Perform re-associations of the plus or minus statement STMT that are always permitted. Returns true if the CFG was changed. */ @@ -3114,6 +3350,11 @@ ssa_forward_propagate_and_combine (void) cfg_changed = true; changed = did_something != 0; } + else if ((code == PLUS_EXPR + || code == BIT_IOR_EXPR + || code == BIT_XOR_EXPR) + && simplify_rotate (&gsi)) + changed = true; else if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR) |