diff mbox series

Improve simplify_rotate (PR middle-end/62263, PR middle-end/82498)

Message ID 20171013193648.GL14653@tucnak
State New
Headers show
Series Improve simplify_rotate (PR middle-end/62263, PR middle-end/82498) | expand

Commit Message

Jakub Jelinek Oct. 13, 2017, 7:36 p.m. UTC
Hi!

The forwprop rotate pattern recognizer is able to detect various
patterns, but for the case where we want to support all rotate
counts without UB, it requires
Y &= B - 1;
R = (X << Y) | (X >> ((-Y) & (B - 1)));
where
R = (X << (Y & (B - 1))) | (X >> ((-Y) & (B - 1)));
is another reasonable way to write the same thing (don't mask it
for the case of negation twice).

The following patch teaches forwprop to handle that.

Also, we weren't recognizing rotates of constant X by variable
shift count Y.

And finally, I've noticed there is a missing check that B is a power of
two, which matters for the & (B - 1) style patterns - if it is
not a pow2p, then it isn't doing what we expect it to be.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-10-13  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/62263
	PR middle-end/82498
	* tree-ssa-forwprop.c (simplify_rotate): Allow def_arg1[N]
	to be any operand_equal_p operands.  For & (B - 1) require
	B to be power of 2.  Recognize
	(X << (Y & (B - 1))) | (X >> ((-Y) & (B - 1))) and similar patterns.

	* c-c++-common/rotate-5.c (f2): New function.  Move old
	function to ...
	(f4): ... this.  Use 127 instead of 128.
	(f3, f5, f6): New functions.
	(main): Test all f[1-6] functions, with both 0 and 1 as
	second arguments.
	* c-c++-common/rotate-6.c: New test.
	* c-c++-common/rotate-6a.c: New test.
	* c-c++-common/rotate-7.c: New test.
	* c-c++-common/rotate-7a.c: New test.
	* c-c++-common/rotate-8.c: New test.


	Jakub

Comments

Richard Biener Oct. 14, 2017, 6:28 p.m. UTC | #1
On October 13, 2017 9:36:48 PM GMT+02:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>The forwprop rotate pattern recognizer is able to detect various
>patterns, but for the case where we want to support all rotate
>counts without UB, it requires
>Y &= B - 1;
>R = (X << Y) | (X >> ((-Y) & (B - 1)));
>where
>R = (X << (Y & (B - 1))) | (X >> ((-Y) & (B - 1)));
>is another reasonable way to write the same thing (don't mask it
>for the case of negation twice).
>
>The following patch teaches forwprop to handle that.
>
>Also, we weren't recognizing rotates of constant X by variable
>shift count Y.
>
>And finally, I've noticed there is a missing check that B is a power of
>two, which matters for the & (B - 1) style patterns - if it is
>not a pow2p, then it isn't doing what we expect it to be.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK. 

Richard. 

