[llvm] [InstCombine] Fold rotate patterns with ZExt/Trunc at different Points (PR #142578)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 16 06:00:02 PDT 2025
================
@@ -698,6 +698,104 @@ define i64 @rotateleft_64_zext_neg_mask_amount(i64 %0, i32 %1) {
ret i64 %10
}
+define i64 @rotateright_64_zext_double_conversion(i64 %x, i32 %y) {
+; CHECK-LABEL: @rotateright_64_zext_double_conversion(
+; CHECK-NEXT: [[Z:%.*]] = zext nneg i32 [[Y:%.*]] to i64
+; CHECK-NEXT: [[OR:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Z]])
+; CHECK-NEXT: ret i64 [[OR]]
+;
+ %z = zext i32 %y to i64
+ %neg = sub nsw i32 0, %y
+ %and2 = and i32 %neg, 63
+ %conv = zext i32 %and2 to i64
+ %shl = shl i64 %x, %conv
+ %shr = lshr i64 %x, %z
+ %or = or i64 %shr, %shl
+ ret i64 %or
+}
+
+define i32 @rotateright_32_trunc_early(i32 %x, i64 %y) {
+; CHECK-LABEL: @rotateright_32_trunc_early(
+; CHECK-NEXT: [[Z:%.*]] = trunc i64 [[Y:%.*]] to i32
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Z]])
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %z = trunc i64 %y to i32
+ %neg = sub nsw i32 0, %z
+ %and2 = and i32 %neg, 31
+ %shl = shl i32 %x, %and2
+ %shr = lshr i32 %x, %z
+ %or = or i32 %shr, %shl
+ ret i32 %or
+}
+
+define i32 @rotateright_32_trunc_neg_mask_amount(i32 %x, i64 %y) {
+; CHECK-LABEL: @rotateright_32_trunc_neg_mask_amount(
+; CHECK-NEXT: [[Z:%.*]] = trunc i64 [[Y:%.*]] to i32
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Z]])
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %z = trunc i64 %y to i32
+ %neg = sub i64 0, %y
+ %and2 = and i64 %neg, 31
+ %conv = trunc i64 %and2 to i32
+ %shl = shl i32 %x, %conv
+ %shr = lshr i32 %x, %z
+ %or = or i32 %shr, %shl
+ ret i32 %or
+}
+
+; restrict the shift amount before rotating
+
+define i32 @rotateleft_32_restricted_shamt(i32 %x, i32 %shAmt) {
+; CHECK-LABEL: @rotateleft_32_restricted_shamt(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHAMT:%.*]], 30
+; CHECK-NEXT: [[OR:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[AND]])
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %and = and i32 %shAmt, 30
+ %shl = shl i32 %x, %and
+ %sub = sub i32 0, %and
+ %shr = lshr i32 %x, %sub
+ %or = or i32 %shl, %shr
+ ret i32 %or
+}
----------------
nikic wrote:
This improvement seems unrelated to the extension changes? Can we split it off?
https://github.com/llvm/llvm-project/pull/142578
More information about the llvm-commits
mailing list