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. */