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