Hi all,

A rotate of a signed integer is not recognized so far.

  int32_t f (int32_t x)
  {
    return (x << 5) | (int32_t)((uint32_t)x >> 27);
  }

The code above is unoptimized in contrast to a version consisting only
of unsigned integers.  I'm wondering if this is intended or not.  Since
GCC has well defined behavior for shifts where the first operand is
signed, I assumed that this also holds for rotates.

The attached patch adds a pattern to match.pd for such signed rotates.
Any comments about this?

Note, for the sake of simplicity the attached patch does not handle the
case where the input is a signed integer and the result is an unsigned,
i.e., the following case is not covered:

  uint32_t f (int32_t x)
  {
    return (x << 5) | ((uint32_t)x >> 27);
  }

My gut feeling was that it's not worth it to have another pattern for
such an impure rotate. Maybe I'm wrong?

Cheers,
Stefan
diff --git a/gcc/match.pd b/gcc/match.pd
index 9cb37740f1e..0297f8c9c89 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2986,6 +2986,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      { tree rotate_type = TREE_TYPE (@0); }
       (convert (rotate (convert:rotate_type @1) @2))))))
 
+/* Recognize a signed rotate: assume that X is signed and C1+C2=width(X) holds,
+   then (X << C1) | (s)((u)X >> C2) -> X r>> C2 where (s) and (u) denote the
+   signed and unsigned types of X, respectively.  */
+(simplify
+ (bit_ior
+  (lshift @0 INTEGER_CST@1)
+  (convert (rshift@3 (convert @0) INTEGER_CST@2)))
+ (if (wi::eq_p (wi::add (wi::to_wide (@1), wi::to_wide (@2)),
+               TYPE_PRECISION (TREE_TYPE (@0)))
+      && TYPE_UNSIGNED (TREE_TYPE (@3)))
+  (rrotate @0 @2)))
+
 /* Simplifications of conversions.  */
 
 /* Basic strip-useless-type-conversions / strip_nops.  */

Reply via email to