On October 13, 2017 9:36:48 PM GMT+02:00, Jakub Jelinek <ja...@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  <ja...@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

Reply via email to