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)) {}
217 bool IsSigned =
false;
219 ConstraintTy() =
default;
223 : Coefficients(std::
move(Coefficients)), IsSigned(IsSigned), IsEq(IsEq),
226 unsigned size()
const {
return Coefficients.size(); }
228 bool empty()
const {
return Coefficients.empty(); }
230 bool isEq()
const {
return IsEq; }
232 bool isNe()
const {
return IsNe; }
239 std::optional<bool> isImpliedBy(
const ConstraintSystem &CS)
const;
252class ConstraintInfo {
254 ConstraintSystem UnsignedCS;
255 ConstraintSystem SignedCS;
257 const DataLayout &DL;
261 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
262 auto &Value2Index = getValue2Index(
false);
264 for (
Value *Arg : FunctionArgs) {
266 false,
false,
false);
267 VarPos.Coefficients[Value2Index[Arg]] = -1;
268 UnsignedCS.addVariableRow(VarPos.Coefficients);
272 DenseMap<Value *, unsigned> &getValue2Index(
bool Signed) {
273 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
275 const DenseMap<Value *, unsigned> &getValue2Index(
bool Signed)
const {
276 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
279 ConstraintSystem &getCS(
bool Signed) {
280 return Signed ? SignedCS : UnsignedCS;
282 const ConstraintSystem &getCS(
bool Signed)
const {
283 return Signed ? SignedCS : UnsignedCS;
286 void popLastConstraint(
bool Signed) { getCS(
Signed).popLastConstraint(); }
287 void popLastNVariables(
bool Signed,
unsigned N) {
288 getCS(
Signed).popLastNVariables(
N);
298 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
305 SmallVectorImpl<Value *> &NewVariables,
306 bool ForceSignedSystem =
false)
const;
321 unsigned NumIn,
unsigned NumOut,
322 SmallVectorImpl<StackEntry> &DFSInStack);
329 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
330 bool ForceSignedSystem);
334 void tightenBoundUsingNe(
Value *
A,
Value *
B,
unsigned NumIn,
unsigned NumOut,
335 SmallVectorImpl<StackEntry> &DFSInStack);
343 DecompEntry(int64_t Coefficient,
Value *Variable)
344 : Coefficient(Coefficient), Variable(Variable) {}
348struct Decomposition {
352 Decomposition(int64_t Offset) : Offset(Offset) {}
353 Decomposition(
Value *V) { Vars.emplace_back(1, V); }
355 : Offset(Offset), Vars(Vars) {}
359 [[nodiscard]]
bool add(int64_t OtherOffset) {
365 [[nodiscard]]
bool add(
const Decomposition &
Other) {
374 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
375 Decomposition Tmp =
Other;
386 [[nodiscard]]
bool mul(int64_t Factor) {
389 for (
auto &Var : Vars)
390 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
399 APInt ConstantOffset;
400 SmallMapVector<Value *, APInt, 4> VariableOffsets;
403 OffsetResult() :
BasePtr(nullptr), ConstantOffset(0, uint64_t(0)) {}
405 OffsetResult(GEPOperator &
GEP,
const DataLayout &
DL)
407 ConstantOffset = APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
417 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
419 Result.ConstantOffset))
427 bool CanCollectInner = InnerGEP->collectOffset(
428 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
430 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
431 VariableOffsets2.
size() > 1 ||
432 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
436 Result.BasePtr = InnerGEP->getPointerOperand();
437 Result.ConstantOffset += ConstantOffset2;
438 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
439 Result.VariableOffsets = std::move(VariableOffsets2);
440 Result.NW &= InnerGEP->getNoWrapFlags();
445static Decomposition
decompose(
Value *V,
const ConstraintInfo &Info,
457 return Info.doesHold(Pred,
Op, ConstantInt::get(
Op->getType(),
RHS));
464 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
467 assert(!IsSigned &&
"The logic below only supports decomposition for "
468 "unsigned predicates at the moment.");
469 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
478 if (!NW.hasNoUnsignedSignedWrap() && ConstantOffset.isNegative())
481 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
482 for (
auto [Index, Scale] : VariableOffsets) {
483 if (!NW.hasNoUnsignedWrap()) {
486 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
492 auto IdxResult =
decompose(Index, Info, IsSigned,
DL);
493 if (IdxResult.mul(Scale.getSExtValue()))
495 if (Result.add(IdxResult))
509 auto MergeResults = [&Info, IsSigned,
511 bool IsSignedB) -> std::optional<Decomposition> {
520 if (Ty->isPointerTy() && !IsSigned) {
532 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
539 return CI->getSExtValue();
554 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
561 Decomposition Result(-1);
562 if (!Result.sub(
decompose(Op0, Info, IsSigned,
DL)))
587 if (Shift < Ty->getIntegerBitWidth() - 1) {
588 assert(Shift < 64 &&
"Would overflow");
590 if (!Result.mul(int64_t(1) << Shift))
602 return int64_t(CI->getZExtValue());
614 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64 &&
615 (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap())) {
616 Value *Src = Trunc->getOperand(0);
619 if (!Trunc->hasNoUnsignedWrap() &&
629 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
640 if (
auto Decomp = MergeResults(Op0, CI,
true))
654 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
661 if (
auto Decomp = MergeResults(Op0, CI, IsSigned))
704 bool ForceSignedSystem)
const {
705 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
707 "signed system can only be forced on eq/ne");
748 auto &Value2Index = getValue2Index(IsSigned);
753 int64_t Offset1 = ADec.Offset;
754 int64_t Offset2 = BDec.Offset;
757 auto &VariablesA = ADec.Vars;
758 auto &VariablesB = BDec.Vars;
762 SmallDenseMap<Value *, unsigned> NewIndexMap;
763 auto GetOrAddIndex = [&Value2Index, &NewVariables,
764 &NewIndexMap](
Value *
V) ->
unsigned {
765 auto V2I = Value2Index.find(V);
766 if (V2I != Value2Index.end())
769 V, Value2Index.size() + NewVariables.size() + 1);
771 NewVariables.push_back(V);
777 GetOrAddIndex(KV.Variable);
783 IsSigned, IsEq, IsNe);
784 auto &
R = Res.Coefficients;
785 for (
const auto &KV : VariablesA)
786 R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
788 for (
const auto &KV : VariablesB) {
789 auto &Coeff =
R[GetOrAddIndex(KV.Variable)];
798 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
804 while (!NewVariables.empty()) {
805 int64_t
Last =
R.back();
809 Value *RemovedV = NewVariables.pop_back_val();
810 NewIndexMap.
erase(RemovedV);
824 auto &Value2Index = getValue2Index(
false);
839 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
840 if (!NewVariables.
empty())
846ConstraintTy::isImpliedBy(
const ConstraintSystem &CS)
const {
847 const auto &[SubCS, NewCoefficients] = CS.
getSubSystem(Coefficients);
848 bool IsConditionImplied = SubCS.isConditionImplied(NewCoefficients);
852 bool IsNegatedOrEqualImplied =
853 !NegatedOrEqual.empty() && SubCS.isConditionImplied(NegatedOrEqual);
858 if (IsConditionImplied && IsNegatedOrEqualImplied)
862 bool IsNegatedImplied =
863 !Negated.empty() && SubCS.isConditionImplied(Negated);
866 bool IsStrictLessThanImplied =
867 !StrictLessThan.empty() && SubCS.isConditionImplied(StrictLessThan);
873 if (IsNegatedImplied || IsStrictLessThanImplied)
879 if (IsConditionImplied)
883 auto IsNegatedImplied = !Negated.empty() && SubCS.isConditionImplied(Negated);
884 if (IsNegatedImplied)
893 auto R = getConstraintForSolving(Pred,
A,
B);
895 getCS(
R.IsSigned).isConditionImpliedInSubSystem(
R.Coefficients);
898bool ConstraintInfo::isKnownNonNegative(
Value *V)
const {
903void ConstraintInfo::transferToOtherSystem(
905 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
908 if (!
A->getType()->isIntegerTy())
968void State::addInfoForInductions(BasicBlock &BB) {
975 if (Header != &BB && Latch != &BB)
982 PHINode *PN =
nullptr;
983 const APInt *IncStep =
nullptr;
1001 if (&BB == Latch && !IncStep)
1012 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB) || InLoopSucc == &BB)
1016 if (!LoopPred || !
L->isLoopInvariant(
B))
1024 const APInt *StepOffset =
nullptr;
1025 const SCEV *StartSCEV =
nullptr;
1026 OverflowingBinaryOperator *Inc =
nullptr;
1028 if (StepOffset->
isZero())
1032 const SCEV *Expr = SE.
getSCEV(PN);
1043 if (IncStep && (*IncStep != *StepOffset || StepOffset->
isNegative()))
1049 if (!(-*StepOffset).isOne())
1055 WorkList.
push_back(FactOrCheck::getConditionFact(
1058 WorkList.
push_back(FactOrCheck::getConditionFact(
1063 WorkList.
push_back(FactOrCheck::getConditionFact(
1066 WorkList.
push_back(FactOrCheck::getConditionFact(
1076 if (!(MonotonicallyIncreasingUnsigned && MonotonicallyIncreasingSigned)) {
1078 if (!MonotonicallyIncreasingUnsigned)
1079 MonotonicallyIncreasingUnsigned =
1082 if (!MonotonicallyIncreasingSigned)
1083 MonotonicallyIncreasingSigned =
1090 if (MonotonicallyIncreasingUnsigned)
1093 if (MonotonicallyIncreasingSigned)
1103 if (!StepOffset->
isOne()) {
1106 StartSCEV = SE.
getSCEV(StartValue);
1113 Value *LowerBound = StartValue;
1114 bool LowerBoundNUW =
true, LowerBoundNSW =
true;
1119 bool UOverflow =
false, SOverflow =
false;
1120 APInt Sum = StartC->getValue().uadd_ov(*StepOffset, UOverflow);
1121 (void)StartC->getValue().sadd_ov(*StepOffset, SOverflow);
1122 LowerBound = ConstantInt::get(StartValue->
getType(), Sum);
1123 LowerBoundNUW = !UOverflow;
1124 LowerBoundNSW = !SOverflow;
1132 if (!MonotonicallyIncreasingUnsigned && LowerBoundNUW)
1133 WorkList.
push_back(FactOrCheck::getConditionFact(
1135 if (!MonotonicallyIncreasingSigned && LowerBoundNSW)
1136 WorkList.
push_back(FactOrCheck::getConditionFact(
1141 B, StartBeforeBoundSLE));
1147 B, StartBeforeBoundULE));
1154 "unsupported predicate");
1156 L->getExitBlocks(ExitBBs);
1157 for (BasicBlock *EB : ExitBBs) {
1172 if (!
Offset.NW.hasNoUnsignedWrap())
1175 if (
Offset.VariableOffsets.size() != 1)
1179 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1181 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1190 std::optional<TypeSize>
Size =
1205 B = ConstantInt::get(Index->getType(), MaxIndex);
1209void State::addInfoFor(BasicBlock &BB) {
1210 addInfoForInductions(BB);
1216 bool GuaranteedToExecute =
true;
1218 for (Instruction &
I : BB) {
1220 for (Use &U :
I.uses()) {
1222 auto *DTN = DT.
getNode(UserI->getParent());
1225 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1230 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1234 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1237 if (GuaranteedToExecute) {
1239 Pred,
A,
B,
DL, TLI)) {
1247 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1252 if (!LI->isVolatile())
1253 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1256 if (!
SI->isVolatile())
1257 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1263 case Intrinsic::assume: {
1266 if (GuaranteedToExecute) {
1273 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1278 case Intrinsic::ssub_with_overflow:
1279 case Intrinsic::ucmp:
1280 case Intrinsic::scmp:
1285 case Intrinsic::umin:
1286 case Intrinsic::umax:
1287 case Intrinsic::smin:
1288 case Intrinsic::smax:
1293 case Intrinsic::uadd_sat:
1294 case Intrinsic::usub_sat:
1300 case Intrinsic::abs:
1313 if ((BO->getOpcode() == Instruction::URem ||
1314 BO->getOpcode() == Instruction::UDiv ||
1315 BO->getOpcode() == Instruction::LShr ||
1316 BO->getOpcode() == Instruction::SRem) &&
1325 for (
auto &Case :
Switch->cases()) {
1327 Value *
V = Case.getCaseValue();
1328 if (!canAddSuccessor(BB, Succ))
1357 SmallPtrSet<Value *, 8> SeenCond;
1358 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1359 if (SeenCond.
insert(V).second)
1364 while (!CondWorkList.
empty()) {
1389 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1391 DT.
getNode(Br->getSuccessor(0)), Pred,
A,
B));
1392 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1400 OS <<
"icmp " << Pred <<
' ';
1401 LHS->printAsOperand(OS,
true);
1403 RHS->printAsOperand(OS,
false);
1412struct ReproducerEntry {
1413 ICmpInst::Predicate Pred;
1448 auto &Value2Index = Info.getValue2Index(IsSigned);
1450 while (!WorkList.
empty()) {
1452 if (!Seen.
insert(V).second)
1454 if (Old2New.
find(V) != Old2New.
end())
1460 if (Value2Index.contains(V) || !
I ||
1471 for (
auto &Entry : Stack)
1474 CollectArguments(
Cond, IsSigned);
1477 for (
auto *
P : Args)
1483 Cond->getModule()->getName() +
1484 Cond->getFunction()->getName() +
"repro",
1487 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1489 Old2New[Args[
I]] =
F->getArg(
I);
1494 Builder.CreateRet(Builder.getTrue());
1495 Builder.SetInsertPoint(Entry->getTerminator());
1504 auto &Value2Index = Info.getValue2Index(IsSigned);
1505 while (!WorkList.
empty()) {
1507 if (Old2New.
find(V) != Old2New.
end())
1511 if (!Value2Index.contains(V) &&
I) {
1512 Old2New[V] =
nullptr;
1522 Old2New[
I] = Cloned;
1523 Old2New[
I]->setName(
I->getName());
1535 for (
auto &Entry : Stack) {
1544 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1545 Builder.CreateAssumption(Cmp);
1550 CloneInstructions(
Cond, IsSigned);
1551 Entry->getTerminator()->setOperand(0,
Cond);
1559 ConstraintInfo &Info) {
1562 auto TryWithConstraint = [&](
const ConstraintTy &R) -> std::optional<bool> {
1565 return std::nullopt;
1568 auto &CSToUse = Info.getCS(R.IsSigned);
1569 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1571 return std::nullopt;
1573 dbgs() <<
"Condition ";
1575 *ImpliedCondition ? Pred
1578 dbgs() <<
" implied by dominating constraints\n";
1581 return ImpliedCondition;
1583 return std::nullopt;
1586 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1587 if (
auto ImpliedCondition = TryWithConstraint(R))
1588 return ImpliedCondition;
1596 if (NewVariables.
empty() && !SR.empty() && Info.isKnownNonNegative(
A) &&
1597 Info.isKnownNonNegative(
B))
1598 if (
auto ImpliedCondition = TryWithConstraint(SR))
1599 return ImpliedCondition;
1605 const auto &Value2Index = Info.getValue2Index(
true);
1606 if (!Value2Index.contains(
A) && !Value2Index.contains(
B))
1607 return std::nullopt;
1610 auto SR = Info.getConstraint(Pred,
A,
B, NewVariables,
1612 if (NewVariables.
empty())
1613 if (
auto ImpliedCondition = TryWithConstraint(SR))
1614 return ImpliedCondition;
1616 return std::nullopt;
1621 ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1625 auto ReplaceCmpWithConstant = [&](
Instruction *CheckInst,
bool IsTrue) {
1627 ReproducerCondStack, Info, DT);
1632 auto *DTN = DT.
getNode(UserI->getParent());
1635 if (UserI->getParent() == ContextInst->
getParent() &&
1636 UserI->comesBefore(ContextInst))
1642 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1651 for (
auto *DVR : DVRUsers) {
1652 auto *DTN = DT.
getNode(DVR->getParent());
1656 auto *MarkedI = DVR->getInstruction();
1657 if (MarkedI->getParent() == ContextInst->
getParent() &&
1658 MarkedI->comesBefore(ContextInst))
1661 DVR->replaceVariableLocationOp(CheckInst, ConstantC);
1671 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1678 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1687 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1696 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1699 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1708 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1718 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1727 Module *ReproducerModule,
1730 Info.popLastConstraint(
E.IsSigned);
1732 auto &Mapping = Info.getValue2Index(
E.IsSigned);
1733 for (
Value *V :
E.ValuesToRelease)
1735 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
1737 if (ReproducerModule)
1744 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
1753 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
1761 unsigned OldSize = DFSInStack.
size();
1764 while (OldSize < DFSInStack.
size()) {
1765 StackEntry
E = DFSInStack.
back();
1773 while (!Worklist.empty()) {
1774 Value *Val = Worklist.pop_back_val();
1782 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
1787 Worklist.push_back(
LHS);
1788 Worklist.push_back(
RHS);
1791 if (OldSize == DFSInStack.
size())
1796 [[maybe_unused]]
bool Matched =
1798 assert(Matched &&
"expected icmp-like match");
1800 if (
auto ImpliedCondition =
checkCondition(Pred,
A,
B, CmpToCheck, Info)) {
1801 if (IsOr == *ImpliedCondition)
1814 unsigned NumIn,
unsigned NumOut,
1815 SmallVectorImpl<StackEntry> &DFSInStack) {
1816 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
1819 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
1821 tightenBoundUsingNe(
A,
B, NumIn, NumOut, DFSInStack);
1824void ConstraintInfo::tightenBoundUsingNe(
1826 SmallVectorImpl<StackEntry> &DFSInStack) {
1827 if (!
A->getType()->isIntegerTy())
1830 for (
bool IsSigned : {
false,
true}) {
1837 const auto &Value2Index = getValue2Index(IsSigned);
1839 [&Value2Index](
const DecompEntry &
E) {
1840 return !Value2Index.contains(
E.Variable);
1851 if (!doesHold(NonStrict,
A,
B))
1857 dbgs() <<
"' using inequality\n");
1858 addFactImpl(
Strict,
A,
B, NumIn, NumOut, DFSInStack,
1866 unsigned NumIn,
unsigned NumOut,
1867 SmallVectorImpl<StackEntry> &DFSInStack,
1868 bool ForceSignedSystem) {
1870 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
1873 if (
R.empty() ||
R.isNe())
1878 auto &CSToUse = getCS(
R.IsSigned);
1879 if (
R.Coefficients.empty())
1882 bool Added = CSToUse.addVariableRowFill(
R.Coefficients);
1888 SmallVector<Value *, 2> ValuesToRelease;
1889 auto &Value2Index = getValue2Index(
R.IsSigned);
1890 for (
Value *V : NewVariables) {
1891 Value2Index.try_emplace(V, Value2Index.size() + 1);
1896 dbgs() <<
" constraint: ";
1902 std::move(ValuesToRelease));
1905 for (
Value *V : NewVariables) {
1907 false,
false,
false);
1908 VarPos.Coefficients[Value2Index[
V]] = -1;
1909 CSToUse.addVariableRow(VarPos.Coefficients);
1911 SmallVector<Value *, 2>());
1917 for (
auto &Coeff :
R.Coefficients)
1920 CSToUse.addVariableRowFill(
R.Coefficients);
1923 SmallVector<Value *, 2>());
1935 Sub = Builder.CreateNSWSub(
A,
B);
1936 U->replaceAllUsesWith(
Sub);
1939 U->replaceAllUsesWith(Builder.getFalse());
1944 if (U->use_empty()) {
1952 if (
II->use_empty()) {
1954 for (
Use &Arg :
II->args())
1966 ConstraintInfo &Info) {
1967 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1971 auto &CSToUse = Info.getCS(R.IsSigned);
1972 return CSToUse.isConditionImpliedInSubSystem(R.Coefficients);
1976 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1983 ConstantInt::get(
A->getType(), 0), Info))
1997 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
1998 State S(DT, LI, SE, TLI);
1999 std::unique_ptr<Module> ReproducerModule(
2018 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
2019 auto HasNoConstOp = [](const FactOrCheck &B) {
2020 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
2021 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
2022 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
2026 if (
A.NumIn ==
B.NumIn) {
2027 if (A.isConditionFact() && B.isConditionFact()) {
2028 bool NoConstOpA = HasNoConstOp(A);
2029 bool NoConstOpB = HasNoConstOp(B);
2030 return NoConstOpA < NoConstOpB;
2032 if (
A.isConditionFact())
2034 if (
B.isConditionFact())
2036 auto *InstA =
A.getContextInst();
2037 auto *InstB =
B.getContextInst();
2038 return InstA->comesBefore(InstB);
2040 return A.NumIn <
B.NumIn;
2043 SmallVector<Instruction *>
ToRemove;
2048 for (FactOrCheck &CB : S.WorkList) {
2051 while (!DFSInStack.
empty()) {
2052 auto &
E = DFSInStack.
back();
2055 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
2057 if (CB.NumOut <=
E.NumOut)
2060 dbgs() <<
"Removing ";
2062 Info.getValue2Index(
E.IsSigned));
2074 Instruction *Inst = CB.getInstructionToSimplify();
2077 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
2083 Pred,
A,
B, Inst, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
2084 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
2088 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
2100 auto AddFact = [&](CmpPredicate Pred,
Value *
A,
Value *
B) {
2106 <<
"Skip adding constraint because system has too many rows.\n");
2110 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
2111 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
2120 CB.NumIn, CB.NumOut, DFSInStack);
2122 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
2136 SmallPtrSet<Value *, 4> Seen;
2137 while (!Worklist.
empty()) {
2140 if (!BO || BO->getOpcode() !=
Opc)
2142 for (
Value *
Op : {BO->getOperand(0), BO->getOperand(1)}) {
2146 Info.addFact(Pred,
Op,
B, CB.NumIn, CB.NumOut, DFSInStack);
2151 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
2154 for (
unsigned I = 0,
2155 E = (DFSInStack.
size() - ReproducerCondStack.
size());
2157 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
2163 if (!CB.isConditionFact()) {
2169 ConstantInt::get(CB.Inst->getType(), 0));
2175 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
2176 AddFact(Pred, MinMax, MinMax->getLHS());
2177 AddFact(Pred, MinMax, MinMax->getRHS());
2181 switch (USatI->getIntrinsicID()) {
2184 case Intrinsic::uadd_sat:
2185 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2186 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2188 case Intrinsic::usub_sat:
2189 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2196 if (BO->getOpcode() == Instruction::URem) {
2203 if (BO->getOpcode() == Instruction::UDiv) {
2208 if (BO->getOpcode() == Instruction::LShr) {
2213 if (BO->getOpcode() == Instruction::SRem) {
2214 Value *
X = BO->getOperand(0);
2215 Value *
N = BO->getOperand(1);
2235 auto &
DL =
F.getDataLayout();
2236 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2241 DL.getTypeStoreSize(AccessType).getFixedValue(), Pred,
A,
B,
DL,
2243 AddFact(Pred,
A,
B);
2247 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2251 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2256 if (CB.isConditionFact()) {
2257 Pred = CB.Cond.Pred;
2261 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2263 dbgs() <<
"Not adding fact ";
2265 dbgs() <<
" because precondition ";
2268 dbgs() <<
" does not hold.\n";
2273 [[maybe_unused]]
bool Matched =
2277 "Must have an assume intrinsic with a icmp like operand");
2279 AddFact(Pred,
A,
B);
2282 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2284 raw_string_ostream StringS(S);
2285 ReproducerModule->print(StringS,
nullptr);
2286 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2287 Rem <<
ore::NV(
"module") << S;
2292 unsigned SignedEntries =
2293 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2294 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2295 DFSInStack.
size() - SignedEntries &&
2296 "updates to CS and DFSInStack are out of sync");
2297 assert(
Info.getCS(
true).size() == SignedEntries &&
2298 "updates to CS and DFSInStack are out of sync");
2302 I->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 bool preconditionHolds(const ConstraintInfo &Info, CmpInst::Predicate Pred, Value *Op, int64_t RHS)
Returns true if the pre-condition Op Pred RHS, required to look through an expression while decomposi...
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 Decomposition decompose(Value *V, const ConstraintInfo &Info, bool IsSigned, const DataLayout &DL)
static Decomposition decomposeGEP(GEPOperator &GEP, const ConstraintInfo &Info, bool IsSigned, const DataLayout &DL)
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 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.
static bool hasNoUnsignedWrap(BinaryOperator &I)
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
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
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.
Predicate getStrictPredicate() const
For example, SGE -> SGT, SLE -> SLT, ULE -> ULT, UGE -> UGT.
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)
LLVM_ABI std::pair< ConstraintSystem, SmallVector< int64_t, 8 > > getSubSystem(ArrayRef< int64_t > R) const
Build and return a sub-system of constraints connected (transitively) to query R, with variables comp...
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.
bool addVariableRowFill(ArrayRef< int64_t > R)
LLVM_ABI void dump() const
Print the constraints in the system.
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.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
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::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)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(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)
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
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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 isKnownPositive(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the given value is known be positive (i.e.
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.