Skip to content

Commit 20147c2

Browse files
committed
[InstCombine] Fold binary operators into single minmax intrinsic
1 parent 7734276 commit 20147c2

File tree

4 files changed

+58
-0
lines changed

4 files changed

+58
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,9 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
15351535
if (Instruction *Phi = foldBinopWithPhiOperands(I))
15361536
return Phi;
15371537

1538+
if (Instruction *R = foldBinOpIntoMinMax(I))
1539+
return R;
1540+
15381541
// (A*B)+(A*C) -> A*(B+C) etc
15391542
if (Value *V = foldUsingDistributiveLaws(I))
15401543
return replaceInstUsesWith(I, V);
@@ -2037,6 +2040,20 @@ Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) {
20372040
return BinaryOperator::CreateFSubFMF(Z, XY, &I);
20382041
}
20392042

2043+
// smin(-a, x - a) + a --> smin(x, 0) [2 commuted variants]
2044+
// smin(x - a, -a) + a --> smin(x, 0) [2 commuted variants]
2045+
if (match(&I,
2046+
m_c_FAdd(m_SMin(m_FNeg(m_Value(A)), m_FSub(m_Value(X), m_Value(A))),
2047+
m_Value(A))) ||
2048+
match(&I,
2049+
m_c_FAdd(m_SMin(m_FSub(m_Value(X), m_Value(A)), m_FNeg(m_Value(A))),
2050+
m_Value(A)))) {
2051+
Constant *Zero = Constant::getNullValue(I.getType());
2052+
return replaceInstUsesWith(
2053+
I,
2054+
Builder.CreateIntrinsic(Intrinsic::smin, {I.getType()}, {X, Zero}, &I));
2055+
}
2056+
20402057
// Check for (fadd double (sitofp x), y), see if we can merge this into an
20412058
// integer add followed by a promotion.
20422059
if (Instruction *R = foldFBinOpOfIntCasts(I))
@@ -2310,6 +2327,9 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
23102327
return Res;
23112328
}
23122329

2330+
if (Instruction *R = foldBinOpIntoMinMax(I))
2331+
return R;
2332+
23132333
// Try this before Negator to preserve NSW flag.
23142334
if (Instruction *R = factorizeMathWithShlOps(I, Builder))
23152335
return R;

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,10 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
670670
/// This is a convenience wrapper function for the above two functions.
671671
Instruction *foldBinOpIntoSelectOrPhi(BinaryOperator &I);
672672

673+
/// Given a binary operator with min/max intrinsic as one operand,
674+
/// try to fold it into a single min/max intrinsic call.
675+
Instruction *foldBinOpIntoMinMax(BinaryOperator &I);
676+
673677
Instruction *foldAddWithConstant(BinaryOperator &Add);
674678

675679
Instruction *foldSquareSumInt(BinaryOperator &I);

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,25 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
18331833
return SelectInst::Create(SI->getCondition(), NewTV, NewFV, "", nullptr, SI);
18341834
}
18351835

1836+
Instruction *InstCombinerImpl::foldBinOpIntoMinMax(BinaryOperator &I) {
1837+
Value *LHS = I.getOperand(0);
1838+
Value *RHS = I.getOperand(1);
1839+
MinMaxIntrinsic *MinMax = dyn_cast<MinMaxIntrinsic>(LHS);
1840+
Value* otherOp = RHS;
1841+
if (!MinMax) {
1842+
MinMax = dyn_cast<MinMaxIntrinsic>(RHS);
1843+
otherOp = LHS;
1844+
}
1845+
if (!MinMax) return nullptr;
1846+
Value* X = MinMax->getLHS();
1847+
Value* Y = MinMax->getRHS();
1848+
Value* NewX = BinaryOperator::Create(I.getOpcode(), X, otherOp);
1849+
Value* NewY = BinaryOperator::Create(I.getOpcode(), Y, otherOp);
1850+
Intrinsic::ID InvID = getInverseMinMaxIntrinsic(MinMax->getIntrinsicID());
1851+
Function *F = Intrinsic::getOrInsertDeclaration(I.getModule(), InvID, I.getType());
1852+
return CallInst::Create(F, {NewX, NewY});
1853+
}
1854+
18361855
static Value *simplifyInstructionWithPHI(Instruction &I, PHINode *PN,
18371856
Value *InValue, BasicBlock *InBB,
18381857
const DataLayout &DL,

llvm/test/Transforms/InstCombine/add-min-max.ll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,18 @@ entry:
8383
%res = add nuw nsw i32 %min, %max
8484
ret i32 %res
8585
}
86+
87+
88+
define i32 @sadd_min_neg(i32 %x, i32 %a) {
89+
; CHECK-LABEL: @sadd_min_neg(
90+
; CHECK-NEXT: entry:
91+
; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.smin.i32(i32 [[A:%.*]], i64 5)
92+
; CHECK-NEXT: ret i32 [[RES]]
93+
;
94+
entry:
95+
%neg_a = sub nsw i32 0, %a
96+
%x_minus_a = sub nsw i32 %x, %a
97+
%smin = call i32 @llvm.smin.i32(i32 %neg_a, i32 %x_minus_a)
98+
%res = add nsw i32 %smin, %a
99+
ret i32 %res
100+
}

0 commit comments

Comments
 (0)