[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:03:32 PDT 2025
https://github.com/sallto created https://github.com/llvm/llvm-project/pull/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)
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.
>From a2b3cd81b835d2bfd05320f048c4c37ab1882167 Mon Sep 17 00:00:00 2001
From: sallto <thomas at saller.com.de>
Date: Tue, 6 May 2025 20:40:56 +0000
Subject: [PATCH] [InstCombine] Funnel shift with negative amount folds to
funnel shift in opposite direction (#138334)
Combine fshl(X,X,Neg(Y)) into fshr(X,X,Y) and
fshr(X,X,Neg(Y)) into fshl(X,X,Y).
Confirmed here: https://alive2.llvm.org/ce/z/tX9iyE
---
.../InstCombine/InstCombineCalls.cpp | 10 ++++++++
llvm/test/Transforms/InstCombine/fsh.ll | 23 +++++++++++++++++++
2 files changed, 33 insertions(+)
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
+}
More information about the llvm-commits
mailing list