[llvm] [InstCombine] Create new instructions instead of in-place operand replacement (PR #115988)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 28 09:02:14 PDT 2026
https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/115988
>From 7c8f342eb4e8106851ba5b8bb59743c183503abb Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 13 Nov 2024 11:49:16 +0800
Subject: [PATCH 01/12] [InstCombine] Add pre-commit tests. NFC.
---
llvm/test/Transforms/InstCombine/minmax-fold.ll | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll
index a982225370620..1dd4c5c56fcdf 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fold.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll
@@ -1842,3 +1842,14 @@ define i32 @test_umin_or_neg1_nuw(i32 %x, i32 range(i32 1, 0) %w) {
%r = select i1 %cmp, i32 %x, i32 %sub
ret i32 %r
}
+
+; Make sure that poison-generating/UB-implying parameters are swapped.
+
+define i32 @umax_commute_operand_drop_attrs(i32 %x) {
+; CHECK-LABEL: @umax_commute_operand_drop_attrs(
+; CHECK-NEXT: [[RET:%.*]] = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 noundef range(i32 -10, -8) [[X:%.*]], i32 -10)
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %ret = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 noundef range(i32 -10, -8) -10, i32 %x)
+ ret i32 %ret
+}
>From 5ce8f2e729316824ab9d701d0ad794008c9b2181 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 13 Nov 2024 12:35:41 +0800
Subject: [PATCH 02/12] [InstCombine] Drop poison-generating/UB-implying param
attrs after changing operands
---
llvm/include/llvm/IR/InstrTypes.h | 3 +
.../Transforms/InstCombine/InstCombiner.h | 8 ++
llvm/lib/IR/Instructions.cpp | 11 ++
.../InstCombine/InstCombineCalls.cpp | 100 ++++++++----------
.../Transforms/InstCombine/minmax-fold.ll | 2 +-
5 files changed, 70 insertions(+), 54 deletions(-)
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 5f7df6a4eb6f8..41955adba789d 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1803,6 +1803,9 @@ class CallBase : public Instruction {
paramHasAttr(ArgNo, Attribute::DereferenceableOrNull);
}
+ /// Drop parameter attributes that may cause this instruction to cause UB.
+ void dropPoisonGeneratingAndUBImplyingParamAttrs(unsigned ArgNo);
+
/// Determine if there are is an inalloca argument. Only the last argument can
/// have the inalloca attribute.
bool hasInAllocaArgument() const {
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index 8f9c586066298..79ca12e80b2ef 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -451,6 +451,14 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
return &I;
}
+ /// Replace operand of a call-like instruction and add old operand to the
+ /// worklist. Also drop poison generating and UB implying parameter
+ /// attributes.
+ Instruction *replaceArgOperand(CallBase &I, unsigned OpNum, Value *V) {
+ I.dropPoisonGeneratingAndUBImplyingParamAttrs(OpNum);
+ return replaceOperand(I, OpNum, V);
+ }
+
/// Replace use and add the previously used value to the worklist.
void replaceUse(Use &U, Value *NewValue) {
Value *OldOp = U;
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index faa046729aff6..0e8f1f1f3975c 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
@@ -330,6 +331,16 @@ unsigned CallBase::getNumSubclassExtraOperandsDynamic() const {
return cast<CallBrInst>(this)->getNumIndirectDests() + 1;
}
+void CallBase::dropPoisonGeneratingAndUBImplyingParamAttrs(unsigned ArgNo) {
+ AttributeMask AM = AttributeFuncs::getUBImplyingAttributes();
+ // TODO: Add a helper AttributeFuncs::getPoisonGeneratingAttributes
+ AM.addAttribute(Attribute::NoFPClass);
+ AM.addAttribute(Attribute::Range);
+ AM.addAttribute(Attribute::Alignment);
+ AM.addAttribute(Attribute::NonNull);
+ removeParamAttrs(ArgNo, AM);
+}
+
bool CallBase::isIndirectCall() const {
const Value *V = getCalledOperand();
if (isa<Function>(V) || isa<Constant>(V))
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index ce9e4b836a56e..34991cfbb1a08 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -349,7 +349,7 @@ Instruction *InstCombinerImpl::simplifyMaskedStore(IntrinsicInst &II) {
APInt PoisonElts(DemandedElts.getBitWidth(), 0);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts,
PoisonElts))
- return replaceOperand(II, 0, V);
+ return replaceArgOperand(II, 0, V);
return nullptr;
}
@@ -432,10 +432,10 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
APInt PoisonElts(DemandedElts.getBitWidth(), 0);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts,
PoisonElts))
- return replaceOperand(II, 0, V);
+ return replaceArgOperand(II, 0, V);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(1), DemandedElts,
PoisonElts))
- return replaceOperand(II, 1, V);
+ return replaceArgOperand(II, 1, V);
return nullptr;
}
@@ -517,11 +517,11 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
if (IsTZ) {
// cttz(-x) -> cttz(x)
if (match(Op0, m_Neg(m_Value(X))))
- return IC.replaceOperand(II, 0, X);
+ return IC.replaceArgOperand(II, 0, X);
// cttz(-x & x) -> cttz(x)
if (match(Op0, m_c_And(m_Neg(m_Value(X)), m_Deferred(X))))
- return IC.replaceOperand(II, 0, X);
+ return IC.replaceArgOperand(II, 0, X);
// cttz(sext(x)) -> cttz(zext(x))
if (match(Op0, m_OneUse(m_SExt(m_Value(X))))) {
@@ -545,10 +545,10 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
Value *Y;
SelectPatternFlavor SPF = matchSelectPattern(Op0, X, Y).Flavor;
if (SPF == SPF_ABS || SPF == SPF_NABS)
- return IC.replaceOperand(II, 0, X);
+ return IC.replaceArgOperand(II, 0, X);
if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
- return IC.replaceOperand(II, 0, X);
+ return IC.replaceArgOperand(II, 0, X);
// cttz(shl(%const, %val), 1) --> add(cttz(%const, 1), %val)
if (match(Op0, m_Shl(m_ImmConstant(C), m_Value(X))) &&
@@ -665,13 +665,13 @@ static Instruction *foldCtpop(IntrinsicInst &II, InstCombinerImpl &IC) {
// ctpop(bitreverse(x)) -> ctpop(x)
// ctpop(bswap(x)) -> ctpop(x)
if (match(Op0, m_BitReverse(m_Value(X))) || match(Op0, m_BSwap(m_Value(X))))
- return IC.replaceOperand(II, 0, X);
+ return IC.replaceArgOperand(II, 0, X);
// ctpop(rot(x)) -> ctpop(x)
if ((match(Op0, m_FShl(m_Value(X), m_Value(Y), m_Value())) ||
match(Op0, m_FShr(m_Value(X), m_Value(Y), m_Value()))) &&
X == Y)
- return IC.replaceOperand(II, 0, X);
+ return IC.replaceArgOperand(II, 0, X);
// ctpop(x | -x) -> bitwidth - cttz(x, false)
if (Op0->hasOneUse() &&
@@ -923,6 +923,8 @@ static CallInst *canonicalizeConstantArg0ToArg1(CallInst &Call) {
if (isa<Constant>(Arg0) && !isa<Constant>(Arg1)) {
Call.setArgOperand(0, Arg1);
Call.setArgOperand(1, Arg0);
+ Call.dropPoisonGeneratingAndUBImplyingParamAttrs(0);
+ Call.dropPoisonGeneratingAndUBImplyingParamAttrs(1);
return &Call;
}
return nullptr;
@@ -1067,13 +1069,13 @@ Instruction *InstCombinerImpl::foldIntrinsicIsFPClass(IntrinsicInst &II) {
// is.fpclass (fneg x), mask -> is.fpclass x, (fneg mask)
II.setArgOperand(1, ConstantInt::get(Src1->getType(), fneg(Mask)));
- return replaceOperand(II, 0, FNegSrc);
+ return replaceArgOperand(II, 0, FNegSrc);
}
Value *FAbsSrc;
if (match(Src0, m_FAbs(m_Value(FAbsSrc)))) {
II.setArgOperand(1, ConstantInt::get(Src1->getType(), inverse_fabs(Mask)));
- return replaceOperand(II, 0, FAbsSrc);
+ return replaceArgOperand(II, 0, FAbsSrc);
}
if ((OrderedMask == fcInf || OrderedInvertedMask == fcInf) &&
@@ -2023,8 +2025,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (II->isCommutative()) {
if (auto Pair = matchSymmetricPair(II->getOperand(0), II->getOperand(1))) {
- replaceOperand(*II, 0, Pair->first);
- replaceOperand(*II, 1, Pair->second);
+ replaceArgOperand(*II, 0, Pair->first);
+ replaceArgOperand(*II, 1, Pair->second);
return II;
}
@@ -2062,10 +2064,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (match(IIOperand, m_Neg(m_Value(X)))) {
if (cast<Instruction>(IIOperand)->hasNoSignedWrap() || IntMinIsPoison)
replaceOperand(*II, 1, Builder.getTrue());
- return replaceOperand(*II, 0, X);
+ return replaceArgOperand(*II, 0, X);
}
if (match(IIOperand, m_c_Select(m_Neg(m_Value(X)), m_Deferred(X))))
- return replaceOperand(*II, 0, X);
+ return replaceArgOperand(*II, 0, X);
Value *Y;
// abs(a * abs(b)) -> abs(a * b)
@@ -2075,7 +2077,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
bool NSW =
cast<Instruction>(IIOperand)->hasNoSignedWrap() && IntMinIsPoison;
auto *XY = NSW ? Builder.CreateNSWMul(X, Y) : Builder.CreateMul(X, Y);
- return replaceOperand(*II, 0, XY);
+ return replaceArgOperand(*II, 0, XY);
}
if (std::optional<bool> Known =
@@ -2517,7 +2519,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
match(II->getArgOperand(0), m_FAbs(m_Value(X))) ||
match(II->getArgOperand(0),
m_Intrinsic<Intrinsic::copysign>(m_Value(X), m_Value())))
- return replaceOperand(*II, 0, X);
+ return replaceArgOperand(*II, 0, X);
}
}
if (ConstantFP *Base = dyn_cast<ConstantFP>(II->getArgOperand(0))) {
@@ -2560,7 +2562,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (!ModuloC)
return nullptr;
if (ModuloC != ShAmtC)
- return replaceOperand(*II, 2, ModuloC);
+ return replaceArgOperand(*II, 2, ModuloC);
assert(match(ConstantFoldCompareInstOperands(ICmpInst::ICMP_UGT, WidthC,
ShAmtC, DL),
@@ -2713,8 +2715,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// TODO: If InnerMask == Op1, we could copy attributes from inner
// callsite -> outer callsite.
Value *NewMask = Builder.CreateAnd(II->getArgOperand(1), InnerMask);
- replaceOperand(CI, 0, InnerPtr);
- replaceOperand(CI, 1, NewMask);
+ replaceArgOperand(CI, 0, InnerPtr);
+ replaceArgOperand(CI, 1, NewMask);
Changed = true;
}
@@ -3026,8 +3028,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *A, *B;
if (match(II->getArgOperand(0), m_FNeg(m_Value(A))) &&
match(II->getArgOperand(1), m_FNeg(m_Value(B)))) {
- replaceOperand(*II, 0, A);
- replaceOperand(*II, 1, B);
+ replaceArgOperand(*II, 0, A);
+ replaceArgOperand(*II, 1, B);
return II;
}
@@ -3062,8 +3064,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (ElementCount::isKnownGT(NegatedCount, OtherCount) &&
ElementCount::isKnownLT(OtherCount, RetCount)) {
Value *InverseOtherOp = Builder.CreateFNeg(OtherOp);
- replaceOperand(*II, NegatedOpArg, OpNotNeg);
- replaceOperand(*II, OtherOpArg, InverseOtherOp);
+ replaceArgOperand(*II, NegatedOpArg, OpNotNeg);
+ replaceArgOperand(*II, OtherOpArg, InverseOtherOp);
return II;
}
// (-A) * B -> -(A * B), if it is cheaper to negate the result
@@ -3092,16 +3094,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *Src2 = II->getArgOperand(2);
Value *X, *Y;
if (match(Src0, m_FNeg(m_Value(X))) && match(Src1, m_FNeg(m_Value(Y)))) {
- replaceOperand(*II, 0, X);
- replaceOperand(*II, 1, Y);
+ replaceArgOperand(*II, 0, X);
+ replaceArgOperand(*II, 1, Y);
return II;
}
// fma fabs(x), fabs(x), z -> fma x, x, z
if (match(Src0, m_FAbs(m_Value(X))) &&
match(Src1, m_FAbs(m_Specific(X)))) {
- replaceOperand(*II, 0, X);
- replaceOperand(*II, 1, X);
+ replaceArgOperand(*II, 0, X);
+ replaceArgOperand(*II, 1, X);
return II;
}
@@ -3157,14 +3159,15 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (match(Mag, m_APFloat(MagC)) && MagC->isNegative()) {
APFloat PosMagC = *MagC;
PosMagC.clearSign();
- return replaceOperand(*II, 0, ConstantFP::get(Mag->getType(), PosMagC));
+ return replaceArgOperand(*II, 0,
+ ConstantFP::get(Mag->getType(), PosMagC));
}
// Peek through changes of magnitude's sign-bit. This call rewrites those:
// copysign (fabs X), Sign --> copysign X, Sign
// copysign (fneg X), Sign --> copysign X, Sign
if (match(Mag, m_FAbs(m_Value(X))) || match(Mag, m_FNeg(m_Value(X))))
- return replaceOperand(*II, 0, X);
+ return replaceArgOperand(*II, 0, X);
// copysign(floor(fabs(X)), X) --> copysign(trunc(X), X)
// copysign ignores the sign bit of its magnitude argument (implicit fabs),
@@ -3220,10 +3223,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
}
// fabs (select Cond, -FVal, FVal) --> fabs FVal
if (match(TVal, m_FNeg(m_Specific(FVal))))
- return replaceOperand(*II, 0, FVal);
+ return replaceArgOperand(*II, 0, FVal);
// fabs (select Cond, TVal, -TVal) --> fabs TVal
if (match(FVal, m_FNeg(m_Specific(TVal))))
- return replaceOperand(*II, 0, TVal);
+ return replaceArgOperand(*II, 0, TVal);
}
Value *Magnitude, *Sign;
@@ -3262,7 +3265,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// f(fabs(x)) --> f(x)
// f(copysign(x, y)) --> f(x)
// for f in {cos, cosh}
- return replaceOperand(*II, 0, X);
+ return replaceArgOperand(*II, 0, X);
}
break;
}
@@ -3328,8 +3331,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *NewExp =
Builder.CreateBinaryIntrinsic(Intrinsic::sadd_sat, InnerExp, Exp);
II->setArgOperand(1, NewExp);
+ II->dropPoisonGeneratingAndUBImplyingParamAttrs(1);
II->setFastMathFlags(InnerFlags); // Or the inner flags.
- return replaceOperand(*II, 0, InnerSrc);
+ return replaceArgOperand(*II, 0, InnerSrc);
}
}
@@ -4098,11 +4102,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *Arg = II->getArgOperand(0);
Value *Vect;
- if (Value *NewOp =
- simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- replaceUse(II->getOperandUse(0), NewOp);
- return II;
- }
+ if (Value *NewOp = simplifyReductionOperand(Arg, /*CanReorderLanes=*/true))
+ return replaceArgOperand(*II, 0, NewOp);
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
if (auto *FTy = dyn_cast<FixedVectorType>(Vect->getType()))
@@ -4138,8 +4139,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- replaceUse(II->getOperandUse(0), NewOp);
- return II;
+ return replaceArgOperand(*II, 0, NewOp);
}
// vector.reduce.add.vNiM(splat(%x)) -> mul(%x, N)
@@ -4184,10 +4184,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *Vect;
if (Value *NewOp =
- simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- replaceUse(II->getOperandUse(0), NewOp);
- return II;
- }
+ simplifyReductionOperand(Arg, /*CanReorderLanes=*/true))
+ return replaceArgOperand(*II, 0, NewOp);
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
if (auto *VTy = dyn_cast<VectorType>(Vect->getType()))
@@ -4208,8 +4206,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- replaceUse(II->getOperandUse(0), NewOp);
- return II;
+ return replaceArgOperand(*II, 0, NewOp);
}
// vector_reduce_mul(zext(<n x i1>)), or
@@ -4250,8 +4247,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- replaceUse(II->getOperandUse(0), NewOp);
- return II;
+ return replaceArgOperand(*II, 0, NewOp);
}
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
@@ -4292,8 +4288,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- replaceUse(II->getOperandUse(0), NewOp);
- return II;
+ return replaceArgOperand(*II, 0, NewOp);
}
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
@@ -4327,8 +4322,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
: 0;
Value *Arg = II->getArgOperand(ArgIdx);
if (Value *NewOp = simplifyReductionOperand(Arg, CanReorderLanes)) {
- replaceUse(II->getOperandUse(ArgIdx), NewOp);
- return nullptr;
+ return replaceArgOperand(*II, ArgIdx, NewOp);
}
break;
}
diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll
index 1dd4c5c56fcdf..2cfa0296890ca 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fold.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll
@@ -1847,7 +1847,7 @@ define i32 @test_umin_or_neg1_nuw(i32 %x, i32 range(i32 1, 0) %w) {
define i32 @umax_commute_operand_drop_attrs(i32 %x) {
; CHECK-LABEL: @umax_commute_operand_drop_attrs(
-; CHECK-NEXT: [[RET:%.*]] = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 noundef range(i32 -10, -8) [[X:%.*]], i32 -10)
+; CHECK-NEXT: [[RET:%.*]] = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 [[X:%.*]], i32 -10)
; CHECK-NEXT: ret i32 [[RET]]
;
%ret = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 noundef range(i32 -10, -8) -10, i32 %x)
>From bc201b5e5cc18b8747b80391bbe26d69b4f3e00b Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 15 Nov 2024 11:35:34 +0800
Subject: [PATCH 03/12] [InstCombine] Swap parameter attributes in
`canonicalizeConstantArg0ToArg1`
---
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 11 +++++++++--
llvm/test/Transforms/InstCombine/minmax-fold.ll | 2 +-
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 34991cfbb1a08..2f758abceb5cc 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -923,8 +923,15 @@ static CallInst *canonicalizeConstantArg0ToArg1(CallInst &Call) {
if (isa<Constant>(Arg0) && !isa<Constant>(Arg1)) {
Call.setArgOperand(0, Arg1);
Call.setArgOperand(1, Arg0);
- Call.dropPoisonGeneratingAndUBImplyingParamAttrs(0);
- Call.dropPoisonGeneratingAndUBImplyingParamAttrs(1);
+ auto CallAttr = Call.getAttributes();
+ auto LHSAttr = CallAttr.getParamAttrs(0);
+ auto RHSAttr = CallAttr.getParamAttrs(1);
+ LLVMContext &Ctx = Call.getContext();
+ Call.setAttributes(
+ CallAttr.removeAttributesAtIndex(Ctx, 0)
+ .removeAttributesAtIndex(Ctx, 1)
+ .addParamAttributes(Ctx, 0, AttrBuilder(Ctx, RHSAttr))
+ .addParamAttributes(Ctx, 1, AttrBuilder(Ctx, LHSAttr)));
return &Call;
}
return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll
index 2cfa0296890ca..049d3153ff51c 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fold.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll
@@ -1847,7 +1847,7 @@ define i32 @test_umin_or_neg1_nuw(i32 %x, i32 range(i32 1, 0) %w) {
define i32 @umax_commute_operand_drop_attrs(i32 %x) {
; CHECK-LABEL: @umax_commute_operand_drop_attrs(
-; CHECK-NEXT: [[RET:%.*]] = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 [[X:%.*]], i32 -10)
+; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 noundef range(i32 -10, -8) -10)
; CHECK-NEXT: ret i32 [[RET]]
;
%ret = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 noundef range(i32 -10, -8) -10, i32 %x)
>From d86d4cc571ce4c6b5d46586fea2dc7ea57a4c843 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 15 Nov 2024 11:42:20 +0800
Subject: [PATCH 04/12] [InstCombine] Add more tests. NFC.
---
llvm/test/Transforms/InstCombine/abs-intrinsic.ll | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index 96dfbe4730d0e..f93d0b366ef11 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -227,6 +227,16 @@ define i32 @abs_of_neg(i32 %x) {
ret i32 %b
}
+define i32 @abs_of_neg_range(i32 %x) {
+; CHECK-LABEL: @abs_of_neg_range(
+; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
+; CHECK-NEXT: ret i32 [[B]]
+;
+ %a = sub i32 0, %x
+ %b = call i32 @llvm.abs.i32(i32 range(i32 -10, 0) %a, i1 false)
+ ret i32 %b
+}
+
define <4 x i32> @abs_of_neg_vec(<4 x i32> %x) {
; CHECK-LABEL: @abs_of_neg_vec(
; CHECK-NEXT: [[B:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 true)
>From 8eac0bc37d3f4143f6a635336a8b45462a0dfa7c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 28 Jun 2026 16:56:13 +0800
Subject: [PATCH 05/12] [InstCombine] Fix regression.
---
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 2f758abceb5cc..57fdc3f305fc0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -349,7 +349,7 @@ Instruction *InstCombinerImpl::simplifyMaskedStore(IntrinsicInst &II) {
APInt PoisonElts(DemandedElts.getBitWidth(), 0);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts,
PoisonElts))
- return replaceArgOperand(II, 0, V);
+ return replaceOperand(II, 0, V);
return nullptr;
}
@@ -432,10 +432,10 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
APInt PoisonElts(DemandedElts.getBitWidth(), 0);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts,
PoisonElts))
- return replaceArgOperand(II, 0, V);
+ return replaceOperand(II, 0, V);
if (Value *V = SimplifyDemandedVectorElts(II.getOperand(1), DemandedElts,
PoisonElts))
- return replaceArgOperand(II, 1, V);
+ return replaceOperand(II, 1, V);
return nullptr;
}
>From 6367a416c8c412319ac2f457201c3d8e5f443f97 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 28 Jun 2026 19:58:07 +0800
Subject: [PATCH 06/12] [InstCombine] Avoid in-place modification
---
llvm/include/llvm/IR/InstrTypes.h | 3 -
.../Transforms/InstCombine/InstCombiner.h | 8 --
llvm/lib/IR/Instructions.cpp | 10 --
.../InstCombine/InstCombineCalls.cpp | 132 +++++++++---------
llvm/test/Transforms/InstCombine/bit_ceil.ll | 2 +-
.../InstCombine/ctpop-bswap-bitreverse.ll | 8 +-
llvm/test/Transforms/InstCombine/ctpop.ll | 4 +-
llvm/test/Transforms/InstCombine/cttz-abs.ll | 14 +-
.../Transforms/InstCombine/cttz-negative.ll | 4 +-
.../InstCombine/hyperbolic-functions.ll | 2 +-
.../test/Transforms/InstCombine/intrinsics.ll | 16 +--
.../test/Transforms/InstCombine/is_fpclass.ll | 6 +-
llvm/test/Transforms/InstCombine/powi.ll | 6 +-
13 files changed, 96 insertions(+), 119 deletions(-)
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 41955adba789d..5f7df6a4eb6f8 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1803,9 +1803,6 @@ class CallBase : public Instruction {
paramHasAttr(ArgNo, Attribute::DereferenceableOrNull);
}
- /// Drop parameter attributes that may cause this instruction to cause UB.
- void dropPoisonGeneratingAndUBImplyingParamAttrs(unsigned ArgNo);
-
/// Determine if there are is an inalloca argument. Only the last argument can
/// have the inalloca attribute.
bool hasInAllocaArgument() const {
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index 79ca12e80b2ef..8f9c586066298 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -451,14 +451,6 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
return &I;
}
- /// Replace operand of a call-like instruction and add old operand to the
- /// worklist. Also drop poison generating and UB implying parameter
- /// attributes.
- Instruction *replaceArgOperand(CallBase &I, unsigned OpNum, Value *V) {
- I.dropPoisonGeneratingAndUBImplyingParamAttrs(OpNum);
- return replaceOperand(I, OpNum, V);
- }
-
/// Replace use and add the previously used value to the worklist.
void replaceUse(Use &U, Value *NewValue) {
Value *OldOp = U;
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 0e8f1f1f3975c..413abb9a39e62 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -331,16 +331,6 @@ unsigned CallBase::getNumSubclassExtraOperandsDynamic() const {
return cast<CallBrInst>(this)->getNumIndirectDests() + 1;
}
-void CallBase::dropPoisonGeneratingAndUBImplyingParamAttrs(unsigned ArgNo) {
- AttributeMask AM = AttributeFuncs::getUBImplyingAttributes();
- // TODO: Add a helper AttributeFuncs::getPoisonGeneratingAttributes
- AM.addAttribute(Attribute::NoFPClass);
- AM.addAttribute(Attribute::Range);
- AM.addAttribute(Attribute::Alignment);
- AM.addAttribute(Attribute::NonNull);
- removeParamAttrs(ArgNo, AM);
-}
-
bool CallBase::isIndirectCall() const {
const Value *V = getCalledOperand();
if (isa<Function>(V) || isa<Constant>(V))
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 57fdc3f305fc0..9dc2ab187e5e4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -507,21 +507,20 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
// If ctlz/cttz is only used as a shift amount, set is_zero_poison to true.
if (II.hasOneUse() && match(Op1, m_Zero()) &&
- match(II.user_back(), m_Shift(m_Value(), m_Specific(&II)))) {
- II.dropUBImplyingAttrsAndMetadata();
- return IC.replaceOperand(II, 1, IC.Builder.getTrue());
- }
+ match(II.user_back(), m_Shift(m_Value(), m_Specific(&II))))
+ return CallInst::Create(II.getCalledFunction(),
+ {Op0, IC.Builder.getTrue()});
Constant *C;
if (IsTZ) {
// cttz(-x) -> cttz(x)
if (match(Op0, m_Neg(m_Value(X))))
- return IC.replaceArgOperand(II, 0, X);
+ return CallInst::Create(II.getCalledFunction(), {X, Op1});
// cttz(-x & x) -> cttz(x)
if (match(Op0, m_c_And(m_Neg(m_Value(X)), m_Deferred(X))))
- return IC.replaceArgOperand(II, 0, X);
+ return CallInst::Create(II.getCalledFunction(), {X, Op1});
// cttz(sext(x)) -> cttz(zext(x))
if (match(Op0, m_OneUse(m_SExt(m_Value(X))))) {
@@ -545,10 +544,10 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
Value *Y;
SelectPatternFlavor SPF = matchSelectPattern(Op0, X, Y).Flavor;
if (SPF == SPF_ABS || SPF == SPF_NABS)
- return IC.replaceArgOperand(II, 0, X);
+ return CallInst::Create(II.getCalledFunction(), {X, Op1});
if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
- return IC.replaceArgOperand(II, 0, X);
+ return CallInst::Create(II.getCalledFunction(), {X, Op1});
// cttz(shl(%const, %val), 1) --> add(cttz(%const, 1), %val)
if (match(Op0, m_Shl(m_ImmConstant(C), m_Value(X))) &&
@@ -638,7 +637,8 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
if (!Known.One.isZero() ||
isKnownNonZero(Op0, IC.getSimplifyQuery().getWithInstruction(&II))) {
if (!match(II.getArgOperand(1), m_One()))
- return IC.replaceOperand(II, 1, IC.Builder.getTrue());
+ return CallInst::Create(II.getCalledFunction(),
+ {Op0, IC.Builder.getTrue()});
}
// Add range attribute since known bits can't completely reflect what we know.
@@ -665,13 +665,13 @@ static Instruction *foldCtpop(IntrinsicInst &II, InstCombinerImpl &IC) {
// ctpop(bitreverse(x)) -> ctpop(x)
// ctpop(bswap(x)) -> ctpop(x)
if (match(Op0, m_BitReverse(m_Value(X))) || match(Op0, m_BSwap(m_Value(X))))
- return IC.replaceArgOperand(II, 0, X);
+ return CallInst::Create(II.getCalledFunction(), X);
// ctpop(rot(x)) -> ctpop(x)
if ((match(Op0, m_FShl(m_Value(X), m_Value(Y), m_Value())) ||
match(Op0, m_FShr(m_Value(X), m_Value(Y), m_Value()))) &&
X == Y)
- return IC.replaceArgOperand(II, 0, X);
+ return CallInst::Create(II.getCalledFunction(), X);
// ctpop(x | -x) -> bitwidth - cttz(x, false)
if (Op0->hasOneUse() &&
@@ -1072,18 +1072,17 @@ Instruction *InstCombinerImpl::foldIntrinsicIsFPClass(IntrinsicInst &II) {
II.getFunction()->getAttributes().hasFnAttr(Attribute::StrictFP);
Value *FNegSrc;
- if (match(Src0, m_FNeg(m_Value(FNegSrc)))) {
- // is.fpclass (fneg x), mask -> is.fpclass x, (fneg mask)
-
- II.setArgOperand(1, ConstantInt::get(Src1->getType(), fneg(Mask)));
- return replaceArgOperand(II, 0, FNegSrc);
- }
+ // is.fpclass (fneg x), mask -> is.fpclass x, (fneg mask)
+ if (match(Src0, m_FNeg(m_Value(FNegSrc))))
+ return CallInst::Create(
+ II.getCalledFunction(),
+ {FNegSrc, ConstantInt::get(Src1->getType(), fneg(Mask))});
Value *FAbsSrc;
- if (match(Src0, m_FAbs(m_Value(FAbsSrc)))) {
- II.setArgOperand(1, ConstantInt::get(Src1->getType(), inverse_fabs(Mask)));
- return replaceArgOperand(II, 0, FAbsSrc);
- }
+ if (match(Src0, m_FAbs(m_Value(FAbsSrc))))
+ return CallInst::Create(
+ II.getCalledFunction(),
+ {FAbsSrc, ConstantInt::get(Src1->getType(), inverse_fabs(Mask))});
if ((OrderedMask == fcInf || OrderedInvertedMask == fcInf) &&
(IsOrdered || IsUnordered) && !IsStrict) {
@@ -2032,8 +2031,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (II->isCommutative()) {
if (auto Pair = matchSymmetricPair(II->getOperand(0), II->getOperand(1))) {
- replaceArgOperand(*II, 0, Pair->first);
- replaceArgOperand(*II, 1, Pair->second);
+ replaceOperand(*II, 0, Pair->first);
+ replaceOperand(*II, 1, Pair->second);
+ II->dropPoisonGeneratingAnnotations();
return II;
}
@@ -2068,13 +2068,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// abs(-x) -> abs(x)
Value *X;
- if (match(IIOperand, m_Neg(m_Value(X)))) {
- if (cast<Instruction>(IIOperand)->hasNoSignedWrap() || IntMinIsPoison)
- replaceOperand(*II, 1, Builder.getTrue());
- return replaceArgOperand(*II, 0, X);
- }
+ if (match(IIOperand, m_Neg(m_Value(X))))
+ return CallInst::Create(
+ II->getCalledFunction(),
+ {X,
+ Builder.getInt1(IntMinIsPoison ||
+ cast<Instruction>(IIOperand)->hasNoSignedWrap())});
+
if (match(IIOperand, m_c_Select(m_Neg(m_Value(X)), m_Deferred(X))))
- return replaceArgOperand(*II, 0, X);
+ return CallInst::Create(II->getCalledFunction(),
+ {X, II->getArgOperand(1)});
Value *Y;
// abs(a * abs(b)) -> abs(a * b)
@@ -2084,7 +2087,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
bool NSW =
cast<Instruction>(IIOperand)->hasNoSignedWrap() && IntMinIsPoison;
auto *XY = NSW ? Builder.CreateNSWMul(X, Y) : Builder.CreateMul(X, Y);
- return replaceArgOperand(*II, 0, XY);
+ return CallInst::Create(II->getCalledFunction(),
+ {XY, II->getArgOperand(1)});
}
if (std::optional<bool> Known =
@@ -2526,7 +2530,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
match(II->getArgOperand(0), m_FAbs(m_Value(X))) ||
match(II->getArgOperand(0),
m_Intrinsic<Intrinsic::copysign>(m_Value(X), m_Value())))
- return replaceArgOperand(*II, 0, X);
+ return CallInst::Create(II->getCalledFunction(), {X, Power});
}
}
if (ConstantFP *Base = dyn_cast<ConstantFP>(II->getArgOperand(0))) {
@@ -2569,7 +2573,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (!ModuloC)
return nullptr;
if (ModuloC != ShAmtC)
- return replaceArgOperand(*II, 2, ModuloC);
+ return CallInst::Create(II->getCalledFunction(), {Op0, Op1, ModuloC});
assert(match(ConstantFoldCompareInstOperands(ICmpInst::ICMP_UGT, WidthC,
ShAmtC, DL),
@@ -2722,8 +2726,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// TODO: If InnerMask == Op1, we could copy attributes from inner
// callsite -> outer callsite.
Value *NewMask = Builder.CreateAnd(II->getArgOperand(1), InnerMask);
- replaceArgOperand(CI, 0, InnerPtr);
- replaceArgOperand(CI, 1, NewMask);
+ replaceOperand(CI, 0, InnerPtr);
+ replaceOperand(CI, 1, NewMask);
Changed = true;
}
@@ -3035,8 +3039,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *A, *B;
if (match(II->getArgOperand(0), m_FNeg(m_Value(A))) &&
match(II->getArgOperand(1), m_FNeg(m_Value(B)))) {
- replaceArgOperand(*II, 0, A);
- replaceArgOperand(*II, 1, B);
+ replaceOperand(*II, 0, A);
+ replaceOperand(*II, 1, B);
return II;
}
@@ -3071,8 +3075,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (ElementCount::isKnownGT(NegatedCount, OtherCount) &&
ElementCount::isKnownLT(OtherCount, RetCount)) {
Value *InverseOtherOp = Builder.CreateFNeg(OtherOp);
- replaceArgOperand(*II, NegatedOpArg, OpNotNeg);
- replaceArgOperand(*II, OtherOpArg, InverseOtherOp);
+ replaceOperand(*II, NegatedOpArg, OpNotNeg);
+ replaceOperand(*II, OtherOpArg, InverseOtherOp);
return II;
}
// (-A) * B -> -(A * B), if it is cheaper to negate the result
@@ -3100,19 +3104,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *Src1 = II->getArgOperand(1);
Value *Src2 = II->getArgOperand(2);
Value *X, *Y;
- if (match(Src0, m_FNeg(m_Value(X))) && match(Src1, m_FNeg(m_Value(Y)))) {
- replaceArgOperand(*II, 0, X);
- replaceArgOperand(*II, 1, Y);
- return II;
- }
+ if (match(Src0, m_FNeg(m_Value(X))) && match(Src1, m_FNeg(m_Value(Y))))
+ return replaceInstUsesWith(
+ *II, Builder.CreateIntrinsic(IID, II->getType(), {X, Y, Src2}, II));
// fma fabs(x), fabs(x), z -> fma x, x, z
- if (match(Src0, m_FAbs(m_Value(X))) &&
- match(Src1, m_FAbs(m_Specific(X)))) {
- replaceArgOperand(*II, 0, X);
- replaceArgOperand(*II, 1, X);
- return II;
- }
+ if (match(Src0, m_FAbs(m_Value(X))) && match(Src1, m_FAbs(m_Specific(X))))
+ return replaceInstUsesWith(
+ *II, Builder.CreateIntrinsic(IID, II->getType(), {X, X, Src2}, II));
// Try to simplify the underlying FMul. We can only apply simplifications
// that do not require rounding.
@@ -3166,15 +3165,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (match(Mag, m_APFloat(MagC)) && MagC->isNegative()) {
APFloat PosMagC = *MagC;
PosMagC.clearSign();
- return replaceArgOperand(*II, 0,
- ConstantFP::get(Mag->getType(), PosMagC));
+ return replaceInstUsesWith(
+ *II, Builder.CreateCopySign(ConstantFP::get(Mag->getType(), PosMagC),
+ Sign, II));
}
// Peek through changes of magnitude's sign-bit. This call rewrites those:
// copysign (fabs X), Sign --> copysign X, Sign
// copysign (fneg X), Sign --> copysign X, Sign
if (match(Mag, m_FAbs(m_Value(X))) || match(Mag, m_FNeg(m_Value(X))))
- return replaceArgOperand(*II, 0, X);
+ return replaceInstUsesWith(*II, Builder.CreateCopySign(X, Sign, II));
// copysign(floor(fabs(X)), X) --> copysign(trunc(X), X)
// copysign ignores the sign bit of its magnitude argument (implicit fabs),
@@ -3185,7 +3185,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (match(Mag, m_Intrinsic<Intrinsic::floor>(m_FAbs(m_Value(FAbsArg)))) &&
FAbsArg == Sign) {
Value *Trunc = Builder.CreateUnaryIntrinsic(Intrinsic::trunc, Sign, II);
- return replaceOperand(*II, 0, Trunc);
+ return replaceInstUsesWith(*II, Builder.CreateCopySign(Trunc, Sign, II));
}
Type *SignEltTy = Sign->getType()->getScalarType();
@@ -3230,10 +3230,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
}
// fabs (select Cond, -FVal, FVal) --> fabs FVal
if (match(TVal, m_FNeg(m_Specific(FVal))))
- return replaceArgOperand(*II, 0, FVal);
+ return replaceInstUsesWith(*II, Builder.CreateFAbs(FVal, II));
// fabs (select Cond, TVal, -TVal) --> fabs TVal
if (match(FVal, m_FNeg(m_Specific(TVal))))
- return replaceArgOperand(*II, 0, TVal);
+ return replaceInstUsesWith(*II, Builder.CreateFAbs(TVal, II));
}
Value *Magnitude, *Sign;
@@ -3272,7 +3272,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// f(fabs(x)) --> f(x)
// f(copysign(x, y)) --> f(x)
// for f in {cos, cosh}
- return replaceArgOperand(*II, 0, X);
+ return replaceInstUsesWith(*II, Builder.CreateUnaryIntrinsic(IID, X, II));
}
break;
}
@@ -3337,10 +3337,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
signBitMustBeTheSame(Exp, InnerExp, SQ.getWithInstruction(II)))) {
Value *NewExp =
Builder.CreateBinaryIntrinsic(Intrinsic::sadd_sat, InnerExp, Exp);
- II->setArgOperand(1, NewExp);
- II->dropPoisonGeneratingAndUBImplyingParamAttrs(1);
- II->setFastMathFlags(InnerFlags); // Or the inner flags.
- return replaceArgOperand(*II, 0, InnerSrc);
+ return replaceInstUsesWith(
+ *II, Builder.CreateLdexp(InnerSrc, NewExp, FMF | InnerFlags));
}
}
@@ -4110,7 +4108,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *Vect;
if (Value *NewOp = simplifyReductionOperand(Arg, /*CanReorderLanes=*/true))
- return replaceArgOperand(*II, 0, NewOp);
+ return replaceOperand(*II, 0, NewOp);
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
if (auto *FTy = dyn_cast<FixedVectorType>(Vect->getType()))
@@ -4146,7 +4144,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceArgOperand(*II, 0, NewOp);
+ return replaceOperand(*II, 0, NewOp);
}
// vector.reduce.add.vNiM(splat(%x)) -> mul(%x, N)
@@ -4192,7 +4190,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true))
- return replaceArgOperand(*II, 0, NewOp);
+ return replaceOperand(*II, 0, NewOp);
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
if (auto *VTy = dyn_cast<VectorType>(Vect->getType()))
@@ -4213,7 +4211,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceArgOperand(*II, 0, NewOp);
+ return replaceOperand(*II, 0, NewOp);
}
// vector_reduce_mul(zext(<n x i1>)), or
@@ -4254,7 +4252,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceArgOperand(*II, 0, NewOp);
+ return replaceOperand(*II, 0, NewOp);
}
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
@@ -4295,7 +4293,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceArgOperand(*II, 0, NewOp);
+ return replaceOperand(*II, 0, NewOp);
}
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
@@ -4329,7 +4327,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
: 0;
Value *Arg = II->getArgOperand(ArgIdx);
if (Value *NewOp = simplifyReductionOperand(Arg, CanReorderLanes)) {
- return replaceArgOperand(*II, ArgIdx, NewOp);
+ return replaceOperand(*II, ArgIdx, NewOp);
}
break;
}
diff --git a/llvm/test/Transforms/InstCombine/bit_ceil.ll b/llvm/test/Transforms/InstCombine/bit_ceil.ll
index edf1c176ff12c..4017c41acbdd7 100644
--- a/llvm/test/Transforms/InstCombine/bit_ceil.ll
+++ b/llvm/test/Transforms/InstCombine/bit_ceil.ll
@@ -380,7 +380,7 @@ define i32 @bit_ceil_plus_nuw(i32 %x) {
; CHECK-LABEL: @bit_ceil_plus_nuw(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X:%.*]], 1
-; CHECK-NEXT: [[CTLZ:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[SUB]], i1 false)
+; CHECK-NEXT: [[CTLZ:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[SUB]], i1 false)
; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 0, [[CTLZ]]
; CHECK-NEXT: [[SUB2:%.*]] = and i32 [[TMP0]], 31
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[SUB2]]
diff --git a/llvm/test/Transforms/InstCombine/ctpop-bswap-bitreverse.ll b/llvm/test/Transforms/InstCombine/ctpop-bswap-bitreverse.ll
index 7e4050873dc92..32791fe186c33 100644
--- a/llvm/test/Transforms/InstCombine/ctpop-bswap-bitreverse.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop-bswap-bitreverse.ll
@@ -3,7 +3,7 @@
define i32 @ctpop_bitreverse(i32 %x) {
; CHECK-LABEL: @ctpop_bitreverse(
-; CHECK-NEXT: [[B:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
+; CHECK-NEXT: [[B:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
; CHECK-NEXT: ret i32 [[B]]
;
%a = tail call i32 @llvm.bitreverse.i32(i32 %x)
@@ -13,7 +13,7 @@ define i32 @ctpop_bitreverse(i32 %x) {
define <2 x i64> @ctpop_bitreverse_vec(<2 x i64> %x) {
; CHECK-LABEL: @ctpop_bitreverse_vec(
-; CHECK-NEXT: [[B:%.*]] = tail call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> [[X:%.*]])
+; CHECK-NEXT: [[B:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> [[X:%.*]])
; CHECK-NEXT: ret <2 x i64> [[B]]
;
%a = tail call <2 x i64> @llvm.bitreverse.v2i64(<2 x i64> %x)
@@ -23,7 +23,7 @@ define <2 x i64> @ctpop_bitreverse_vec(<2 x i64> %x) {
define i32 @ctpop_bswap(i32 %x) {
; CHECK-LABEL: @ctpop_bswap(
-; CHECK-NEXT: [[B:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
+; CHECK-NEXT: [[B:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
; CHECK-NEXT: ret i32 [[B]]
;
%a = tail call i32 @llvm.bswap.i32(i32 %x)
@@ -33,7 +33,7 @@ define i32 @ctpop_bswap(i32 %x) {
define <2 x i64> @ctpop_bswap_vec(<2 x i64> %x) {
; CHECK-LABEL: @ctpop_bswap_vec(
-; CHECK-NEXT: [[B:%.*]] = tail call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> [[X:%.*]])
+; CHECK-NEXT: [[B:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> [[X:%.*]])
; CHECK-NEXT: ret <2 x i64> [[B]]
;
%a = tail call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %x)
diff --git a/llvm/test/Transforms/InstCombine/ctpop.ll b/llvm/test/Transforms/InstCombine/ctpop.ll
index 217a3c308a2dd..e3a6a2ad594ee 100644
--- a/llvm/test/Transforms/InstCombine/ctpop.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop.ll
@@ -265,7 +265,7 @@ define <2 x i32> @ctpop_add_no_common_bits_vec_use2(<2 x i32> %a, <2 x i32> %b,
define i8 @ctpop_rotate_left(i8 %a, i8 %amt) {
; CHECK-LABEL: @ctpop_rotate_left(
-; CHECK-NEXT: [[RES:%.*]] = tail call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[A:%.*]])
+; CHECK-NEXT: [[RES:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[A:%.*]])
; CHECK-NEXT: ret i8 [[RES]]
;
%rotl = tail call i8 @llvm.fshl.i8(i8 %a, i8 %a, i8 %amt)
@@ -275,7 +275,7 @@ define i8 @ctpop_rotate_left(i8 %a, i8 %amt) {
define i8 @ctpop_rotate_right(i8 %a, i8 %amt) {
; CHECK-LABEL: @ctpop_rotate_right(
-; CHECK-NEXT: [[RES:%.*]] = tail call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[A:%.*]])
+; CHECK-NEXT: [[RES:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[A:%.*]])
; CHECK-NEXT: ret i8 [[RES]]
;
%rotr = tail call i8 @llvm.fshr.i8(i8 %a, i8 %a, i8 %amt)
diff --git a/llvm/test/Transforms/InstCombine/cttz-abs.ll b/llvm/test/Transforms/InstCombine/cttz-abs.ll
index 9d3b6168e710b..69dfc5dd0dc19 100644
--- a/llvm/test/Transforms/InstCombine/cttz-abs.ll
+++ b/llvm/test/Transforms/InstCombine/cttz-abs.ll
@@ -3,7 +3,7 @@
define i32 @cttz_abs(i32 %x) {
; CHECK-LABEL: @cttz_abs(
-; CHECK-NEXT: [[R:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
; CHECK-NEXT: ret i32 [[R]]
;
%c = icmp slt i32 %x, 0
@@ -29,7 +29,7 @@ define i32 @cttz_abs2(i32 %x) {
; CHECK-LABEL: @cttz_abs2(
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], 0
; CHECK-NEXT: call void @use_cond(i1 [[C]])
-; CHECK-NEXT: [[R:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
; CHECK-NEXT: ret i32 [[R]]
;
%c = icmp sgt i32 %x, 0
@@ -44,7 +44,7 @@ define i32 @cttz_abs3(i32 %x) {
; CHECK-LABEL: @cttz_abs3(
; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[X:%.*]], -1
; CHECK-NEXT: call void @use_cond(i1 [[C]])
-; CHECK-NEXT: [[R:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
; CHECK-NEXT: ret i32 [[R]]
;
%c = icmp sgt i32 %x, -1
@@ -57,7 +57,7 @@ define i32 @cttz_abs3(i32 %x) {
define i32 @cttz_abs4(i32 %x) {
; CHECK-LABEL: @cttz_abs4(
-; CHECK-NEXT: [[R:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
; CHECK-NEXT: ret i32 [[R]]
;
%c = icmp slt i32 %x, 1
@@ -69,7 +69,7 @@ define i32 @cttz_abs4(i32 %x) {
define i32 @cttz_nabs(i32 %x) {
; CHECK-LABEL: @cttz_nabs(
-; CHECK-NEXT: [[R:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
+; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: ret i32 [[R]]
;
%c = icmp slt i32 %x, 0
@@ -107,7 +107,7 @@ define i32 @cttz_abs_multiuse(i32 %x) {
; CHECK-LABEL: @cttz_abs_multiuse(
; CHECK-NEXT: [[D:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: call void @use_abs(i32 [[D]])
-; CHECK-NEXT: [[R:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
; CHECK-NEXT: ret i32 [[R]]
;
%c = icmp slt i32 %x, 1
@@ -123,7 +123,7 @@ define i32 @cttz_nabs_multiuse(i32 %x) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: [[D:%.*]] = sub i32 0, [[TMP1]]
; CHECK-NEXT: call void @use_abs(i32 [[D]])
-; CHECK-NEXT: [[R:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
+; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 true)
; CHECK-NEXT: ret i32 [[R]]
;
%c = icmp slt i32 %x, 1
diff --git a/llvm/test/Transforms/InstCombine/cttz-negative.ll b/llvm/test/Transforms/InstCombine/cttz-negative.ll
index 6f812e420935d..5c6cf553dd91f 100644
--- a/llvm/test/Transforms/InstCombine/cttz-negative.ll
+++ b/llvm/test/Transforms/InstCombine/cttz-negative.ll
@@ -26,7 +26,7 @@ define i32 @cttz_neg_value_multiuse(i32 %x) {
define i64 @cttz_neg_value_64(i64 %x) {
; CHECK-LABEL: @cttz_neg_value_64(
-; CHECK-NEXT: [[B:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 true)
+; CHECK-NEXT: [[B:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 true)
; CHECK-NEXT: ret i64 [[B]]
;
%a = sub i64 0, %x
@@ -36,7 +36,7 @@ define i64 @cttz_neg_value_64(i64 %x) {
define i64 @cttz_neg_value2_64(i64 %x) {
; CHECK-LABEL: @cttz_neg_value2_64(
-; CHECK-NEXT: [[B:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
+; CHECK-NEXT: [[B:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false)
; CHECK-NEXT: ret i64 [[B]]
;
%a = sub i64 0, %x
diff --git a/llvm/test/Transforms/InstCombine/hyperbolic-functions.ll b/llvm/test/Transforms/InstCombine/hyperbolic-functions.ll
index 6cf689a982dd0..279d2775af8ea 100644
--- a/llvm/test/Transforms/InstCombine/hyperbolic-functions.ll
+++ b/llvm/test/Transforms/InstCombine/hyperbolic-functions.ll
@@ -4,7 +4,7 @@
define double @fneg_cosh(double noundef %x) {
; CHECK-LABEL: @fneg_cosh(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[RET:%.*]] = tail call nnan double @llvm.cosh.f64(double [[X:%.*]])
+; CHECK-NEXT: [[RET:%.*]] = call nnan double @llvm.cosh.f64(double [[X:%.*]])
; CHECK-NEXT: ret double [[RET]]
;
entry:
diff --git a/llvm/test/Transforms/InstCombine/intrinsics.ll b/llvm/test/Transforms/InstCombine/intrinsics.ll
index 9dceb419215e5..8610912e8127c 100644
--- a/llvm/test/Transforms/InstCombine/intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/intrinsics.ll
@@ -139,7 +139,7 @@ define <vscale x 1 x i1> @cttz_knownbits_scalable_vec(<vscale x 1 x i32> %arg) {
define i32 @cttz_knownbits2(i32 %arg) {
; CHECK-LABEL: @cttz_knownbits2(
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG:%.*]], 4
-; CHECK-NEXT: [[CNT:%.*]] = call range(i32 0, 3) i32 @llvm.cttz.i32(i32 [[OR]], i1 true) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT: [[CNT:%.*]] = call range(i32 0, 3) i32 @llvm.cttz.i32(i32 [[OR]], i1 true) #[[ATTR3:[0-9]+]]
; CHECK-NEXT: ret i32 [[CNT]]
;
%or = or i32 %arg, 4
@@ -150,7 +150,7 @@ define i32 @cttz_knownbits2(i32 %arg) {
define <2 x i32> @cttz_knownbits2_vec(<2 x i32> %arg) {
; CHECK-LABEL: @cttz_knownbits2_vec(
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[ARG:%.*]], splat (i32 4)
-; CHECK-NEXT: [[CNT:%.*]] = call range(i32 0, 3) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[OR]], i1 true) #[[ATTR2]]
+; CHECK-NEXT: [[CNT:%.*]] = call range(i32 0, 3) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[OR]], i1 true) #[[ATTR3]]
; CHECK-NEXT: ret <2 x i32> [[CNT]]
;
%or = or <2 x i32> %arg, <i32 4, i32 4>
@@ -256,7 +256,7 @@ define <2 x i1> @ctlz_knownbits_vec(<2 x i8> %arg) {
define i8 @ctlz_knownbits2(i8 %arg) {
; CHECK-LABEL: @ctlz_knownbits2(
; CHECK-NEXT: [[OR:%.*]] = or i8 [[ARG:%.*]], 32
-; CHECK-NEXT: [[CNT:%.*]] = call range(i8 0, 3) i8 @llvm.ctlz.i8(i8 [[OR]], i1 true) #[[ATTR2]]
+; CHECK-NEXT: [[CNT:%.*]] = call range(i8 0, 3) i8 @llvm.ctlz.i8(i8 [[OR]], i1 true) #[[ATTR3]]
; CHECK-NEXT: ret i8 [[CNT]]
;
%or = or i8 %arg, 32
@@ -267,7 +267,7 @@ define i8 @ctlz_knownbits2(i8 %arg) {
define <2 x i8> @ctlz_knownbits2_vec(<2 x i8> %arg) {
; CHECK-LABEL: @ctlz_knownbits2_vec(
; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[ARG:%.*]], splat (i8 32)
-; CHECK-NEXT: [[CNT:%.*]] = call range(i8 0, 3) <2 x i8> @llvm.ctlz.v2i8(<2 x i8> [[OR]], i1 true) #[[ATTR2]]
+; CHECK-NEXT: [[CNT:%.*]] = call range(i8 0, 3) <2 x i8> @llvm.ctlz.v2i8(<2 x i8> [[OR]], i1 true) #[[ATTR3]]
; CHECK-NEXT: ret <2 x i8> [[CNT]]
;
%or = or <2 x i8> %arg, <i8 32, i8 32>
@@ -314,7 +314,7 @@ define <2 x i32> @ctlz_poison_vec(<2 x i32> %Value) {
define i32 @ctlz_no_zero(i32 %a) {
; CHECK-LABEL: @ctlz_no_zero(
; CHECK-NEXT: [[OR:%.*]] = or i32 [[A:%.*]], 8
-; CHECK-NEXT: [[CTLZ:%.*]] = tail call range(i32 0, 29) i32 @llvm.ctlz.i32(i32 [[OR]], i1 true)
+; CHECK-NEXT: [[CTLZ:%.*]] = call range(i32 0, 29) i32 @llvm.ctlz.i32(i32 [[OR]], i1 true)
; CHECK-NEXT: ret i32 [[CTLZ]]
;
%or = or i32 %a, 8
@@ -325,7 +325,7 @@ define i32 @ctlz_no_zero(i32 %a) {
define <2 x i32> @ctlz_no_zero_vec(<2 x i32> %a) {
; CHECK-LABEL: @ctlz_no_zero_vec(
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[A:%.*]], splat (i32 8)
-; CHECK-NEXT: [[CTLZ:%.*]] = tail call range(i32 0, 29) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[OR]], i1 true)
+; CHECK-NEXT: [[CTLZ:%.*]] = call range(i32 0, 29) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[OR]], i1 true)
; CHECK-NEXT: ret <2 x i32> [[CTLZ]]
;
%or = or <2 x i32> %a, <i32 8, i32 8>
@@ -352,7 +352,7 @@ define <2 x i32> @cttz_poison_vec(<2 x i32> %Value) {
define i32 @cttz_no_zero(i32 %a) {
; CHECK-LABEL: @cttz_no_zero(
; CHECK-NEXT: [[OR:%.*]] = or i32 [[A:%.*]], 8
-; CHECK-NEXT: [[CTTZ:%.*]] = tail call range(i32 0, 4) i32 @llvm.cttz.i32(i32 [[OR]], i1 true)
+; CHECK-NEXT: [[CTTZ:%.*]] = call range(i32 0, 4) i32 @llvm.cttz.i32(i32 [[OR]], i1 true)
; CHECK-NEXT: ret i32 [[CTTZ]]
;
%or = or i32 %a, 8
@@ -363,7 +363,7 @@ define i32 @cttz_no_zero(i32 %a) {
define <2 x i32> @cttz_no_zero_vec(<2 x i32> %a) {
; CHECK-LABEL: @cttz_no_zero_vec(
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[A:%.*]], splat (i32 8)
-; CHECK-NEXT: [[CTTZ:%.*]] = tail call range(i32 0, 4) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[OR]], i1 true)
+; CHECK-NEXT: [[CTTZ:%.*]] = call range(i32 0, 4) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[OR]], i1 true)
; CHECK-NEXT: ret <2 x i32> [[CTTZ]]
;
%or = or <2 x i32> %a, <i32 8, i32 8>
diff --git a/llvm/test/Transforms/InstCombine/is_fpclass.ll b/llvm/test/Transforms/InstCombine/is_fpclass.ll
index a4f7a43adf1e5..62b456a6e81a2 100644
--- a/llvm/test/Transforms/InstCombine/is_fpclass.ll
+++ b/llvm/test/Transforms/InstCombine/is_fpclass.ll
@@ -1743,7 +1743,7 @@ define i1 @test_class_fneg_posinf_negnormal_possubnormal_negzero_nan(float %arg)
; -> ninf|pnormal|negsubnormal|pzero|snan
define i1 @test_class_fneg_posinf_negnormal_possubnormal_negzero_snan_strictfp(float %arg) strictfp {
; CHECK-LABEL: @test_class_fneg_posinf_negnormal_possubnormal_negzero_snan_strictfp(
-; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 341) #[[ATTR0]]
+; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 341)
; CHECK-NEXT: ret i1 [[CLASS]]
;
%fneg = fneg float %arg
@@ -2075,7 +2075,7 @@ define i1 @test_class_fabs_posinf_negnormal_possubnormal_negzero_nan(float %arg)
; -> pinf|psubnormal|snan
define i1 @test_class_fabs_posinf_negnormal_possubnormal_negzero_snan_strictfp(float %arg) strictfp {
; CHECK-LABEL: @test_class_fabs_posinf_negnormal_possubnormal_negzero_snan_strictfp(
-; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 661) #[[ATTR0]]
+; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 661)
; CHECK-NEXT: ret i1 [[CLASS]]
;
%fabs = call float @llvm.fabs.f32(float %arg) strictfp
@@ -2406,7 +2406,7 @@ define i1 @test_class_fneg_fabs_posinf_negnormal_possubnormal_negzero_nan(float
; strictfp doesn't matter
define i1 @test_class_fneg_fabs_posinf_negnormal_possubnormal_negzero_snan_strictfp(float %arg) strictfp {
; CHECK-LABEL: @test_class_fneg_fabs_posinf_negnormal_possubnormal_negzero_snan_strictfp(
-; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 361) #[[ATTR0]]
+; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG:%.*]], i32 361)
; CHECK-NEXT: ret i1 [[CLASS]]
;
%fabs = call float @llvm.fabs.f32(float %arg) strictfp
diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll
index 2059e94e0e371..e106ccad909b9 100644
--- a/llvm/test/Transforms/InstCombine/powi.ll
+++ b/llvm/test/Transforms/InstCombine/powi.ll
@@ -11,7 +11,7 @@ declare void @use(double)
define double @powi_fneg_even_int(double %x) {
; CHECK-LABEL: @powi_fneg_even_int(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
; CHECK-NEXT: ret double [[R]]
;
entry:
@@ -23,7 +23,7 @@ entry:
define double @powi_fabs_even_int(double %x) {
; CHECK-LABEL: @powi_fabs_even_int(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
; CHECK-NEXT: ret double [[R]]
;
entry:
@@ -35,7 +35,7 @@ entry:
define double @powi_copysign_even_int(double %x, double %y) {
; CHECK-LABEL: @powi_copysign_even_int(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[R:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
+; CHECK-NEXT: [[R:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 4)
; CHECK-NEXT: ret double [[R]]
;
entry:
>From 7d48df1b27be3f23b500cc31bcdce886777215c8 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 28 Jun 2026 20:01:22 +0800
Subject: [PATCH 07/12] [InstCombine] Add more tests. NFC.
---
.../Transforms/InstCombine/minmax-of-minmax.ll | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll b/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
index e04e3c146924b..e2256630e2f62 100644
--- a/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
@@ -288,3 +288,18 @@ define i32 @umin_of_umin_umax_wrong_operand2(i32 %x, i32 %y, i32 %z) {
%r = select i1 %cmp3, i32 %min, i32 %max
ret i32 %r
}
+
+; Make sure that the range attribute is dropped.
+
+define i32 @umax_of_umax_umin_drop_range(i32 %x, i32 %y) {
+; CHECK-LABEL: @umax_of_umax_umin_drop_range(
+; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %cmp1 = icmp ugt i32 %x, %y
+ %min = select i1 %cmp1, i32 %y, i32 %x
+ %cmp2 = icmp ugt i32 %x, %y
+ %max = select i1 %cmp2, i32 %x, i32 %y
+ %r = call i32 @llvm.umax.i32(i32 range(i32 0, 4) %min, i32 range(i32 4, 8) %max)
+ ret i32 %r
+}
>From bd7674e92b443423b04cdfe45b222345b2fcc0d6 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 28 Jun 2026 20:02:34 +0800
Subject: [PATCH 08/12] [IR] Drop unused includes
---
llvm/lib/IR/Instructions.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 413abb9a39e62..faa046729aff6 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -16,7 +16,6 @@
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
>From fef4c03e8754b3f3418bce9bca62f65e681f4f31 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 28 Jun 2026 23:39:45 +0800
Subject: [PATCH 09/12] [InstCombine] Address review comments.
---
llvm/include/llvm/IR/Attributes.h | 6 +--
.../InstCombine/InstCombineCalls.cpp | 44 ++++++++++++-------
.../Transforms/InstCombine/minmax-fold.ll | 6 +--
3 files changed, 33 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index 833f2a033a067..3387649850ed5 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -579,9 +579,6 @@ class AttributeList {
static AttributeList getImpl(LLVMContext &C, ArrayRef<AttributeSet> AttrSets);
- AttributeList setAttributesAtIndex(LLVMContext &C, unsigned Index,
- AttributeSet Attrs) const;
-
public:
AttributeList() = default;
@@ -604,6 +601,9 @@ class AttributeList {
LLVM_ABI static AttributeList get(LLVMContext &C, unsigned Index,
const AttrBuilder &B);
+ AttributeList setAttributesAtIndex(LLVMContext &C, unsigned Index,
+ AttributeSet Attrs) const;
+
// TODO: remove non-AtIndex versions of these methods.
/// Add an attribute to the attribute set at the given index.
/// Returns a new list because attribute lists are immutable.
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 9dc2ab187e5e4..091b449b19f72 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -923,15 +923,15 @@ static CallInst *canonicalizeConstantArg0ToArg1(CallInst &Call) {
if (isa<Constant>(Arg0) && !isa<Constant>(Arg1)) {
Call.setArgOperand(0, Arg1);
Call.setArgOperand(1, Arg0);
- auto CallAttr = Call.getAttributes();
- auto LHSAttr = CallAttr.getParamAttrs(0);
- auto RHSAttr = CallAttr.getParamAttrs(1);
+ AttributeList CallAttr = Call.getAttributes();
+ AttributeSet LHSAttr = CallAttr.getParamAttrs(0);
+ AttributeSet RHSAttr = CallAttr.getParamAttrs(1);
LLVMContext &Ctx = Call.getContext();
- Call.setAttributes(
- CallAttr.removeAttributesAtIndex(Ctx, 0)
- .removeAttributesAtIndex(Ctx, 1)
- .addParamAttributes(Ctx, 0, AttrBuilder(Ctx, RHSAttr))
- .addParamAttributes(Ctx, 1, AttrBuilder(Ctx, LHSAttr)));
+ Call.setAttributes(CallAttr
+ .setAttributesAtIndex(
+ Ctx, AttributeList::FirstArgIndex + 0, RHSAttr)
+ .setAttributesAtIndex(
+ Ctx, AttributeList::FirstArgIndex + 1, LHSAttr));
return &Call;
}
return nullptr;
@@ -4107,8 +4107,11 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *Arg = II->getArgOperand(0);
Value *Vect;
- if (Value *NewOp = simplifyReductionOperand(Arg, /*CanReorderLanes=*/true))
- return replaceOperand(*II, 0, NewOp);
+ if (Value *NewOp =
+ simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
+ replaceUse(II->getOperandUse(0), NewOp);
+ return II;
+ }
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
if (auto *FTy = dyn_cast<FixedVectorType>(Vect->getType()))
@@ -4144,7 +4147,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceOperand(*II, 0, NewOp);
+ replaceUse(II->getOperandUse(0), NewOp);
+ return II;
}
// vector.reduce.add.vNiM(splat(%x)) -> mul(%x, N)
@@ -4189,8 +4193,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
Value *Vect;
if (Value *NewOp =
- simplifyReductionOperand(Arg, /*CanReorderLanes=*/true))
- return replaceOperand(*II, 0, NewOp);
+ simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
+ replaceUse(II->getOperandUse(0), NewOp);
+ return II;
+ }
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
if (auto *VTy = dyn_cast<VectorType>(Vect->getType()))
@@ -4211,7 +4217,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceOperand(*II, 0, NewOp);
+ replaceUse(II->getOperandUse(0), NewOp);
+ return II;
}
// vector_reduce_mul(zext(<n x i1>)), or
@@ -4252,7 +4259,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceOperand(*II, 0, NewOp);
+ replaceUse(II->getOperandUse(0), NewOp);
+ return II;
}
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
@@ -4293,7 +4301,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Value *NewOp =
simplifyReductionOperand(Arg, /*CanReorderLanes=*/true)) {
- return replaceOperand(*II, 0, NewOp);
+ replaceUse(II->getOperandUse(0), NewOp);
+ return II;
}
if (match(Arg, m_ZExtOrSExtOrSelf(m_Value(Vect)))) {
@@ -4327,7 +4336,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
: 0;
Value *Arg = II->getArgOperand(ArgIdx);
if (Value *NewOp = simplifyReductionOperand(Arg, CanReorderLanes)) {
- return replaceOperand(*II, ArgIdx, NewOp);
+ replaceUse(II->getOperandUse(ArgIdx), NewOp);
+ return nullptr;
}
break;
}
diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll
index 049d3153ff51c..3234ed5055f80 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fold.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll
@@ -1845,9 +1845,9 @@ define i32 @test_umin_or_neg1_nuw(i32 %x, i32 range(i32 1, 0) %w) {
; Make sure that poison-generating/UB-implying parameters are swapped.
-define i32 @umax_commute_operand_drop_attrs(i32 %x) {
-; CHECK-LABEL: @umax_commute_operand_drop_attrs(
-; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 noundef range(i32 -10, -8) -10)
+define i32 @umax_commute_operand_swap_attrs(i32 %x) {
+; CHECK-LABEL: @umax_commute_operand_swap_attrs(
+; CHECK-NEXT: [[RET:%.*]] = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 [[X:%.*]], i32 noundef range(i32 -10, -8) -10)
; CHECK-NEXT: ret i32 [[RET]]
;
%ret = call range(i32 -10, 0) i32 @llvm.umax.i32(i32 noundef range(i32 -10, -8) -10, i32 %x)
>From c27d88cd51aaa73536cfff069e32697a2a65ccca Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 28 Jun 2026 23:45:58 +0800
Subject: [PATCH 10/12] [InstCombine] Add pre-commit tests. NFC.
---
.../test/Transforms/InstCombine/minmax-of-minmax.ll | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll b/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
index e2256630e2f62..d55824362728a 100644
--- a/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
@@ -303,3 +303,16 @@ define i32 @umax_of_umax_umin_drop_range(i32 %x, i32 %y) {
%r = call i32 @llvm.umax.i32(i32 range(i32 0, 4) %min, i32 range(i32 4, 8) %max)
ret i32 %r
}
+
+; Make sure that the noundef attribute is dropped.
+
+define i32 @umax_of_symmetric_drop_noundef(i1 %cond, i32 %x, i32 %y) {
+; CHECK-LABEL: @umax_of_symmetric_drop_noundef(
+; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 noundef [[Y:%.*]], i32 [[X:%.*]])
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %sel1 = select i1 %cond, i32 %y, i32 %x
+ %sel2 = select i1 %cond, i32 %x, i32 %y
+ %r = call i32 @llvm.umax.i32(i32 noundef %sel1, i32 %sel2)
+ ret i32 %r
+}
>From ec211d2342ff939a3eb98b264ee27a58796a6f83 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 29 Jun 2026 00:01:05 +0800
Subject: [PATCH 11/12] [InstCombine] Drop noundef
---
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 1 +
llvm/test/Transforms/InstCombine/minmax-of-minmax.ll | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 091b449b19f72..0c2d11fab4f43 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2034,6 +2034,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
replaceOperand(*II, 0, Pair->first);
replaceOperand(*II, 1, Pair->second);
II->dropPoisonGeneratingAnnotations();
+ II->dropUBImplyingAttrsAndMetadata();
return II;
}
diff --git a/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll b/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
index d55824362728a..56ba1cf5e9e1f 100644
--- a/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-of-minmax.ll
@@ -308,7 +308,7 @@ define i32 @umax_of_umax_umin_drop_range(i32 %x, i32 %y) {
define i32 @umax_of_symmetric_drop_noundef(i1 %cond, i32 %x, i32 %y) {
; CHECK-LABEL: @umax_of_symmetric_drop_noundef(
-; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 noundef [[Y:%.*]], i32 [[X:%.*]])
+; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[Y:%.*]], i32 [[X:%.*]])
; CHECK-NEXT: ret i32 [[MAX]]
;
%sel1 = select i1 %cond, i32 %y, i32 %x
>From e89cf83d3b081152f87edaa3403e6d77c7c6a2cf Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 29 Jun 2026 00:01:46 +0800
Subject: [PATCH 12/12] [IR] Add LLVM_ABI
---
llvm/include/llvm/IR/Attributes.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index 3387649850ed5..049f699b2980b 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -601,8 +601,10 @@ class AttributeList {
LLVM_ABI static AttributeList get(LLVMContext &C, unsigned Index,
const AttrBuilder &B);
- AttributeList setAttributesAtIndex(LLVMContext &C, unsigned Index,
- AttributeSet Attrs) const;
+ /// Set the attribute set at the given index.
+ /// Returns a new list because attribute lists are immutable.
+ [[nodiscard]] LLVM_ABI AttributeList setAttributesAtIndex(
+ LLVMContext &C, unsigned Index, AttributeSet Attrs) const;
// TODO: remove non-AtIndex versions of these methods.
/// Add an attribute to the attribute set at the given index.
More information about the llvm-commits
mailing list