On Sat, 11 May 2013, Jakub Jelinek wrote: > On Sat, May 11, 2013 at 09:05:52AM +0200, Jakub Jelinek wrote: > > > Seems that we ought to have a testcase, even though it probably > > > means scanning the tree dumps to pick up the undefined behaviour. > > > Approved with a testcase. > > > > I have added lots of testcases recently, for rotation by zero perhaps > > something similar to rotate-1a.c from above can be added as rotate-2b.c > > and rotate-4b.c, and test zero rotation. > > Thanks for forcing me to do more testcases, I've actually found a serious > bug in my recent patch. The (X << Y) OP (X >> ((-Y) & (B - 1))) style > patterns can only be recognized as rotates if OP is |, because > while they act as rotates for Y != 0, they act differently for Y == 0. > For (X << Y) OP (X >> (B - Y)) that is not an issue, because for Y == 0 > they trigger undefined behavior. > > Fixed thusly, plus added coverage for rotates by 0. And rotate-5.c > testcase is to test the expmed.c change.
Ok. Thanks, Richard. > 2013-05-10 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/45216 > PR tree-optimization/57157 > * tree-ssa-forwprop.c (simplify_rotate): Only recognize > the (-Y) & (B - 1) variant if OP is |. > * expmed.c (expand_shift_1): For rotations by const0_rtx just > return shifted. Use (-op1) & (prec - 1) as other_amount > instead of prec - op1. > > * c-c++-common/rotate-1.c: Add 32 tests with +. > * c-c++-common/rotate-1a.c: Adjust. > * c-c++-common/rotate-2.c: Add 32 tests with +, expect > only 48 rotates. > * c-c++-common/rotate-2b.c: New test. > * c-c++-common/rotate-3.c: Add 32 tests with +. > * c-c++-common/rotate-4.c: Add 32 tests with +, expect > only 48 rotates. > * c-c++-common/rotate-4b.c: New test. > * c-c++-common/rotate-5.c: New test. > > --- gcc/tree-ssa-forwprop.c.jj 2013-05-10 10:39:13.000000000 +0200 > +++ gcc/tree-ssa-forwprop.c 2013-05-11 09:57:39.627194037 +0200 > @@ -2135,10 +2135,10 @@ simplify_bitwise_binary (gimple_stmt_ite > (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)))) > + (X << Y) | (X >> ((-Y) & (B - 1))) > + (X << (int) Y) | (X >> (int) ((-Y) & (B - 1))) > + ((T) ((T2) X << Y)) | ((T) ((T2) X >> ((-Y) & (B - 1)))) > + ((T) ((T2) X << (int) Y)) | ((T) ((T2) X >> (int) ((-Y) & (B - 1)))) > > and transform these into: > X r<< CNT1 > @@ -2293,7 +2293,8 @@ simplify_rotate (gimple_stmt_iterator *g > && 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_CODE (cdef_arg1[i]) == SSA_NAME > + && gimple_assign_rhs_code (stmt) == BIT_IOR_EXPR) > { > tree tem; > enum tree_code code; > --- gcc/expmed.c.jj 2013-05-07 10:26:46.000000000 +0200 > +++ gcc/expmed.c 2013-05-11 09:11:54.087412982 +0200 > @@ -2166,7 +2166,8 @@ expand_shift_1 (enum tree_code code, enu > { > /* If we have been unable to open-code this by a rotation, > do it as the IOR of two shifts. I.e., to rotate A > - by N bits, compute (A << N) | ((unsigned) A >> (C - N)) > + by N bits, compute > + (A << N) | ((unsigned) A >> ((-N) & (C - 1))) > where C is the bitsize of A. > > It is theoretically possible that the target machine might > @@ -2181,14 +2182,22 @@ expand_shift_1 (enum tree_code code, enu > rtx temp1; > > new_amount = op1; > - if (CONST_INT_P (op1)) > + if (op1 == const0_rtx) > + return shifted; > + else if (CONST_INT_P (op1)) > other_amount = GEN_INT (GET_MODE_BITSIZE (mode) > - INTVAL (op1)); > else > - other_amount > - = simplify_gen_binary (MINUS, GET_MODE (op1), > - GEN_INT (GET_MODE_PRECISION (mode)), > - op1); > + { > + other_amount > + = simplify_gen_unary (NEG, GET_MODE (op1), > + op1, GET_MODE (op1)); > + other_amount > + = simplify_gen_binary (AND, GET_MODE (op1), > + other_amount, > + GEN_INT (GET_MODE_PRECISION (mode) > + - 1)); > + } > > shifted = force_reg (mode, shifted); > > --- gcc/testsuite/c-c++-common/rotate-1.c.jj 2013-05-10 10:39:13.000000000 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-1.c 2013-05-11 10:11:22.725252954 > +0200 > @@ -1,7 +1,7 @@ > /* Check rotate pattern detection. */ > /* { dg-do compile } */ > /* { dg-options "-O2 -fdump-tree-optimized" } */ > -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 96 "optimized" } } */ > /* { dg-final { cleanup-tree-dump "optimized" } } */ > > unsigned int > @@ -387,3 +387,195 @@ f64 (unsigned char x, unsigned long int > { > return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); > } > + > +unsigned int > +f65 (unsigned int x, unsigned int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f66 (unsigned int x, unsigned long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f67 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned int > +f68 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); > +} > + > +unsigned short int > +f69 (unsigned short int x, unsigned int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned short int > +f70 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned char > +f71 (unsigned char x, unsigned int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned char > +f72 (unsigned char x, unsigned long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned int > +f73 (unsigned int x, unsigned int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f74 (unsigned int x, unsigned long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f75 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned int > +f76 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); > +} > + > +unsigned short int > +f77 (unsigned short int x, unsigned int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned short int > +f78 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned char > +f79 (unsigned char x, unsigned int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned char > +f80 (unsigned char x, unsigned long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned int > +f81 (unsigned int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); > +} > + > +unsigned int > +f82 (unsigned int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); > +} > + > +unsigned int > +f83 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); > +} > + > +unsigned int > +f84 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned short int > +f85 (unsigned short int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); > +} > + > +unsigned short int > +f86 (unsigned short int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); > +} > + > +unsigned char > +f87 (unsigned char x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ - y)) + (x >> y); > +} > + > +unsigned char > +f88 (unsigned char x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ - y)) + (x >> y); > +} > + > +unsigned int > +f89 (unsigned int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); > +} > + > +unsigned int > +f90 (unsigned int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); > +} > + > +unsigned int > +f91 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); > +} > + > +unsigned int > +f92 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned short int > +f93 (unsigned short int x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); > +} > + > +unsigned short int > +f94 (unsigned short int x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); > +} > + > +unsigned char > +f95 (unsigned char x, unsigned int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); > +} > + > +unsigned char > +f96 (unsigned char x, unsigned long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); > +} > --- gcc/testsuite/c-c++-common/rotate-1a.c.jj 2013-05-10 10:39:13.000000000 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-1a.c 2013-05-11 10:16:15.702552070 > +0200 > @@ -21,13 +21,18 @@ unsigned int expected[] = { > 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, > +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 }; > > #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) > +D(1) D(2) D(3) D(4) D(5) D(6) D(7) D(8) \ > +F(90) F(91) F(92) F(93) F(94) F(95) F(96) > ALL > > int > --- gcc/testsuite/c-c++-common/rotate-2.c.jj 2013-05-10 10:39:13.000000000 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-2.c 2013-05-11 10:35:38.127716820 > +0200 > @@ -1,7 +1,9 @@ > /* Check rotate pattern detection. */ > /* { dg-do compile } */ > /* { dg-options "-O2 -fdump-tree-optimized" } */ > -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* Rotates should be recognized only in functions with | instead of + or ^, > + or in functions that have constant shift counts (unused attribute on y). > */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 48 "optimized" } } */ > /* { dg-final { cleanup-tree-dump "optimized" } } */ > > unsigned int > @@ -387,3 +389,195 @@ f64 (unsigned char x, unsigned long int > { > return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> > y); > } > + > +unsigned int > +f65 (unsigned int x, unsigned int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f66 (unsigned int x, unsigned long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f67 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f68 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); > +} > + > +unsigned short int > +f69 (unsigned short int x, unsigned int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned short int > +f70 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned char > +f71 (unsigned char x, unsigned int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned char > +f72 (unsigned char x, unsigned long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned int > +f73 (unsigned int x, unsigned int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f74 (unsigned int x, unsigned long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f75 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f76 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > 1); > +} > + > +unsigned short int > +f77 (unsigned short int x, unsigned int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned short int > +f78 (unsigned short int x, unsigned long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned char > +f79 (unsigned char x, unsigned int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned char > +f80 (unsigned char x, unsigned long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned int > +f81 (unsigned int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); > +} > + > +unsigned int > +f82 (unsigned int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); > +} > + > +unsigned int > +f83 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); > +} > + > +unsigned int > +f84 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned short int > +f85 (unsigned short int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); > +} > + > +unsigned short int > +f86 (unsigned short int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); > +} > + > +unsigned char > +f87 (unsigned char x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); > +} > + > +unsigned char > +f88 (unsigned char x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); > +} > + > +unsigned int > +f89 (unsigned int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > y); > +} > + > +unsigned int > +f90 (unsigned int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > y); > +} > + > +unsigned int > +f91 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > 1); > +} > + > +unsigned int > +f92 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned short int > +f93 (unsigned short int x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x > >> y); > +} > + > +unsigned short int > +f94 (unsigned short int x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x > >> y); > +} > + > +unsigned char > +f95 (unsigned char x, unsigned int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> > y); > +} > + > +unsigned char > +f96 (unsigned char x, unsigned long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> > y); > +} > --- gcc/testsuite/c-c++-common/rotate-2b.c.jj 2013-05-11 09:46:48.588912339 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-2b.c 2013-05-11 10:19:22.767376497 > +0200 > @@ -0,0 +1,49 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -Wno-overflow" } */ > + > +extern > +#ifdef __cplusplus > +"C" > +#endif > +void abort (void); > + > +#ifndef ROTATE_N > +#define ROTATE_N "rotate-2.c" > +#endif > + > +#include ROTATE_N > + > +unsigned int expected[] = { > +0x12345678, 0x12345678, 0x2468acf0, 0x91a2b3c, 0x5678, 0x5678, 0x78, 0x78, > +0x12345678, 0x12345678, 0x2468acf0, 0x91a2b3c, 0x5678, 0x5678, 0x78, 0x78, > +0x0, 0x0, 0x2468acf0, 0x91a2b3c, 0x0, 0x0, 0x0, 0x0, > +0x0, 0x0, 0x2468acf0, 0x91a2b3c, 0x0, 0x0, 0x0, 0x0, > +0x12345678, 0x12345678, 0x91a2b3c, 0x2468acf0, 0x5678, 0x5678, 0x78, 0x78, > +0x12345678, 0x12345678, 0x91a2b3c, 0x2468acf0, 0x5678, 0x5678, 0x78, 0x78, > +0x0, 0x0, 0x91a2b3c, 0x2468acf0, 0x0, 0x0, 0x0, 0x0, > +0x0, 0x0, 0x91a2b3c, 0x2468acf0, 0x0, 0x0, 0x0, 0x0, > +0x2468acf0, 0x2468acf0, 0x2468acf0, 0x91a2b3c, 0xacf0, 0xacf0, 0xf0, 0xf0, > +0x2468acf0, 0x2468acf0, 0x2468acf0, 0x91a2b3c, 0xacf0, 0xacf0, 0xf0, 0xf0, > +0x2468acf0, 0x2468acf0, 0x91a2b3c, 0x2468acf0, 0xacf0, 0xacf0, 0xf0, 0xf0, > +0x2468acf0, 0x2468acf0, 0x91a2b3c, 0x2468acf0, 0xacf0, 0xacf0, 0xf0, 0xf0 }; > + > +#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) D(6) D(7) D(8) \ > +F(90) F(91) F(92) F(93) F(94) F(95) F(96) > +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, 0) != expected[n - 1]) > abort (); > + ALL > + return 0; > +#endif > +} > --- gcc/testsuite/c-c++-common/rotate-3.c.jj 2013-05-10 10:39:13.000000000 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-3.c 2013-05-11 10:14:41.003101647 > +0200 > @@ -1,7 +1,7 @@ > /* Check rotate pattern detection. */ > /* { dg-do compile } */ > /* { dg-options "-O2 -fdump-tree-optimized" } */ > -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 96 "optimized" } } */ > /* { dg-final { cleanup-tree-dump "optimized" } } */ > > unsigned int > @@ -387,3 +387,195 @@ f64 (unsigned char x, long int y) > { > return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) ^ (x >> y); > } > + > +unsigned int > +f65 (unsigned int x, int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f66 (unsigned int x, long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)); > +} > + > +unsigned int > +f67 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned int > +f68 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); > +} > + > +unsigned short int > +f69 (unsigned short int x, int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned short int > +f70 (unsigned short int x, long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)); > +} > + > +unsigned char > +f71 (unsigned char x, int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned char > +f72 (unsigned char x, long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ - y)); > +} > + > +unsigned int > +f73 (unsigned int x, int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f74 (unsigned int x, long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - y)); > +} > + > +unsigned int > +f75 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned int > +f76 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); > +} > + > +unsigned short int > +f77 (unsigned short int x, int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned short int > +f78 (unsigned short int x, long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned short) - y)); > +} > + > +unsigned char > +f79 (unsigned char x, int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned char > +f80 (unsigned char x, long int y) > +{ > + return (x << y) + (x >> (__CHAR_BIT__ * sizeof (unsigned char) - y)); > +} > + > +unsigned int > +f81 (unsigned int x, int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); > +} > + > +unsigned int > +f82 (unsigned int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - y)) + (x >> y); > +} > + > +unsigned int > +f83 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_INT__ - 1)) + (x >> 1); > +} > + > +unsigned int > +f84 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - 1)); > +} > + > +unsigned short int > +f85 (unsigned short int x, int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); > +} > + > +unsigned short int > +f86 (unsigned short int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * __SIZEOF_SHORT__ - y)) + (x >> y); > +} > + > +unsigned char > +f87 (unsigned char x, int y) > +{ > + return (x << (__CHAR_BIT__ - y)) + (x >> y); > +} > + > +unsigned char > +f88 (unsigned char x, long int y) > +{ > + return (x << (__CHAR_BIT__ - y)) + (x >> y); > +} > + > +unsigned int > +f89 (unsigned int x, int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); > +} > + > +unsigned int > +f90 (unsigned int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - y)) + (x >> y); > +} > + > +unsigned int > +f91 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned int) - 1)) + (x >> 1); > +} > + > +unsigned int > +f92 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> (__CHAR_BIT__ * sizeof (unsigned int) - 1)); > +} > + > +unsigned short int > +f93 (unsigned short int x, int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); > +} > + > +unsigned short int > +f94 (unsigned short int x, long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned short) - y)) + (x >> y); > +} > + > +unsigned char > +f95 (unsigned char x, int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); > +} > + > +unsigned char > +f96 (unsigned char x, long int y) > +{ > + return (x << (__CHAR_BIT__ * sizeof (unsigned char) - y)) + (x >> y); > +} > --- gcc/testsuite/c-c++-common/rotate-4.c.jj 2013-05-10 10:39:13.000000000 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-4.c 2013-05-11 10:35:56.784601368 > +0200 > @@ -1,7 +1,9 @@ > /* Check rotate pattern detection. */ > /* { dg-do compile } */ > /* { dg-options "-O2 -fdump-tree-optimized" } */ > -/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 64 "optimized" } } */ > +/* Rotates should be recognized only in functions with | instead of + or ^, > + or in functions that have constant shift counts (unused attribute on y). > */ > +/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 48 "optimized" } } */ > /* { dg-final { cleanup-tree-dump "optimized" } } */ > > unsigned int > @@ -387,3 +389,195 @@ f64 (unsigned char x, long int y) > { > return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> > y); > } > + > +unsigned int > +f65 (unsigned int x, int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f66 (unsigned int x, long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f67 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned int > +f68 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); > +} > + > +unsigned short int > +f69 (unsigned short int x, int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned short int > +f70 (unsigned short int x, long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))); > +} > + > +unsigned char > +f71 (unsigned char x, int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned char > +f72 (unsigned char x, long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ - 1))); > +} > + > +unsigned int > +f73 (unsigned int x, int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f74 (unsigned int x, long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f75 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned int > +f76 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > 1); > +} > + > +unsigned short int > +f77 (unsigned short int x, int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned short int > +f78 (unsigned short int x, long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - > 1))); > +} > + > +unsigned char > +f79 (unsigned char x, int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned char > +f80 (unsigned char x, long int y) > +{ > + return (x << y) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - > 1))); > +} > + > +unsigned int > +f81 (unsigned int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); > +} > + > +unsigned int > +f82 (unsigned int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> y); > +} > + > +unsigned int > +f83 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> 1); > +} > + > +unsigned int > +f84 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))); > +} > + > +unsigned short int > +f85 (unsigned short int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); > +} > + > +unsigned short int > +f86 (unsigned short int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> y); > +} > + > +unsigned char > +f87 (unsigned char x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); > +} > + > +unsigned char > +f88 (unsigned char x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> y); > +} > + > +unsigned int > +f89 (unsigned int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > y); > +} > + > +unsigned int > +f90 (unsigned int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > y); > +} > + > +unsigned int > +f91 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> > 1); > +} > + > +unsigned int > +f92 (unsigned int x, int y __attribute__((unused))) > +{ > + return (x << 1) + (x >> ((-1) & (__CHAR_BIT__ * sizeof (unsigned int) - > 1))); > +} > + > +unsigned short int > +f93 (unsigned short int x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x > >> y); > +} > + > +unsigned short int > +f94 (unsigned short int x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x > >> y); > +} > + > +unsigned char > +f95 (unsigned char x, int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> > y); > +} > + > +unsigned char > +f96 (unsigned char x, long int y) > +{ > + return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> > y); > +} > --- gcc/testsuite/c-c++-common/rotate-4b.c.jj 2013-05-11 10:19:37.190287705 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-4b.c 2013-05-11 10:31:46.249115585 > +0200 > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 -Wno-overflow" } */ > + > +#define ROTATE_N "rotate-4.c" > + > +#include "rotate-2b.c" > --- gcc/testsuite/c-c++-common/rotate-5.c.jj 2013-05-11 10:20:17.094179336 > +0200 > +++ gcc/testsuite/c-c++-common/rotate-5.c 2013-05-11 10:29:06.360066035 > +0200 > @@ -0,0 +1,43 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +extern > +#ifdef __cplusplus > +"C" > +#endif > +void abort (void); > + > +#if __CHAR_BIT__ * __SIZEOF_LONG_LONG__ == 64 > +__attribute__((noinline, noclone)) > +unsigned long long > +f1 (unsigned long long x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & 63)); > +} > + > +#if __CHAR_BIT__ * __SIZEOF_INT128__ == 128 > +__attribute__((noinline, noclone)) > +unsigned __int128 > +f2 (unsigned __int128 x, unsigned int y) > +{ > + return (x << y) | (x >> ((-y) & 128)); > +} > +#endif > +#endif > + > +int > +main () > +{ > +#if __CHAR_BIT__ * __SIZEOF_LONG_LONG__ == 64 > + if (f1 (0x123456789abcdef0ULL, 0) != 0x123456789abcdef0ULL) > + abort (); > +#if __CHAR_BIT__ * __SIZEOF_INT128__ == 128 > + if (f2 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64) > + | 0x0fedcba987654321ULL, 0) > + != ((((unsigned __int128) 0x123456789abcdef0ULL) << 64) > + | 0x0fedcba987654321ULL)) > + abort (); > +#endif > +#endif > + return 0; > +} > > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend