[llvm] [InstCombine] Funnel shift with negative amount folds to funnel shift in opposite direction (#138334) (PR #138763)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 6 14:04:09 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: None (sallto)
<details>
<summary>Changes</summary>
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)
I opened this as a non-draft PR, as the second item in #<!-- -->138334 is not directly related to this change, therefore they can be seperate PRs.
---
Full diff: https://github.com/llvm/llvm-project/pull/138763.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+10)
- (modified) llvm/test/Transforms/InstCombine/fsh.ll (+23)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 844e18dd7d8c5..26e7b83f37ca8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2306,6 +2306,16 @@ 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)
+ Value *Y;
+ if (Op0 == Op1 && 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..f05212bccaed8 100644
--- a/llvm/test/Transforms/InstCombine/fsh.ll
+++ b/llvm/test/Transforms/InstCombine/fsh.ll
@@ -1084,3 +1084,26 @@ 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: define i32 @fshl_neg_amount(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; 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: define i32 @fshr_neg_amount(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; 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
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/138763
More information about the llvm-commits
mailing list