Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,9 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
if (Instruction *Phi = foldBinopWithPhiOperands(I))
return Phi;

if (Instruction *R = foldBinOpIntoMinMax(I))
return R;

// (A*B)+(A*C) -> A*(B+C) etc
if (Value *V = foldUsingDistributiveLaws(I))
return replaceInstUsesWith(I, V);
Expand Down Expand Up @@ -2037,6 +2040,20 @@ Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) {
return BinaryOperator::CreateFSubFMF(Z, XY, &I);
}

// smin(-a, x - a) + a --> smin(x, 0) [2 commuted variants]
// smin(x - a, -a) + a --> smin(x, 0) [2 commuted variants]
if (match(&I,
m_c_FAdd(m_SMin(m_FNeg(m_Value(A)), m_FSub(m_Value(X), m_Value(A))),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why it works... You are matching an fadd instead of an add.

m_Value(A))) ||
match(&I,
m_c_FAdd(m_SMin(m_FSub(m_Value(X), m_Value(A)), m_FNeg(m_Value(A))),
m_Value(A)))) {
Constant *Zero = Constant::getNullValue(I.getType());
return replaceInstUsesWith(
I,
Builder.CreateIntrinsic(Intrinsic::smin, {I.getType()}, {X, Zero}, &I));
}

// Check for (fadd double (sitofp x), y), see if we can merge this into an
// integer add followed by a promotion.
if (Instruction *R = foldFBinOpOfIntCasts(I))
Expand Down Expand Up @@ -2310,6 +2327,9 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
return Res;
}

if (Instruction *R = foldBinOpIntoMinMax(I))
return R;

// Try this before Negator to preserve NSW flag.
if (Instruction *R = factorizeMathWithShlOps(I, Builder))
return R;
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,10 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
/// This is a convenience wrapper function for the above two functions.
Instruction *foldBinOpIntoSelectOrPhi(BinaryOperator &I);

/// Given a binary operator with min/max intrinsic as one operand,
/// try to fold it into a single min/max intrinsic call.
Instruction *foldBinOpIntoMinMax(BinaryOperator &I);

Instruction *foldAddWithConstant(BinaryOperator &Add);

Instruction *foldSquareSumInt(BinaryOperator &I);
Expand Down
19 changes: 19 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,25 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
return SelectInst::Create(SI->getCondition(), NewTV, NewFV, "", nullptr, SI);
}

Instruction *InstCombinerImpl::foldBinOpIntoMinMax(BinaryOperator &I) {
Value *LHS = I.getOperand(0);
Value *RHS = I.getOperand(1);
MinMaxIntrinsic *MinMax = dyn_cast<MinMaxIntrinsic>(LHS);
Value* otherOp = RHS;
if (!MinMax) {
MinMax = dyn_cast<MinMaxIntrinsic>(RHS);
otherOp = LHS;
}
if (!MinMax) return nullptr;
Value* X = MinMax->getLHS();
Value* Y = MinMax->getRHS();
Value* NewX = BinaryOperator::Create(I.getOpcode(), X, otherOp);
Value* NewY = BinaryOperator::Create(I.getOpcode(), Y, otherOp);
Intrinsic::ID InvID = getInverseMinMaxIntrinsic(MinMax->getIntrinsicID());
Function *F = Intrinsic::getOrInsertDeclaration(I.getModule(), InvID, I.getType());
return CallInst::Create(F, {NewX, NewY});
}

static Value *simplifyInstructionWithPHI(Instruction &I, PHINode *PN,
Value *InValue, BasicBlock *InBB,
const DataLayout &DL,
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/Transforms/InstCombine/add-min-max.ll
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,18 @@ entry:
%res = add nuw nsw i32 %min, %max
ret i32 %res
}


define i32 @sadd_min_neg(i32 %x, i32 %a) {
; CHECK-LABEL: @sadd_min_neg(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.smin.i32(i32 [[A:%.*]], i64 5)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI failed: /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/test/Transforms/InstCombine/add-min-max.ll:91:15: error: CHECK-NEXT: expected string not found in input
Do you use LLM to generate check lines instead of UTC?
Please read https://llvm.org/docs/InstCombineContributorGuide.html#tests

; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%neg_a = sub nsw i32 0, %a
%x_minus_a = sub nsw i32 %x, %a
%smin = call i32 @llvm.smin.i32(i32 %neg_a, i32 %x_minus_a)
%res = add nsw i32 %smin, %a
ret i32 %res
}