Skip to content

Commit a2b3cd8

Browse files
committed
[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
1 parent 7581aa1 commit a2b3cd8

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2306,6 +2306,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
23062306
return BitOp;
23072307
}
23082308

2309+
// fshl(X, X, Neg(Y)) --> fshr(X, X, Y)
2310+
// fshr(X, X, Neg(Y)) --> fshl(X, X, Y)
2311+
Value *Y;
2312+
if (Op0 == Op1 && match(II->getArgOperand(2), m_Neg(m_Value(Y)))) {
2313+
Module *Mod = II->getModule();
2314+
Function *OppositeShift = Intrinsic::getOrInsertDeclaration(
2315+
Mod, IID == Intrinsic::fshl ? Intrinsic::fshr : Intrinsic::fshl, Ty);
2316+
return CallInst::Create(OppositeShift, {Op0, Op1, Y});
2317+
}
2318+
23092319
// fshl(X, 0, Y) --> shl(X, and(Y, BitWidth - 1)) if bitwidth is a
23102320
// power-of-2
23112321
if (IID == Intrinsic::fshl && isPowerOf2_32(BitWidth) &&

llvm/test/Transforms/InstCombine/fsh.ll

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,3 +1084,26 @@ define i8 @fshl_range_trunc(i1 %x) {
10841084
%tr = trunc nsw i32 %fshl to i8
10851085
ret i8 %tr
10861086
}
1087+
1088+
;; Issue #138334 negative rotate amounts can be folded into the opposite direction
1089+
define i32 @fshl_neg_amount(i32 %x, i32 %y) {
1090+
; CHECK-LABEL: define i32 @fshl_neg_amount(
1091+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
1092+
; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X]], i32 [[X]], i32 [[Y]])
1093+
; CHECK-NEXT: ret i32 [[R]]
1094+
;
1095+
%n = sub i32 0, %y
1096+
%r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %n)
1097+
ret i32 %r
1098+
}
1099+
1100+
define i32 @fshr_neg_amount(i32 %x, i32 %y) {
1101+
; CHECK-LABEL: define i32 @fshr_neg_amount(
1102+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
1103+
; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X]], i32 [[X]], i32 [[Y]])
1104+
; CHECK-NEXT: ret i32 [[R]]
1105+
;
1106+
%n = sub i32 0, %y
1107+
%r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %n)
1108+
ret i32 %r
1109+
}

0 commit comments

Comments
 (0)