>2017-10-13  Jakub Jelinek  <jakub@redhat.com>
>
>	PR middle-end/62263
>	PR middle-end/82498
>	* tree-ssa-forwprop.c (simplify_rotate): Allow def_arg1[N]
>	to be any operand_equal_p operands.  For & (B - 1) require
>	B to be power of 2.  Recognize
>	(X << (Y & (B - 1))) | (X >> ((-Y) & (B - 1))) and similar patterns.
>
>	* c-c++-common/rotate-5.c (f2): New function.  Move old
>	function to ...
>	(f4): ... this.  Use 127 instead of 128.
>	(f3, f5, f6): New functions.
>	(main): Test all f[1-6] functions, with both 0 and 1 as
>	second arguments.
>	* c-c++-common/rotate-6.c: New test.
>	* c-c++-common/rotate-6a.c: New test.
>	* c-c++-common/rotate-7.c: New test.
>	* c-c++-common/rotate-7a.c: New test.
>	* c-c++-common/rotate-8.c: New test.
>
>--- gcc/tree-ssa-forwprop.c.jj	2017-09-14 22:15:12.000000000 +0200
>+++ gcc/tree-ssa-forwprop.c	2017-10-13 14:35:31.763191645 +0200
>@@ -1491,9 +1491,14 @@ defcodefor_name (tree name, enum tree_co
>    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
>+   +, | or ^, some type T2 wider than T.  For:
>    (X << CNT1) OP (X >> CNT2)				iff CNT1 + CNT2 == B
>  ((T) ((T2) X << CNT1)) OP ((T) ((T2) X >> CNT2))	iff CNT1 + CNT2 == B
>+
>+   transform these into:
>+   X r<< CNT1
>+
>+   Or for:
>    (X << Y) OP (X >> (B - Y))
>    (X << (int) Y) OP (X >> (int) (B - Y))
>    ((T) ((T2) X << Y)) OP ((T) ((T2) X >> (B - Y)))
>@@ -1503,12 +1508,23 @@ defcodefor_name (tree name, enum tree_co
>    ((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
>+   transform these into:
>    X r<< Y
> 
>+   Or for:
>+   (X << (Y & (B - 1))) | (X >> ((-Y) & (B - 1)))
>+   (X << (int) (Y & (B - 1))) | (X >> (int) ((-Y) & (B - 1)))
>+   ((T) ((T2) X << (Y & (B - 1)))) | ((T) ((T2) X >> ((-Y) & (B -
>1))))
>+   ((T) ((T2) X << (int) (Y & (B - 1)))) \
>+     | ((T) ((T2) X >> (int) ((-Y) & (B - 1))))
>+
>+   transform these into:
>+   X r<< (Y & (B - 1))
>+
>    Note, in the patterns with T2 type, the type of OP operands
>-   might be even a signed type, but should have precision B.  */
>+   might be even a signed type, but should have precision B.
>+   Expressions with & (B - 1) should be recognized only if B is
>+   a power of 2.  */
> 
> static bool
> simplify_rotate (gimple_stmt_iterator *gsi)
>@@ -1578,7 +1594,9 @@ simplify_rotate (gimple_stmt_iterator *g
> 	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])
>+  if (!operand_equal_for_phi_arg_p (def_arg1[0], def_arg1[1])
>+      || !types_compatible_p (TREE_TYPE (def_arg1[0]),
>+			      TREE_TYPE (def_arg1[1])))
>     return false;
>   if (!TYPE_UNSIGNED (TREE_TYPE (def_arg1[0])))
>     return false;
>@@ -1649,8 +1667,10 @@ simplify_rotate (gimple_stmt_iterator *g
> 	/* 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).  */
>+	   One shift count is Y and the other (-Y) & (B - 1).
>+	   Or one shift count is Y & (B - 1) and the other (-Y) & (B - 1). 
>*/
> 	else if (cdef_code[i] == BIT_AND_EXPR
>+		 && pow2p_hwi (TYPE_PRECISION (rtype))
> 		 && tree_fits_shwi_p (cdef_arg2[i])
> 		 && tree_to_shwi (cdef_arg2[i])
> 		    == TYPE_PRECISION (rtype) - 1
>@@ -1675,17 +1695,50 @@ simplify_rotate (gimple_stmt_iterator *g
> 		    rotcnt = tem;
> 		    break;
> 		  }
>-		defcodefor_name (tem, &code, &tem, NULL);
>+		tree tem2;
>+		defcodefor_name (tem, &code, &tem2, NULL);
> 		if (CONVERT_EXPR_CODE_P (code)
>-		    && INTEGRAL_TYPE_P (TREE_TYPE (tem))
>-		    && TYPE_PRECISION (TREE_TYPE (tem))
>+		    && INTEGRAL_TYPE_P (TREE_TYPE (tem2))
>+		    && TYPE_PRECISION (TREE_TYPE (tem2))
> 		       > floor_log2 (TYPE_PRECISION (rtype))
>-		    && type_has_mode_precision_p (TREE_TYPE (tem))
>-		    && (tem == def_arg2[1 - i]
>-			|| tem == def_arg2_alt[1 - i]))
>+		    && type_has_mode_precision_p (TREE_TYPE (tem2)))
> 		  {
>-		    rotcnt = tem;
>-		    break;
>+		    if (tem2 == def_arg2[1 - i]
>+			|| tem2 == def_arg2_alt[1 - i])
>+		      {
>+			rotcnt = tem2;
>+			break;
>+		      }
>+		  }
>+		else
>+		  tem2 = NULL_TREE;
>+
>+		if (cdef_code[1 - i] == BIT_AND_EXPR
>+		    && tree_fits_shwi_p (cdef_arg2[1 - i])
>+		    && tree_to_shwi (cdef_arg2[1 - i])
>+		       == TYPE_PRECISION (rtype) - 1
>+		    && TREE_CODE (cdef_arg1[1 - i]) == SSA_NAME)
>+		  {
>+		    if (tem == cdef_arg1[1 - i]
>+			|| tem2 == cdef_arg1[1 - i])
>+		      {
>+			rotcnt = def_arg2[1 - i];
>+			break;
>+		      }
>+		    tree tem3;
>+		    defcodefor_name (cdef_arg1[1 - i], &code, &tem3, NULL);
>+		    if (CONVERT_EXPR_CODE_P (code)
>+			&& INTEGRAL_TYPE_P (TREE_TYPE (tem3))
>+			&& TYPE_PRECISION (TREE_TYPE (tem3))
>+			   > floor_log2 (TYPE_PRECISION (rtype))
>+			&& type_has_mode_precision_p (TREE_TYPE (tem3)))
>+		      {
>+			if (tem == tem3 || tem2 == tem3)
>+			  {
>+			    rotcnt = def_arg2[1 - i];
>+			    break;
>+			  }
>+		      }
> 		  }
> 	      }
> 	  }
>--- gcc/testsuite/c-c++-common/rotate-5.c.jj	2013-05-13
>13:03:31.000000000 +0200
>+++ gcc/testsuite/c-c++-common/rotate-5.c	2017-10-13 13:36:17.130077499
>+0200
>@@ -15,12 +15,40 @@ f1 (unsigned long long x, unsigned int y
>   return (x << y) | (x >> ((-y) & 63));
> }
> 
>+__attribute__((noinline, noclone))
>+unsigned long long
>+f2 (unsigned long long x, unsigned int y)
>+{
>+  return (x << y) + (x >> ((-y) & 63));
>+}
>+
>+__attribute__((noinline, noclone))
>+unsigned long long
>+f3 (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)
>+f4 (unsigned __int128 x, unsigned int y)
> {
>-  return (x << y) | (x >> ((-y) & 128));
>+  return (x << y) | (x >> ((-y) & 127));
>+}
>+
>+__attribute__((noinline, noclone))
>+unsigned __int128
>+f5 (unsigned __int128 x, unsigned int y)
>+{
>+  return (x << y) + (x >> ((-y) & 127));
>+}
>+
>+__attribute__((noinline, noclone))
>+unsigned __int128
>+f6 (unsigned __int128 x, unsigned int y)
>+{
>+  return (x << y) ^ (x >> ((-y) & 127));
> }
> #endif
> #endif
>@@ -31,12 +59,45 @@ main ()
> #if __CHAR_BIT__ * __SIZEOF_LONG_LONG__ == 64
>   if (f1 (0x123456789abcdef0ULL, 0) != 0x123456789abcdef0ULL)
>     abort ();
>+  if (f2 (0x123456789abcdef0ULL, 0) != 0x2468acf13579bde0ULL)
>+    abort ();
>+  if (f3 (0x123456789abcdef0ULL, 0) != 0)
>+    abort ();
>+  if (f1 (0x123456789abcdef0ULL, 1) != 0x2468acf13579bde0ULL)
>+    abort ();
>+  if (f2 (0x123456789abcdef0ULL, 1) != 0x2468acf13579bde0ULL)
>+    abort ();
>+  if (f3 (0x123456789abcdef0ULL, 1) != 0x2468acf13579bde0ULL)
>+    abort ();
> #if __CHAR_BIT__ * __SIZEOF_INT128__ == 128
>-  if (f2 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
>+  if (f4 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
> 	  | 0x0fedcba987654321ULL, 0)
>       != ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
>           | 0x0fedcba987654321ULL))
>     abort ();
>+  if (f5 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
>+	  | 0x0fedcba987654321ULL, 0)
>+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
>+          | 0x1fdb97530eca8642ULL))
>+    abort ();
>+  if (f6 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
>+	  | 0x0fedcba987654321ULL, 0) != 0)
>+    abort ();
>+  if (f4 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
>+	  | 0x0fedcba987654321ULL, 1)
>+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
>+          | 0x1fdb97530eca8642ULL))
>+    abort ();
>+  if (f5 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
>+	  | 0x0fedcba987654321ULL, 1)
>+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
>+          | 0x1fdb97530eca8642ULL))
>+    abort ();
>+  if (f6 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
>+	  | 0x0fedcba987654321ULL, 1)
>+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
>+          | 0x1fdb97530eca8642ULL))
>+    abort ();
> #endif
> #endif
>   return 0;
>--- gcc/testsuite/c-c++-common/rotate-6.c.jj	2017-10-13
>12:58:07.310836490 +0200
>+++ gcc/testsuite/c-c++-common/rotate-6.c	2017-10-13 13:29:01.901294238
>+0200
>@@ -0,0 +1,582 @@
>+/* Check rotate pattern detection.  */
>+/* { dg-do compile } */
>+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-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" } }
>*/
>+
>+unsigned int
>+f1 (unsigned int x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f2 (unsigned int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f6 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f7 (unsigned char x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f8 (unsigned char x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f9 (unsigned int x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x
>>> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f10 (unsigned int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) |
>(x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned short int
>+f14 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) |
>(x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned char
>+f15 (unsigned char x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (x
>>> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned char
>+f16 (unsigned char x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f18 (unsigned int x, unsigned long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x <<
>(y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f22 (unsigned short int x, unsigned long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x <<
>(y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f23 (unsigned char x, unsigned int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f24 (unsigned char x, unsigned long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f25 (unsigned int x, unsigned int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^
>(x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f26 (unsigned int x, unsigned long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^
>(x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned short int
>+f30 (unsigned short int x, unsigned long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)))
>^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned char
>+f31 (unsigned char x, unsigned int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^
>(x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned char
>+f32 (unsigned char x, unsigned long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^
>(x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned int
>+f33 (unsigned int x, unsigned int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x <<
>((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f34 (unsigned int x, unsigned long int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x <<
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f38 (unsigned short int x, unsigned long int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x <<
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f39 (unsigned char x, unsigned int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ - 1))) | (x << ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f40 (unsigned char x, unsigned long int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ - 1))) | (x << ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f41 (unsigned int x, unsigned int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x
><< ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f42 (unsigned int x, unsigned long int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) |
>(x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned short int
>+f46 (unsigned short int x, unsigned long int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) |
>(x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned char
>+f47 (unsigned char x, unsigned int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (x
><< ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned char
>+f48 (unsigned char x, unsigned long int y)
>+{
>+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f50 (unsigned int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >>
>(y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f54 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >>
>(y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f55 (unsigned char x, unsigned int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f56 (unsigned char x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f57 (unsigned int x, unsigned int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f58 (unsigned int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned short int
>+f62 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)))
>^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned char
>+f63 (unsigned char x, unsigned int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned char
>+f64 (unsigned char x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned int
>+f65 (unsigned int x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f66 (unsigned int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f70 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f71 (unsigned char x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f72 (unsigned char x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f73 (unsigned int x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x
>>> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f74 (unsigned int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) +
>(x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned short int
>+f78 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) +
>(x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned char
>+f79 (unsigned char x, unsigned int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x
>>> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned char
>+f80 (unsigned char x, unsigned long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f82 (unsigned int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >>
>(y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f86 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >>
>(y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f87 (unsigned char x, unsigned int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f88 (unsigned char x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f89 (unsigned int x, unsigned int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) +
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f90 (unsigned int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) +
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned short int
>+f94 (unsigned short int x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)))
>+ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned char
>+f95 (unsigned char x, unsigned int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) +
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned char
>+f96 (unsigned char x, unsigned long int y)
>+{
>+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) +
>(x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>--- gcc/testsuite/c-c++-common/rotate-6a.c.jj	2017-10-13
>12:58:10.977791838 +0200
>+++ gcc/testsuite/c-c++-common/rotate-6a.c	2017-10-13
>13:24:05.786890355 +0200
>@@ -0,0 +1,6 @@
>+/* { dg-do run } */
>+/* { dg-options "-O2 -Wno-overflow" } */
>+
>+#define ROTATE_N "rotate-6.c"
>+
>+#include "rotate-1a.c"
>--- gcc/testsuite/c-c++-common/rotate-7.c.jj	2017-10-13
>13:40:16.575272270 +0200
>+++ gcc/testsuite/c-c++-common/rotate-7.c	2017-10-13 13:41:16.843566194
>+0200
>@@ -0,0 +1,582 @@
>+/* Check rotate pattern detection.  */
>+/* { dg-do compile } */
>+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-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" } }
>*/
>+
>+unsigned int
>+f1 (unsigned int x, int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f2 (unsigned int x, long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f6 (unsigned short int x, long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >>
>((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f7 (unsigned char x, int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f8 (unsigned char x, long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f9 (unsigned int x, int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x
>>> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f10 (unsigned int x, long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) |
>(x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned short int
>+f14 (unsigned short int x, long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) |
>(x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
>+}
>+
>+unsigned char
>+f15 (unsigned char x, int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (x
>>> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
>+}
>+
>+unsigned char
>+f16 (unsigned char x, long int y)
>+{
>+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+unsigned int
>+f18 (unsigned int x, long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x <<
>(y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
>+}
>+
>+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned short int
>+f22 (unsigned short int x, long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x <<
>(y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
>+}
>+
>+unsigned char
>+f23 (unsigned char x, int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned char
>+f24 (unsigned char x, long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__
>- 1)));
>+}
>+
>+unsigned int
>+f25 (unsigned int x, int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^
>(x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+unsigned int
>+f26 (unsigned int x, long int y)
>+{
>+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^
>(x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
>+}
>+
>+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__((unu
diff mbox series

Patch

--- gcc/tree-ssa-forwprop.c.jj	2017-09-14 22:15:12.000000000 +0200
+++ gcc/tree-ssa-forwprop.c	2017-10-13 14:35:31.763191645 +0200
@@ -1491,9 +1491,14 @@  defcodefor_name (tree name, enum tree_co
    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
+   +, | or ^, some type T2 wider than T.  For:
    (X << CNT1) OP (X >> CNT2)				iff CNT1 + CNT2 == B
    ((T) ((T2) X << CNT1)) OP ((T) ((T2) X >> CNT2))	iff CNT1 + CNT2 == B
+
+   transform these into:
+   X r<< CNT1
+
+   Or for:
    (X << Y) OP (X >> (B - Y))
    (X << (int) Y) OP (X >> (int) (B - Y))
    ((T) ((T2) X << Y)) OP ((T) ((T2) X >> (B - Y)))
@@ -1503,12 +1508,23 @@  defcodefor_name (tree name, enum tree_co
    ((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
+   transform these into:
    X r<< Y
 
+   Or for:
+   (X << (Y & (B - 1))) | (X >> ((-Y) & (B - 1)))
+   (X << (int) (Y & (B - 1))) | (X >> (int) ((-Y) & (B - 1)))
+   ((T) ((T2) X << (Y & (B - 1)))) | ((T) ((T2) X >> ((-Y) & (B - 1))))
+   ((T) ((T2) X << (int) (Y & (B - 1)))) \
+     | ((T) ((T2) X >> (int) ((-Y) & (B - 1))))
+
+   transform these into:
+   X r<< (Y & (B - 1))
+
    Note, in the patterns with T2 type, the type of OP operands
-   might be even a signed type, but should have precision B.  */
+   might be even a signed type, but should have precision B.
+   Expressions with & (B - 1) should be recognized only if B is
+   a power of 2.  */
 
 static bool
 simplify_rotate (gimple_stmt_iterator *gsi)
@@ -1578,7 +1594,9 @@  simplify_rotate (gimple_stmt_iterator *g
 	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])
+  if (!operand_equal_for_phi_arg_p (def_arg1[0], def_arg1[1])
+      || !types_compatible_p (TREE_TYPE (def_arg1[0]),
+			      TREE_TYPE (def_arg1[1])))
     return false;
   if (!TYPE_UNSIGNED (TREE_TYPE (def_arg1[0])))
     return false;
@@ -1649,8 +1667,10 @@  simplify_rotate (gimple_stmt_iterator *g
 	/* 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).  */
+	   One shift count is Y and the other (-Y) & (B - 1).
+	   Or one shift count is Y & (B - 1) and the other (-Y) & (B - 1).  */
 	else if (cdef_code[i] == BIT_AND_EXPR
+		 && pow2p_hwi (TYPE_PRECISION (rtype))
 		 && tree_fits_shwi_p (cdef_arg2[i])
 		 && tree_to_shwi (cdef_arg2[i])
 		    == TYPE_PRECISION (rtype) - 1
@@ -1675,17 +1695,50 @@  simplify_rotate (gimple_stmt_iterator *g
 		    rotcnt = tem;
 		    break;
 		  }
-		defcodefor_name (tem, &code, &tem, NULL);
+		tree tem2;
+		defcodefor_name (tem, &code, &tem2, NULL);
 		if (CONVERT_EXPR_CODE_P (code)
-		    && INTEGRAL_TYPE_P (TREE_TYPE (tem))
-		    && TYPE_PRECISION (TREE_TYPE (tem))
+		    && INTEGRAL_TYPE_P (TREE_TYPE (tem2))
+		    && TYPE_PRECISION (TREE_TYPE (tem2))
 		       > floor_log2 (TYPE_PRECISION (rtype))
-		    && type_has_mode_precision_p (TREE_TYPE (tem))
-		    && (tem == def_arg2[1 - i]
-			|| tem == def_arg2_alt[1 - i]))
+		    && type_has_mode_precision_p (TREE_TYPE (tem2)))
 		  {
-		    rotcnt = tem;
-		    break;
+		    if (tem2 == def_arg2[1 - i]
+			|| tem2 == def_arg2_alt[1 - i])
+		      {
+			rotcnt = tem2;
+			break;
+		      }
+		  }
+		else
+		  tem2 = NULL_TREE;
+
+		if (cdef_code[1 - i] == BIT_AND_EXPR
+		    && tree_fits_shwi_p (cdef_arg2[1 - i])
+		    && tree_to_shwi (cdef_arg2[1 - i])
+		       == TYPE_PRECISION (rtype) - 1
+		    && TREE_CODE (cdef_arg1[1 - i]) == SSA_NAME)
+		  {
+		    if (tem == cdef_arg1[1 - i]
+			|| tem2 == cdef_arg1[1 - i])
+		      {
+			rotcnt = def_arg2[1 - i];
+			break;
+		      }
+		    tree tem3;
+		    defcodefor_name (cdef_arg1[1 - i], &code, &tem3, NULL);
+		    if (CONVERT_EXPR_CODE_P (code)
+			&& INTEGRAL_TYPE_P (TREE_TYPE (tem3))
+			&& TYPE_PRECISION (TREE_TYPE (tem3))
+			   > floor_log2 (TYPE_PRECISION (rtype))
+			&& type_has_mode_precision_p (TREE_TYPE (tem3)))
+		      {
+			if (tem == tem3 || tem2 == tem3)
+			  {
+			    rotcnt = def_arg2[1 - i];
+			    break;
+			  }
+		      }
 		  }
 	      }
 	  }
--- gcc/testsuite/c-c++-common/rotate-5.c.jj	2013-05-13 13:03:31.000000000 +0200
+++ gcc/testsuite/c-c++-common/rotate-5.c	2017-10-13 13:36:17.130077499 +0200
@@ -15,12 +15,40 @@  f1 (unsigned long long x, unsigned int y
   return (x << y) | (x >> ((-y) & 63));
 }
 
+__attribute__((noinline, noclone))
+unsigned long long
+f2 (unsigned long long x, unsigned int y)
+{
+  return (x << y) + (x >> ((-y) & 63));
+}
+
+__attribute__((noinline, noclone))
+unsigned long long
+f3 (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)
+f4 (unsigned __int128 x, unsigned int y)
 {
-  return (x << y) | (x >> ((-y) & 128));
+  return (x << y) | (x >> ((-y) & 127));
+}
+
+__attribute__((noinline, noclone))
+unsigned __int128
+f5 (unsigned __int128 x, unsigned int y)
+{
+  return (x << y) + (x >> ((-y) & 127));
+}
+
+__attribute__((noinline, noclone))
+unsigned __int128
+f6 (unsigned __int128 x, unsigned int y)
+{
+  return (x << y) ^ (x >> ((-y) & 127));
 }
 #endif
 #endif
@@ -31,12 +59,45 @@  main ()
 #if __CHAR_BIT__ * __SIZEOF_LONG_LONG__ == 64
   if (f1 (0x123456789abcdef0ULL, 0) != 0x123456789abcdef0ULL)
     abort ();
+  if (f2 (0x123456789abcdef0ULL, 0) != 0x2468acf13579bde0ULL)
+    abort ();
+  if (f3 (0x123456789abcdef0ULL, 0) != 0)
+    abort ();
+  if (f1 (0x123456789abcdef0ULL, 1) != 0x2468acf13579bde0ULL)
+    abort ();
+  if (f2 (0x123456789abcdef0ULL, 1) != 0x2468acf13579bde0ULL)
+    abort ();
+  if (f3 (0x123456789abcdef0ULL, 1) != 0x2468acf13579bde0ULL)
+    abort ();
 #if __CHAR_BIT__ * __SIZEOF_INT128__ == 128
-  if (f2 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
+  if (f4 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
 	  | 0x0fedcba987654321ULL, 0)
       != ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
           | 0x0fedcba987654321ULL))
     abort ();
+  if (f5 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
+	  | 0x0fedcba987654321ULL, 0)
+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
+          | 0x1fdb97530eca8642ULL))
+    abort ();
+  if (f6 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
+	  | 0x0fedcba987654321ULL, 0) != 0)
+    abort ();
+  if (f4 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
+	  | 0x0fedcba987654321ULL, 1)
+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
+          | 0x1fdb97530eca8642ULL))
+    abort ();
+  if (f5 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
+	  | 0x0fedcba987654321ULL, 1)
+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
+          | 0x1fdb97530eca8642ULL))
+    abort ();
+  if (f6 ((((unsigned __int128) 0x123456789abcdef0ULL) << 64)
+	  | 0x0fedcba987654321ULL, 1)
+      != ((((unsigned __int128) 0x2468acf13579bde0ULL) << 64)
+          | 0x1fdb97530eca8642ULL))
+    abort ();
 #endif
 #endif
   return 0;
--- gcc/testsuite/c-c++-common/rotate-6.c.jj	2017-10-13 12:58:07.310836490 +0200
+++ gcc/testsuite/c-c++-common/rotate-6.c	2017-10-13 13:29:01.901294238 +0200
@@ -0,0 +1,582 @@ 
+/* Check rotate pattern detection.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-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" } } */
+
+unsigned int
+f1 (unsigned int x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f2 (unsigned int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f6 (unsigned short int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f7 (unsigned char x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f8 (unsigned char x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f9 (unsigned int x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f10 (unsigned int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f14 (unsigned short int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f15 (unsigned char x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f16 (unsigned char x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f18 (unsigned int x, unsigned long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f22 (unsigned short int x, unsigned long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f23 (unsigned char x, unsigned int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f24 (unsigned char x, unsigned long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f25 (unsigned int x, unsigned int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f26 (unsigned int x, unsigned long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f30 (unsigned short int x, unsigned long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f31 (unsigned char x, unsigned int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f32 (unsigned char x, unsigned long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned int
+f33 (unsigned int x, unsigned int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f34 (unsigned int x, unsigned long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f38 (unsigned short int x, unsigned long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f39 (unsigned char x, unsigned int y)
+{
+  return (x >> (y & (__CHAR_BIT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f40 (unsigned char x, unsigned long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f41 (unsigned int x, unsigned int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f42 (unsigned int x, unsigned long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f46 (unsigned short int x, unsigned long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f47 (unsigned char x, unsigned int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f48 (unsigned char x, unsigned long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f50 (unsigned int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f54 (unsigned short int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f55 (unsigned char x, unsigned int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f56 (unsigned char x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f57 (unsigned int x, unsigned int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f58 (unsigned int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f62 (unsigned short int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f63 (unsigned char x, unsigned int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f64 (unsigned char x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned int
+f65 (unsigned int x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f66 (unsigned int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f70 (unsigned short int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f71 (unsigned char x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f72 (unsigned char x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f73 (unsigned int x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f74 (unsigned int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f78 (unsigned short int x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f79 (unsigned char x, unsigned int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f80 (unsigned char x, unsigned long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f82 (unsigned int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f86 (unsigned short int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f87 (unsigned char x, unsigned int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f88 (unsigned char x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f89 (unsigned int x, unsigned int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f90 (unsigned int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f94 (unsigned short int x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f95 (unsigned char x, unsigned int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f96 (unsigned char x, unsigned long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
--- gcc/testsuite/c-c++-common/rotate-6a.c.jj	2017-10-13 12:58:10.977791838 +0200
+++ gcc/testsuite/c-c++-common/rotate-6a.c	2017-10-13 13:24:05.786890355 +0200
@@ -0,0 +1,6 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -Wno-overflow" } */
+
+#define ROTATE_N "rotate-6.c"
+
+#include "rotate-1a.c"
--- gcc/testsuite/c-c++-common/rotate-7.c.jj	2017-10-13 13:40:16.575272270 +0200
+++ gcc/testsuite/c-c++-common/rotate-7.c	2017-10-13 13:41:16.843566194 +0200
@@ -0,0 +1,582 @@ 
+/* Check rotate pattern detection.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-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" } } */
+
+unsigned int
+f1 (unsigned int x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f2 (unsigned int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f6 (unsigned short int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f7 (unsigned char x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f8 (unsigned char x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f9 (unsigned int x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f10 (unsigned int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f14 (unsigned short int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f15 (unsigned char x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f16 (unsigned char x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f18 (unsigned int x, long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f22 (unsigned short int x, long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f23 (unsigned char x, int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f24 (unsigned char x, long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ - 1))) ^ (x << (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f25 (unsigned int x, int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f26 (unsigned int x, long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f30 (unsigned short int x, long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f31 (unsigned char x, int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f32 (unsigned char x, long int y)
+{
+  return (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned int
+f33 (unsigned int x, int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f34 (unsigned int x, long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f38 (unsigned short int x, long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f39 (unsigned char x, int y)
+{
+  return (x >> (y & (__CHAR_BIT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f40 (unsigned char x, long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ - 1))) | (x << ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f41 (unsigned int x, int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f42 (unsigned int x, long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) | (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f46 (unsigned short int x, long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f47 (unsigned char x, int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f48 (unsigned char x, long int y)
+{
+  return (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) | (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f50 (unsigned int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f54 (unsigned short int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f55 (unsigned char x, int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f56 (unsigned char x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) ^ (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f57 (unsigned int x, int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f58 (unsigned int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f62 (unsigned short int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f63 (unsigned char x, int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f64 (unsigned char x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) ^ (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned int
+f65 (unsigned int x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f66 (unsigned int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f70 (unsigned short int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f71 (unsigned char x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f72 (unsigned char x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ - 1))) + (x >> ((-y) & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f73 (unsigned int x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f74 (unsigned int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f78 (unsigned short int x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f79 (unsigned char x, int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f80 (unsigned char x, long int y)
+{
+  return (x << (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (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 & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f82 (unsigned int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) + (x >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+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 & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned short int
+f86 (unsigned short int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1))) + (x >> (y & (__CHAR_BIT__ * __SIZEOF_SHORT__ - 1)));
+}
+
+unsigned char
+f87 (unsigned char x, int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned char
+f88 (unsigned char x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ - 1))) + (x >> (y & (__CHAR_BIT__ - 1)));
+}
+
+unsigned int
+f89 (unsigned int x, int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+unsigned int
+f90 (unsigned int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned int) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned int) - 1)));
+}
+
+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 & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned short int
+f94 (unsigned short int x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned short) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned short) - 1)));
+}
+
+unsigned char
+f95 (unsigned char x, int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
+
+unsigned char
+f96 (unsigned char x, long int y)
+{
+  return (x << ((-y) & (__CHAR_BIT__ * sizeof (unsigned char) - 1))) + (x >> (y & (__CHAR_BIT__ * sizeof (unsigned char) - 1)));
+}
--- gcc/testsuite/c-c++-common/rotate-7a.c.jj	2017-10-13 13:40:20.043231641 +0200
+++ gcc/testsuite/c-c++-common/rotate-7a.c	2017-10-13 13:40:26.136160259 +0200
@@ -0,0 +1,6 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -Wno-overflow" } */
+
+#define ROTATE_N "rotate-7.c"
+
+#include "rotate-1a.c"
--- gcc/testsuite/c-c++-common/rotate-8.c.jj	2017-10-13 15:56:08.313597324 +0200
+++ gcc/testsuite/c-c++-common/rotate-8.c	2017-10-13 15:55:32.000000000 +0200
@@ -0,0 +1,170 @@ 
+/* PR middle-end/62263 */
+/* PR middle-end/82498 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "r\[<>]\[<>]" 23 "optimized" } } */
+
+unsigned int
+f1 (unsigned int x, unsigned char y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned int
+f2 (unsigned int x, signed char y)
+{
+  y &= __CHAR_BIT__ * __SIZEOF_INT__ - 1;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned int
+f3 (unsigned int x, unsigned char y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))));
+}
+
+unsigned int
+f4 (unsigned int x, unsigned char y)
+{
+  y = y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1);
+  return y ? (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y)) : x;
+}
+
+unsigned int
+f5 (unsigned int x, unsigned char y)
+{
+  y = y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1);
+  return (x << y) | (x >> ((__CHAR_BIT__ * __SIZEOF_INT__ - y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f6 (unsigned int x, unsigned char y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> ((__CHAR_BIT__ * __SIZEOF_INT__ - (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f7 (unsigned int x, unsigned char y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> ((__CHAR_BIT__ * __SIZEOF_INT__ - y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f8 (unsigned int x, unsigned char y)
+{
+  return (x << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (x >> ((-y) & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f9 (unsigned int x, int y)
+{
+  return (0x12345678U << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (0x12345678U >> (-y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f10 (unsigned int x, int y)
+{
+  return (0x12345678U >> (-y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (0x12345678U << (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f11 (unsigned int x, int y)
+{
+  return (0x12345678U >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (0x12345678U << (-y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned int
+f12 (unsigned int x, int y)
+{
+  return (0x12345678U << (-y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1))) | (0x12345678U >> (y & (__CHAR_BIT__ * __SIZEOF_INT__ - 1)));
+}
+
+unsigned
+f13 (unsigned x, unsigned char y)
+{
+  if (y == 0)
+    return x;
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned
+f14 (unsigned x, unsigned y)
+{
+  if (y == 0)
+    return x;
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned
+f15 (unsigned x, unsigned short y)
+{
+  if (y == 0)
+    return x;
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned
+f16 (unsigned x, unsigned char y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  if (y == 0)
+    return x;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned
+f17 (unsigned x, unsigned y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  if (y == 0)
+    return x;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned
+f18 (unsigned x, unsigned short y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  if (y == 0)
+    return x;
+  return (x << y) | (x >> (__CHAR_BIT__ * __SIZEOF_INT__ - y));
+}
+
+unsigned
+f19 (unsigned x, unsigned char y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (((unsigned char) -y) % (__CHAR_BIT__ * __SIZEOF_INT__)));
+}
+
+unsigned
+f20 (unsigned x, unsigned int y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (-y % (__CHAR_BIT__ * __SIZEOF_INT__)));
+}
+
+unsigned
+f21 (unsigned x, unsigned short y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (((unsigned short) -y) % (__CHAR_BIT__ * __SIZEOF_INT__)));
+}
+
+unsigned
+f22 (unsigned x, unsigned char y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (-y & ((__CHAR_BIT__ * __SIZEOF_INT__) - 1)));
+}
+
+unsigned
+f23 (unsigned x, unsigned short y)
+{
+  y %= __CHAR_BIT__ * __SIZEOF_INT__;
+  return (x << y) | (x >> (-y & ((__CHAR_BIT__ * __SIZEOF_INT__) - 1)));
+}