54#define DEBUG_TYPE "constraint-elimination"
56STATISTIC(NumCondsRemoved,
"Number of instructions removed");
58 "Controls which conditions are eliminated");
62 cl::desc(
"Maximum number of rows to keep in constraint system"));
66 cl::desc(
"Dump IR to reproduce successful transformations."));
74 UserI = Phi->getIncomingBlock(U)->getTerminator();
87 : Pred(Pred), Op0(Op0), Op1(Op1) {}
119 FactOrCheck(EntryTy Ty,
DomTreeNode *DTN, Instruction *Inst)
120 : Inst(Inst), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
124 :
U(
U), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
125 Ty(EntryTy::UseCheck) {}
129 :
Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
130 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
132 static FactOrCheck getConditionFact(
DomTreeNode *DTN, CmpPredicate Pred,
135 return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
138 static FactOrCheck getInstFact(
DomTreeNode *DTN, Instruction *Inst) {
139 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
142 static FactOrCheck getCheck(
DomTreeNode *DTN, Use *U) {
143 return FactOrCheck(DTN, U);
146 static FactOrCheck getCheck(
DomTreeNode *DTN, CallInst *CI) {
147 return FactOrCheck(EntryTy::InstCheck, DTN, CI);
150 bool isCheck()
const {
151 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
155 assert(!isConditionFact());
156 if (Ty == EntryTy::UseCheck)
163 if (Ty == EntryTy::InstCheck)
169 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
177 TargetLibraryInfo &TLI;
180 State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE,
181 TargetLibraryInfo &TLI)
182 : DT(DT), LI(LI), SE(SE), TLI(TLI) {}
185 void addInfoFor(BasicBlock &BB);
189 void addInfoForInductions(BasicBlock &BB);
193 bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ)
const {
194 return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
203 bool IsSigned =
false;
206 SmallVector<Value *, 2> ValuesToRelease;
208 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
209 SmallVector<Value *, 2> ValuesToRelease)
210 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
211 ValuesToRelease(std::
move(ValuesToRelease)) {}
216 SmallVector<ConditionTy, 2> Preconditions;
218 bool IsSigned =
false;
220 ConstraintTy() =
default;
224 : Coefficients(std::
move(Coefficients)), IsSigned(IsSigned), IsEq(IsEq),
227 unsigned size()
const {
return Coefficients.size(); }
229 unsigned empty()
const {
return Coefficients.empty(); }
233 bool isValid(
const ConstraintInfo &Info)
const;
235 bool isEq()
const {
return IsEq; }
237 bool isNe()
const {
return IsNe; }
244 std::optional<bool> isImpliedBy(
const ConstraintSystem &
CS)
const;
257class ConstraintInfo {
259 ConstraintSystem UnsignedCS;
260 ConstraintSystem SignedCS;
262 const DataLayout &DL;
266 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
267 auto &Value2Index = getValue2Index(
false);
269 for (
Value *Arg : FunctionArgs) {
271 false,
false,
false);
272 VarPos.Coefficients[Value2Index[Arg]] = -1;
273 UnsignedCS.addVariableRow(VarPos.Coefficients);
277 DenseMap<Value *, unsigned> &getValue2Index(
bool Signed) {
278 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
280 const DenseMap<Value *, unsigned> &getValue2Index(
bool Signed)
const {
281 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
284 ConstraintSystem &getCS(
bool Signed) {
285 return Signed ? SignedCS : UnsignedCS;
287 const ConstraintSystem &getCS(
bool Signed)
const {
288 return Signed ? SignedCS : UnsignedCS;
291 void popLastConstraint(
bool Signed) { getCS(
Signed).popLastConstraint(); }
292 void popLastNVariables(
bool Signed,
unsigned N) {
293 getCS(
Signed).popLastNVariables(
N);
299 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
306 SmallVectorImpl<Value *> &NewVariables,
307 bool ForceSignedSystem =
false)
const;
322 unsigned NumIn,
unsigned NumOut,
323 SmallVectorImpl<StackEntry> &DFSInStack);
330 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
331 bool ForceSignedSystem);
339 DecompEntry(int64_t Coefficient,
Value *Variable)
340 : Coefficient(Coefficient), Variable(Variable) {}
344struct Decomposition {
348 Decomposition(int64_t Offset) : Offset(Offset) {}
349 Decomposition(
Value *V) { Vars.emplace_back(1, V); }
351 : Offset(Offset), Vars(Vars) {}
355 [[nodiscard]]
bool add(int64_t OtherOffset) {
361 [[nodiscard]]
bool add(
const Decomposition &
Other) {
370 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
371 Decomposition Tmp =
Other;
382 [[nodiscard]]
bool mul(int64_t Factor) {
385 for (
auto &Var : Vars)
386 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
395 APInt ConstantOffset;
396 SmallMapVector<Value *, APInt, 4> VariableOffsets;
399 OffsetResult() :
BasePtr(nullptr), ConstantOffset(0, uint64_t(0)) {}
401 OffsetResult(GEPOperator &
GEP,
const DataLayout &
DL)
403 ConstantOffset = APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
413 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
415 Result.ConstantOffset))
423 bool CanCollectInner = InnerGEP->collectOffset(
424 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
426 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
427 VariableOffsets2.
size() > 1 ||
428 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
432 Result.BasePtr = InnerGEP->getPointerOperand();
433 Result.ConstantOffset += ConstantOffset2;
434 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
435 Result.VariableOffsets = std::move(VariableOffsets2);
436 Result.NW &= InnerGEP->getNoWrapFlags();
455 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
458 assert(!IsSigned &&
"The logic below only supports decomposition for "
459 "unsigned predicates at the moment.");
460 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
469 if (!NW.hasNoUnsignedSignedWrap() && ConstantOffset.isNegative())
472 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
473 for (
auto [Index, Scale] : VariableOffsets) {
474 auto IdxResult =
decompose(Index, Preconditions, IsSigned,
DL);
475 if (IdxResult.mul(Scale.getSExtValue()))
477 if (Result.add(IdxResult))
480 if (!NW.hasNoUnsignedWrap()) {
482 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
485 ConstantInt::get(Index->getType(), 0));
498 auto MergeResults = [&Preconditions, IsSigned,
500 bool IsSignedB) -> std::optional<Decomposition> {
509 if (Ty->isPointerTy() && !IsSigned) {
521 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
528 return CI->getSExtValue();
543 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
549 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
550 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
558 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
568 if (Shift < Ty->getIntegerBitWidth() - 1) {
569 assert(Shift < 64 &&
"Would overflow");
570 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
571 if (!Result.mul(int64_t(1) << Shift))
583 return int64_t(CI->getZExtValue());
592 ConstantInt::get(Op0->
getType(), 0));
594 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64) {
595 if (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap()) {
596 V = Trunc->getOperand(0);
597 if (!Trunc->hasNoUnsignedWrap())
599 ConstantInt::get(V->getType(), 0));
607 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
617 if (
auto Decomp = MergeResults(Op0, CI,
true))
625 ConstantInt::get(Op0->
getType(), 0));
628 ConstantInt::get(Op1->
getType(), 0));
630 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
637 if (
auto Decomp = MergeResults(Op0, CI, IsSigned))
645 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
653 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
660 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
661 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
673 bool ForceSignedSystem)
const {
674 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
676 "signed system can only be forced on eq/ne");
718 auto &Value2Index = getValue2Index(IsSigned);
720 Preconditions, IsSigned,
DL);
722 Preconditions, IsSigned,
DL);
723 int64_t Offset1 = ADec.Offset;
724 int64_t Offset2 = BDec.Offset;
727 auto &VariablesA = ADec.Vars;
728 auto &VariablesB = BDec.Vars;
732 SmallDenseMap<Value *, unsigned> NewIndexMap;
733 auto GetOrAddIndex = [&Value2Index, &NewVariables,
734 &NewIndexMap](
Value *
V) ->
unsigned {
735 auto V2I = Value2Index.find(V);
736 if (V2I != Value2Index.end())
739 V, Value2Index.size() + NewVariables.size() + 1);
741 NewVariables.push_back(V);
747 GetOrAddIndex(KV.Variable);
753 IsSigned, IsEq, IsNe);
754 auto &
R = Res.Coefficients;
755 for (
const auto &KV : VariablesA)
756 R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
758 for (
const auto &KV : VariablesB) {
759 auto &Coeff =
R[GetOrAddIndex(KV.Variable)];
768 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
771 Res.Preconditions = std::move(Preconditions);
775 while (!NewVariables.empty()) {
776 int64_t
Last =
R.back();
780 Value *RemovedV = NewVariables.pop_back_val();
781 NewIndexMap.
erase(RemovedV);
795 auto &Value2Index = getValue2Index(
false);
810 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
811 if (!NewVariables.
empty())
816bool ConstraintTy::isValid(
const ConstraintInfo &Info)
const {
817 return Coefficients.
size() > 0 &&
819 return Info.doesHold(
C.Pred,
C.Op0,
C.Op1);
824ConstraintTy::isImpliedBy(
const ConstraintSystem &
CS)
const {
825 const auto &[SubCS, NewCoefficients] =
CS.getSubSystem(Coefficients);
826 bool IsConditionImplied = SubCS.isConditionImplied(NewCoefficients);
830 bool IsNegatedOrEqualImplied =
831 !NegatedOrEqual.empty() && SubCS.isConditionImplied(NegatedOrEqual);
836 if (IsConditionImplied && IsNegatedOrEqualImplied)
840 bool IsNegatedImplied =
841 !Negated.empty() && SubCS.isConditionImplied(Negated);
844 bool IsStrictLessThanImplied =
845 !StrictLessThan.empty() && SubCS.isConditionImplied(StrictLessThan);
851 if (IsNegatedImplied || IsStrictLessThanImplied)
857 if (IsConditionImplied)
861 auto IsNegatedImplied = !Negated.empty() && SubCS.isConditionImplied(Negated);
862 if (IsNegatedImplied)
871 auto R = getConstraintForSolving(Pred,
A,
B);
872 return R.isValid(*
this) &&
873 getCS(
R.IsSigned).isConditionImpliedInSubSystem(
R.Coefficients);
876void ConstraintInfo::transferToOtherSystem(
878 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
879 auto IsKnownNonNegative = [
this](
Value *
V) {
885 if (!
A->getType()->isIntegerTy())
896 if (IsKnownNonNegative(
B)) {
906 if (IsKnownNonNegative(
A)) {
915 if (IsKnownNonNegative(
A))
923 if (IsKnownNonNegative(
B))
929 if (IsKnownNonNegative(
B))
940 CS.addVariableRowFill(
C);
945void State::addInfoForInductions(BasicBlock &BB) {
952 if (Header != &BB && Latch != &BB)
959 PHINode *PN =
nullptr;
960 const APInt *IncStep =
nullptr;
978 if (&BB == Latch && !IncStep)
989 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB) || InLoopSucc == &BB)
993 if (!LoopPred || !
L->isLoopInvariant(
B))
1001 const APInt *StepOffset =
nullptr;
1002 const SCEV *StartSCEV =
nullptr;
1003 OverflowingBinaryOperator *Inc =
nullptr;
1005 if (StepOffset->
isZero())
1009 const SCEV *Expr = SE.
getSCEV(PN);
1020 if (IncStep && (*IncStep != *StepOffset || StepOffset->
isNegative()))
1026 if (!(-*StepOffset).isOne())
1032 WorkList.
push_back(FactOrCheck::getConditionFact(
1035 WorkList.
push_back(FactOrCheck::getConditionFact(
1040 WorkList.
push_back(FactOrCheck::getConditionFact(
1043 WorkList.
push_back(FactOrCheck::getConditionFact(
1053 if (!(MonotonicallyIncreasingUnsigned && MonotonicallyIncreasingSigned)) {
1055 if (!MonotonicallyIncreasingUnsigned)
1056 MonotonicallyIncreasingUnsigned =
1059 if (!MonotonicallyIncreasingSigned)
1060 MonotonicallyIncreasingSigned =
1067 if (MonotonicallyIncreasingUnsigned)
1070 if (MonotonicallyIncreasingSigned)
1080 if (!StepOffset->
isOne()) {
1083 StartSCEV = SE.
getSCEV(StartValue);
1090 Value *LowerBound = StartValue;
1091 bool LowerBoundNUW =
true, LowerBoundNSW =
true;
1096 bool UOverflow =
false, SOverflow =
false;
1097 APInt Sum = StartC->getValue().uadd_ov(*StepOffset, UOverflow);
1098 (void)StartC->getValue().sadd_ov(*StepOffset, SOverflow);
1099 LowerBound = ConstantInt::get(StartValue->
getType(), Sum);
1100 LowerBoundNUW = !UOverflow;
1101 LowerBoundNSW = !SOverflow;
1109 if (!MonotonicallyIncreasingUnsigned && LowerBoundNUW)
1110 WorkList.
push_back(FactOrCheck::getConditionFact(
1112 if (!MonotonicallyIncreasingSigned && LowerBoundNSW)
1113 WorkList.
push_back(FactOrCheck::getConditionFact(
1118 B, StartBeforeBoundSLE));
1124 B, StartBeforeBoundULE));
1131 "unsupported predicate");
1133 L->getExitBlocks(ExitBBs);
1134 for (BasicBlock *EB : ExitBBs) {
1149 if (!
Offset.NW.hasNoUnsignedWrap())
1152 if (
Offset.VariableOffsets.size() != 1)
1156 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1158 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1167 std::optional<TypeSize>
Size =
1182 B = ConstantInt::get(Index->getType(), MaxIndex);
1186void State::addInfoFor(BasicBlock &BB) {
1187 addInfoForInductions(BB);
1193 bool GuaranteedToExecute =
true;
1195 for (Instruction &
I : BB) {
1197 for (Use &U :
I.uses()) {
1199 auto *DTN = DT.
getNode(UserI->getParent());
1202 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1207 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1211 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1214 if (GuaranteedToExecute) {
1216 Pred,
A,
B,
DL, TLI)) {
1224 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1229 if (!LI->isVolatile())
1230 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1233 if (!
SI->isVolatile())
1234 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1240 case Intrinsic::assume: {
1243 if (GuaranteedToExecute) {
1250 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1255 case Intrinsic::ssub_with_overflow:
1256 case Intrinsic::ucmp:
1257 case Intrinsic::scmp:
1262 case Intrinsic::umin:
1263 case Intrinsic::umax:
1264 case Intrinsic::smin:
1265 case Intrinsic::smax:
1270 case Intrinsic::uadd_sat:
1271 case Intrinsic::usub_sat:
1277 case Intrinsic::abs:
1287 if ((BO->getOpcode() == Instruction::URem ||
1288 BO->getOpcode() == Instruction::UDiv ||
1289 BO->getOpcode() == Instruction::LShr) &&
1298 for (
auto &Case :
Switch->cases()) {
1300 Value *
V = Case.getCaseValue();
1301 if (!canAddSuccessor(BB, Succ))
1330 SmallPtrSet<Value *, 8> SeenCond;
1331 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1332 if (SeenCond.
insert(V).second)
1337 while (!CondWorkList.
empty()) {
1362 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1364 DT.
getNode(Br->getSuccessor(0)), Pred,
A,
B));
1365 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1373 OS <<
"icmp " << Pred <<
' ';
1374 LHS->printAsOperand(OS,
true);
1376 RHS->printAsOperand(OS,
false);
1385struct ReproducerEntry {
1386 ICmpInst::Predicate Pred;
1421 auto &Value2Index = Info.getValue2Index(IsSigned);
1423 while (!WorkList.
empty()) {
1425 if (!Seen.
insert(V).second)
1427 if (Old2New.
find(V) != Old2New.
end())
1433 if (Value2Index.contains(V) || !
I ||
1444 for (
auto &Entry : Stack)
1447 CollectArguments(
Cond, IsSigned);
1450 for (
auto *
P : Args)
1456 Cond->getModule()->getName() +
1457 Cond->getFunction()->getName() +
"repro",
1460 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1462 Old2New[Args[
I]] =
F->getArg(
I);
1467 Builder.CreateRet(Builder.getTrue());
1468 Builder.SetInsertPoint(Entry->getTerminator());
1477 auto &Value2Index = Info.getValue2Index(IsSigned);
1478 while (!WorkList.
empty()) {
1480 if (Old2New.
find(V) != Old2New.
end())
1484 if (!Value2Index.contains(V) &&
I) {
1485 Old2New[V] =
nullptr;
1495 Old2New[
I] = Cloned;
1496 Old2New[
I]->setName(
I->getName());
1508 for (
auto &Entry : Stack) {
1517 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1518 Builder.CreateAssumption(Cmp);
1523 CloneInstructions(
Cond, IsSigned);
1524 Entry->getTerminator()->setOperand(0,
Cond);
1532 ConstraintInfo &Info) {
1535 auto TryWithConstraint = [&](
const ConstraintTy &R) -> std::optional<bool> {
1536 if (R.empty() || !R.isValid(Info)) {
1538 return std::nullopt;
1541 auto &CSToUse = Info.getCS(R.IsSigned);
1542 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1544 return std::nullopt;
1546 dbgs() <<
"Condition ";
1548 *ImpliedCondition ? Pred
1551 dbgs() <<
" implied by dominating constraints\n";
1554 return ImpliedCondition;
1556 return std::nullopt;
1559 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1560 if (
auto ImpliedCondition = TryWithConstraint(R))
1561 return ImpliedCondition;
1566 const auto &Value2Index = Info.getValue2Index(
true);
1567 if (!Value2Index.contains(
A) && !Value2Index.contains(
B))
1568 return std::nullopt;
1571 auto SR = Info.getConstraint(Pred,
A,
B, NewVariables,
1573 if (NewVariables.
empty())
1574 if (
auto ImpliedCondition = TryWithConstraint(SR))
1575 return ImpliedCondition;
1577 return std::nullopt;
1582 ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1586 auto ReplaceCmpWithConstant = [&](
Instruction *CheckInst,
bool IsTrue) {
1588 ReproducerCondStack, Info, DT);
1593 auto *DTN = DT.
getNode(UserI->getParent());
1596 if (UserI->getParent() == ContextInst->
getParent() &&
1597 UserI->comesBefore(ContextInst))
1603 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1612 for (
auto *DVR : DVRUsers) {
1613 auto *DTN = DT.
getNode(DVR->getParent());
1617 auto *MarkedI = DVR->getInstruction();
1618 if (MarkedI->getParent() == ContextInst->
getParent() &&
1619 MarkedI->comesBefore(ContextInst))
1622 DVR->replaceVariableLocationOp(CheckInst, ConstantC);
1632 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1639 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1648 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1657 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1660 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1669 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1679 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1688 Module *ReproducerModule,
1691 Info.popLastConstraint(
E.IsSigned);
1693 auto &Mapping = Info.getValue2Index(
E.IsSigned);
1694 for (
Value *V :
E.ValuesToRelease)
1696 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
1698 if (ReproducerModule)
1705 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
1714 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
1722 unsigned OldSize = DFSInStack.
size();
1725 while (OldSize < DFSInStack.
size()) {
1726 StackEntry
E = DFSInStack.
back();
1734 while (!Worklist.empty()) {
1735 Value *Val = Worklist.pop_back_val();
1743 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
1748 Worklist.push_back(
LHS);
1749 Worklist.push_back(
RHS);
1752 if (OldSize == DFSInStack.
size())
1757 [[maybe_unused]]
bool Matched =
1759 assert(Matched &&
"expected icmp-like match");
1761 if (
auto ImpliedCondition =
checkCondition(Pred,
A,
B, CmpToCheck, Info)) {
1762 if (IsOr == *ImpliedCondition)
1775 unsigned NumIn,
unsigned NumOut,
1776 SmallVectorImpl<StackEntry> &DFSInStack) {
1777 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
1780 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
1784 unsigned NumIn,
unsigned NumOut,
1785 SmallVectorImpl<StackEntry> &DFSInStack,
1786 bool ForceSignedSystem) {
1790 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
1793 if (!
R.isValid(*
this) ||
R.isNe())
1798 auto &CSToUse = getCS(
R.IsSigned);
1799 if (
R.Coefficients.empty())
1802 bool Added = CSToUse.addVariableRowFill(
R.Coefficients);
1808 SmallVector<Value *, 2> ValuesToRelease;
1809 auto &Value2Index = getValue2Index(
R.IsSigned);
1810 for (
Value *V : NewVariables) {
1811 Value2Index.try_emplace(V, Value2Index.size() + 1);
1816 dbgs() <<
" constraint: ";
1822 std::move(ValuesToRelease));
1825 for (
Value *V : NewVariables) {
1827 false,
false,
false);
1828 VarPos.Coefficients[Value2Index[
V]] = -1;
1829 CSToUse.addVariableRow(VarPos.Coefficients);
1831 SmallVector<Value *, 2>());
1837 for (
auto &Coeff :
R.Coefficients)
1840 CSToUse.addVariableRowFill(
R.Coefficients);
1843 SmallVector<Value *, 2>());
1855 Sub = Builder.CreateSub(
A,
B);
1856 U->replaceAllUsesWith(
Sub);
1859 U->replaceAllUsesWith(Builder.getFalse());
1864 if (U->use_empty()) {
1872 if (
II->use_empty()) {
1873 II->eraseFromParent();
1883 ConstraintInfo &Info) {
1884 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1885 if (R.size() < 2 || !R.isValid(Info))
1888 auto &CSToUse = Info.getCS(R.IsSigned);
1889 return CSToUse.isConditionImpliedInSubSystem(R.Coefficients);
1893 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1900 ConstantInt::get(
A->getType(), 0), Info))
1914 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
1915 State S(DT, LI, SE, TLI);
1916 std::unique_ptr<Module> ReproducerModule(
1935 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
1936 auto HasNoConstOp = [](const FactOrCheck &B) {
1937 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
1938 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
1939 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
1943 if (
A.NumIn ==
B.NumIn) {
1944 if (A.isConditionFact() && B.isConditionFact()) {
1945 bool NoConstOpA = HasNoConstOp(A);
1946 bool NoConstOpB = HasNoConstOp(B);
1947 return NoConstOpA < NoConstOpB;
1949 if (
A.isConditionFact())
1951 if (
B.isConditionFact())
1953 auto *InstA =
A.getContextInst();
1954 auto *InstB =
B.getContextInst();
1955 return InstA->comesBefore(InstB);
1957 return A.NumIn <
B.NumIn;
1960 SmallVector<Instruction *>
ToRemove;
1965 for (FactOrCheck &CB : S.WorkList) {
1968 while (!DFSInStack.
empty()) {
1969 auto &
E = DFSInStack.
back();
1972 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
1974 if (CB.NumOut <=
E.NumOut)
1977 dbgs() <<
"Removing ";
1979 Info.getValue2Index(
E.IsSigned));
1991 Instruction *Inst = CB.getInstructionToSimplify();
1994 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
2000 Pred,
A,
B, Inst, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
2001 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
2005 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
2017 auto AddFact = [&](CmpPredicate Pred,
Value *
A,
Value *
B) {
2023 <<
"Skip adding constraint because system has too many rows.\n");
2027 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
2028 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
2037 CB.NumIn, CB.NumOut, DFSInStack);
2039 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
2053 SmallPtrSet<Value *, 4> Seen;
2054 while (!Worklist.
empty()) {
2057 if (!BO || BO->getOpcode() !=
Opc)
2059 for (
Value *
Op : {BO->getOperand(0), BO->getOperand(1)}) {
2063 Info.addFact(Pred,
Op,
B, CB.NumIn, CB.NumOut, DFSInStack);
2068 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
2071 for (
unsigned I = 0,
2072 E = (DFSInStack.
size() - ReproducerCondStack.
size());
2074 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
2080 if (!CB.isConditionFact()) {
2086 ConstantInt::get(CB.Inst->getType(), 0));
2092 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
2093 AddFact(Pred, MinMax, MinMax->getLHS());
2094 AddFact(Pred, MinMax, MinMax->getRHS());
2098 switch (USatI->getIntrinsicID()) {
2101 case Intrinsic::uadd_sat:
2102 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2103 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2105 case Intrinsic::usub_sat:
2106 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2113 if (BO->getOpcode() == Instruction::URem) {
2120 if (BO->getOpcode() == Instruction::UDiv) {
2125 if (BO->getOpcode() == Instruction::LShr) {
2132 auto &
DL =
F.getDataLayout();
2133 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2138 DL.getTypeStoreSize(AccessType).getFixedValue(), Pred,
A,
B,
DL,
2140 AddFact(Pred,
A,
B);
2144 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2148 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2153 if (CB.isConditionFact()) {
2154 Pred = CB.Cond.Pred;
2158 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2160 dbgs() <<
"Not adding fact ";
2162 dbgs() <<
" because precondition ";
2165 dbgs() <<
" does not hold.\n";
2170 [[maybe_unused]]
bool Matched =
2174 "Must have an assume intrinsic with a icmp like operand");
2176 AddFact(Pred,
A,
B);
2179 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2181 raw_string_ostream StringS(S);
2182 ReproducerModule->print(StringS,
nullptr);
2183 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2184 Rem <<
ore::NV(
"module") << S;
2189 unsigned SignedEntries =
2190 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2191 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2192 DFSInStack.
size() - SignedEntries &&
2193 "updates to CS and DFSInStack are out of sync");
2194 assert(
Info.getCS(
true).size() == SignedEntries &&
2195 "updates to CS and DFSInStack are out of sync");
2199 I->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
std::pair< ICmpInst *, unsigned > ConditionTy
static int64_t MaxConstraintValue
static int64_t MinSignedConstraintValue
static Instruction * getContextInstForUse(Use &U)
static Decomposition decomposeGEP(GEPOperator &GEP, SmallVectorImpl< ConditionTy > &Preconditions, bool IsSigned, const DataLayout &DL)
static bool canUseSExt(ConstantInt *CI)
static void dumpConstraint(ArrayRef< int64_t > C, const DenseMap< Value *, unsigned > &Value2Index)
static void removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack)
static std::optional< bool > checkCondition(CmpInst::Predicate Pred, Value *A, Value *B, Instruction *CheckInst, ConstraintInfo &Info)
static cl::opt< unsigned > MaxRows("constraint-elimination-max-rows", cl::init(500), cl::Hidden, cl::desc("Maximum number of rows to keep in constraint system"))
static cl::opt< bool > DumpReproducers("constraint-elimination-dump-reproducers", cl::init(false), cl::Hidden, cl::desc("Dump IR to reproduce successful transformations."))
static bool checkOrAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack, SmallVectorImpl< Instruction * > &ToRemove)
Check if either the first condition of an AND or OR is implied by the (negated in case of OR) second ...
static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE, OptimizationRemarkEmitter &ORE, TargetLibraryInfo &TLI)
static OffsetResult collectOffsets(GEPOperator &GEP, const DataLayout &DL)
static bool checkAndReplaceMinMax(MinMaxIntrinsic *MinMax, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
static bool getConstraintFromMemoryAccess(GetElementPtrInst &GEP, uint64_t AccessSize, CmpPredicate &Pred, Value *&A, Value *&B, const DataLayout &DL, const TargetLibraryInfo &TLI)
static void dumpUnpackedICmp(raw_ostream &OS, ICmpInst::Predicate Pred, Value *LHS, Value *RHS)
static void generateReproducer(Instruction *Cond, bool IsSigned, Module *M, ArrayRef< ReproducerEntry > Stack, ConstraintInfo &Info, DominatorTree &DT)
Helper function to generate a reproducer function for simplifying Cond.
static Decomposition decompose(Value *V, SmallVectorImpl< ConditionTy > &Preconditions, bool IsSigned, const DataLayout &DL)
static bool checkAndReplaceCondition(CmpPredicate Pred, Value *A, Value *B, Instruction *CheckInst, ConstraintInfo &Info, unsigned NumIn, unsigned NumOut, Instruction *ContextInst, Module *ReproducerModule, ArrayRef< ReproducerEntry > ReproducerCondStack, DominatorTree &DT, SmallVectorImpl< Instruction * > &ToRemove)
static bool replaceSubOverflowUses(IntrinsicInst *II, Value *A, Value *B, SmallVectorImpl< Instruction * > &ToRemove)
static bool tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Machine Check Debug Module
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
bool isNegative() const
Determine sign of this APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool slt(const APInt &RHS) const
Signed less than comparison.
bool isOne() const
Determine if this is a value of 1.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this basic block belongs to.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Represents analyses that only rely on functions' control flow.
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
bool isEquality() const
Determine if this is an equals/not equals predicate.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ ICMP_ULT
unsigned less than
@ ICMP_SGE
signed greater or equal
@ ICMP_ULE
unsigned less or equal
static LLVM_ABI bool isEquality(Predicate pred)
Determine if this is an equals/not equals predicate.
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Predicate getNonStrictPredicate() const
For example, SGT -> SGE, SLT -> SLE, ULT -> ULE, UGT -> UGE.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
This class represents a ucmp/scmp intrinsic.
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
static LLVM_ABI CmpPredicate getInverse(CmpPredicate P)
Get the inverse predicate of a CmpPredicate.
bool hasSameSign() const
Query samesign information, for optimizations.
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
const APInt & getValue() const
Return the constant as an APInt value reference.
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
static SmallVector< int64_t, 8 > negate(SmallVector< int64_t, 8 > R)
static SmallVector< int64_t, 8 > toStrictLessThan(SmallVector< int64_t, 8 > R)
Converts the given vector to form a strict less than inequality.
static SmallVector< int64_t, 8 > negateOrEqual(SmallVector< int64_t, 8 > R)
Multiplies each coefficient in the given vector by -1.
A parsed version of the target data layout string in and methods for querying it.
static bool shouldExecute(CounterInfo &Counter)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const KeyT &Val)
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.
unsigned getDFSNumOut() const
Analysis pass which computes a DominatorTree.
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
static GEPNoWrapFlags none()
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
@ ExternalLinkage
Externally visible function.
Predicate getFlippedSignednessPredicate() const
For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->EQ.
Predicate getSignedPredicate() const
For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
bool isRelational() const
Return true if the predicate is relational (not EQ or NE).
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})
Drop all unknown metadata except for debug locations.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
Analysis pass that exposes the LoopInfo for a function.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
This class represents min/max intrinsics.
A Module instance is used to store all the information related to an LLVM module.
bool hasNoSignedWrap() const
Test whether this operation is known to never undergo signed overflow, aka the nsw property.
bool hasNoUnsignedWrap() const
Test whether this operation is known to never undergo unsigned overflow, aka the nuw property.
Value * getIncomingValueForBlock(const BasicBlock *BB) const
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI bool isSCEVable(Type *Ty) const
Test if values of the given type are analyzable within the SCEV framework.
@ MonotonicallyIncreasing
LLVM_ABI APInt getConstantMultiple(const SCEV *S, const Instruction *CtxI=nullptr)
Returns the max constant multiple of S.
LLVM_ABI std::optional< MonotonicPredicateType > getMonotonicPredicateType(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred)
If, for all loop invariant X, the predicate "LHS `Pred` X" is monotonically increasing or decreasing,...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
iterator find(const KeyT &Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI const Value * stripPointerCastsSameRepresentation() const
Strip off pointer casts, all-zero GEPs and address space casts but ensures the representation of the ...
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
constexpr ScalarTy getFixedValue() const
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
match_bind< PHINode > m_Phi(PHINode *&PN)
Match a PHI node, capturing it if we match.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWAdd(const LHS &L, const RHS &R)
auto m_LogicalOp()
Matches either L && R or L || R where L and R are arbitrary values.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(const LHS &L, const RHS &R)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
DisjointOr_match< LHS, RHS > m_DisjointOr(const LHS &L, const RHS &R)
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
ExtractValue_match< Ind, Val_t > m_ExtractValue(const Val_t &V)
Match a single index ExtractValue instruction.
ICmpLike_match< LHS, RHS > m_ICmpLike(CmpPredicate &Pred, const LHS &L, const RHS &R)
auto m_Value()
Match an arbitrary value and ignore it.
NoWrapTrunc_match< OpTy, TruncInst::NoSignedWrap > m_NSWTrunc(const OpTy &Op)
Matches trunc nsw.
NNegZExt_match< OpTy > m_NNegZExt(const OpTy &Op)
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoSignedWrap > m_NSWShl(const LHS &L, const RHS &R)
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWShl(const LHS &L, const RHS &R)
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWMul(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWSub(const LHS &L, const RHS &R)
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap > m_NSWAdd(const LHS &L, const RHS &R)
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoSignedWrap > m_NSWMul(const LHS &L, const RHS &R)
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
bind_cst_ty m_scev_APInt(const APInt *&C)
Match an SCEV constant and bind it to an APInt.
specificloop_ty m_SpecificLoop(const Loop *L)
bool match(const SCEV *S, const Pattern &P)
SCEVAffineAddRec_match< Op0_t, Op1_t, match_isa< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
initializer< Ty > init(const Ty &Val)
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr std::enable_if_t< std::is_signed_v< T >, std::pair< T, bool > > AddOverflow(T X, T Y)
Add two signed integers, computing the two's complement truncated result, returning a pair {result,...
LLVM_ABI std::optional< TypeSize > getBaseObjectSize(const Value *Ptr, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Like getObjectSize(), but only returns the size of base objects (like allocas, global variables and a...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
DomTreeNodeBase< BasicBlock > DomTreeNode
constexpr std::enable_if_t< std::is_signed_v< T >, std::pair< T, bool > > SubOverflow(T X, T Y)
Subtract two signed integers, computing the two's complement truncated result, returning a pair {resu...
constexpr unsigned MaxAnalysisRecursionDepth
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
LLVM_ABI void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
constexpr std::enable_if_t< std::is_signed_v< T >, std::pair< T, bool > > MulOverflow(T X, T Y)
Multiply two signed integers, computing the two's complement truncated result, returning a pair {resu...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be poison, but may be undef.
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
LLVM_ABI void findDbgUsers(Value *V, SmallVectorImpl< DbgVariableRecord * > &DbgVariableRecords)
Finds the debug info records describing a value.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Various options to control the behavior of getObjectSize.
bool NullIsUnknownSize
If this is true, null pointers in address space 0 will be treated as though they can't be evaluated.
bool RoundToAlign
Whether to round the result up to the alignment of allocas, byval arguments, and global variables.
A MapVector that performs no allocations if smaller than a certain size.