[llvm] 1ee9576 - [InstCombine] Funnel shift with negative amount folds to funnel shift in opposite direction (#138334) (#138763)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 7 06:50:55 PDT 2025
Author: sallto
Date: 2025-05-07T15:50:49+02:00
New Revision: 1ee9576ee7b80fe9b965e597041c6b197a333275
URL: https://github.com/llvm/llvm-project/commit/1ee9576ee7b80fe9b965e597041c6b197a333275
DIFF: https://github.com/llvm/llvm-project/commit/1ee9576ee7b80fe9b965e597041c6b197a333275.diff
LOG: [InstCombine] Funnel shift with negative amount folds to funnel shift in opposite direction (#138334) (#138763)
Partially `fixes` #138334.
Combine fshl(X,X,Neg(Y)) into fshr(X,X,Y) and
fshr(X,X,Neg(Y)) into fshl(X,X,Y)
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/fsh.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 3e78b20e41f0d..4716eeb60f0cd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2300,6 +2300,18 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
return BitOp;
}
+ // fshl(X, X, Neg(Y)) --> fshr(X, X, Y)
+ // fshr(X, X, Neg(Y)) --> fshl(X, X, Y)
+ // if BitWidth is a power-of-2
+ Value *Y;
+ if (Op0 == Op1 && isPowerOf2_32(BitWidth) &&
+ match(II->getArgOperand(2), m_Neg(m_Value(Y)))) {
+ Module *Mod = II->getModule();
+ Function *OppositeShift = Intrinsic::getOrInsertDeclaration(
+ Mod, IID == Intrinsic::fshl ? Intrinsic::fshr : Intrinsic::fshl, Ty);
+ return CallInst::Create(OppositeShift, {Op0, Op1, Y});
+ }
+
// fshl(X, 0, Y) --> shl(X, and(Y, BitWidth - 1)) if bitwidth is a
// power-of-2
if (IID == Intrinsic::fshl && isPowerOf2_32(BitWidth) &&
diff --git a/llvm/test/Transforms/InstCombine/fsh.ll b/llvm/test/Transforms/InstCombine/fsh.ll
index 3ff4f9a2abf33..862853f992968 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1084,3 +1084,72 @@ define i8 @fshl_range_trunc(i1 %x) {
%tr = trunc nsw i32 %fshl to i8
ret i8 %tr
}
+
+;; Issue #138334 negative rotate amounts can be folded into the opposite direction
+define i32 @fshl_neg_amount(i32 %x, i32 %y) {
+; CHECK-LABEL: @fshl_neg_amount(
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %n = sub i32 0, %y
+ %r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %n)
+ ret i32 %r
+}
+
+define i32 @fshr_neg_amount(i32 %x, i32 %y) {
+; CHECK-LABEL: @fshr_neg_amount(
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]])
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %n = sub i32 0, %y
+ %r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %n)
+ ret i32 %r
+}
+
+;; negative test, funnel shift is not a rotate
+
+define i32 @fshl_neg_amount_non_rotate(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @fshl_neg_amount_non_rotate(
+; CHECK-NEXT: [[N:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[Z:%.*]], i32 [[N]])
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %n = sub i32 0, %y
+ %r = call i32 @llvm.fshl.i32(i32 %x, i32 %z, i32 %n)
+ ret i32 %r
+}
+
+define i32 @fshr_neg_amount_non_rotate(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @fshr_neg_amount_non_rotate(
+; CHECK-NEXT: [[N:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[Z:%.*]], i32 [[N]])
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %n = sub i32 0, %y
+ %r = call i32 @llvm.fshr.i32(i32 %x, i32 %z, i32 %n)
+ ret i32 %r
+}
+
+;; negative test, bitwidth is not a power of two
+
+define i31 @fshl_neg_amount_non_power_two(i31 %x, i31 %y) {
+; CHECK-LABEL: @fshl_neg_amount_non_power_two(
+; CHECK-NEXT: [[N:%.*]] = sub i31 0, [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = call i31 @llvm.fshl.i31(i31 [[X:%.*]], i31 [[X]], i31 [[N]])
+; CHECK-NEXT: ret i31 [[R]]
+;
+ %n = sub i31 0, %y
+ %r = call i31 @llvm.fshl.i31(i31 %x, i31 %x, i31 %n)
+ ret i31 %r
+}
+
+define i31 @fshr_neg_amount_non_power_two(i31 %x, i31 %y) {
+; CHECK-LABEL: @fshr_neg_amount_non_power_two(
+; CHECK-NEXT: [[N:%.*]] = sub i31 0, [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = call i31 @llvm.fshr.i31(i31 [[X:%.*]], i31 [[X]], i31 [[N]])
+; CHECK-NEXT: ret i31 [[R]]
+;
+ %n = sub i31 0, %y
+ %r = call i31 @llvm.fshr.i31(i31 %x, i31 %x, i31 %n)
+ ret i31 %r
+}
More information about the llvm-commits
mailing list