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);
294 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
301 SmallVectorImpl<Value *> &NewVariables,
302 bool ForceSignedSystem =
false)
const;
317 unsigned NumIn,
unsigned NumOut,
318 SmallVectorImpl<StackEntry> &DFSInStack);
325 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
326 bool ForceSignedSystem);
330 void tightenBoundUsingNe(
Value *
A,
Value *
B,
unsigned NumIn,
unsigned NumOut,
331 SmallVectorImpl<StackEntry> &DFSInStack);
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();
441static Decomposition
decompose(
Value *V,
const ConstraintInfo &Info,
453 return Info.doesHold(Pred,
Op, ConstantInt::get(
Op->getType(),
RHS));
460 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
463 assert(!IsSigned &&
"The logic below only supports decomposition for "
464 "unsigned predicates at the moment.");
465 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
474 if (!NW.hasNoUnsignedSignedWrap() && ConstantOffset.isNegative())
477 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
478 for (
auto [Index, Scale] : VariableOffsets) {
479 if (!NW.hasNoUnsignedWrap()) {
482 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
488 auto IdxResult =
decompose(Index, Info, IsSigned,
DL);
489 if (IdxResult.mul(Scale.getSExtValue()))
491 if (Result.add(IdxResult))
505 auto MergeResults = [&Info, IsSigned,
507 bool IsSignedB) -> std::optional<Decomposition> {
516 if (Ty->isPointerTy() && !IsSigned) {
528 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
535 return CI->getSExtValue();
550 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
557 Decomposition Result(-1);
558 if (!Result.sub(
decompose(Op0, Info, IsSigned,
DL)))
583 if (Shift < Ty->getIntegerBitWidth() - 1) {
584 assert(Shift < 64 &&
"Would overflow");
586 if (!Result.mul(int64_t(1) << Shift))
598 return int64_t(CI->getZExtValue());
610 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64 &&
611 (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap())) {
612 Value *Src = Trunc->getOperand(0);
615 if (!Trunc->hasNoUnsignedWrap() &&
625 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
636 if (
auto Decomp = MergeResults(Op0, CI,
true))
650 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
657 if (
auto Decomp = MergeResults(Op0, CI, IsSigned))
698 bool ForceSignedSystem)
const {
699 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
701 "signed system can only be forced on eq/ne");
742 auto &Value2Index = getValue2Index(IsSigned);
747 int64_t Offset1 = ADec.Offset;
748 int64_t Offset2 = BDec.Offset;
751 auto &VariablesA = ADec.Vars;
752 auto &VariablesB = BDec.Vars;
756 SmallDenseMap<Value *, unsigned> NewIndexMap;
757 auto GetOrAddIndex = [&Value2Index, &NewVariables,
758 &NewIndexMap](
Value *
V) ->
unsigned {
759 auto V2I = Value2Index.find(V);
760 if (V2I != Value2Index.end())
763 V, Value2Index.size() + NewVariables.size() + 1);
765 NewVariables.push_back(V);
771 GetOrAddIndex(KV.Variable);
777 IsSigned, IsEq, IsNe);
778 auto &
R = Res.Coefficients;
779 for (
const auto &KV : VariablesA)
780 R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
782 for (
const auto &KV : VariablesB) {
783 auto &Coeff =
R[GetOrAddIndex(KV.Variable)];
792 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
798 while (!NewVariables.empty()) {
799 int64_t
Last =
R.back();
803 Value *RemovedV = NewVariables.pop_back_val();
804 NewIndexMap.
erase(RemovedV);
818 auto &Value2Index = getValue2Index(
false);
833 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
834 if (!NewVariables.
empty())
840ConstraintTy::isImpliedBy(
const ConstraintSystem &
CS)
const {
841 const auto &[SubCS, NewCoefficients] =
CS.getSubSystem(Coefficients);
842 bool IsConditionImplied = SubCS.isConditionImplied(NewCoefficients);
846 bool IsNegatedOrEqualImplied =
847 !NegatedOrEqual.empty() && SubCS.isConditionImplied(NegatedOrEqual);
852 if (IsConditionImplied && IsNegatedOrEqualImplied)
856 bool IsNegatedImplied =
857 !Negated.empty() && SubCS.isConditionImplied(Negated);
860 bool IsStrictLessThanImplied =
861 !StrictLessThan.empty() && SubCS.isConditionImplied(StrictLessThan);
867 if (IsNegatedImplied || IsStrictLessThanImplied)
873 if (IsConditionImplied)
877 auto IsNegatedImplied = !Negated.empty() && SubCS.isConditionImplied(Negated);
878 if (IsNegatedImplied)
887 auto R = getConstraintForSolving(Pred,
A,
B);
889 getCS(
R.IsSigned).isConditionImpliedInSubSystem(
R.Coefficients);
892void ConstraintInfo::transferToOtherSystem(
894 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
895 auto IsKnownNonNegative = [
this](
Value *
V) {
901 if (!
A->getType()->isIntegerTy())
912 if (IsKnownNonNegative(
B)) {
922 if (IsKnownNonNegative(
A)) {
931 if (IsKnownNonNegative(
A))
939 if (IsKnownNonNegative(
B))
945 if (IsKnownNonNegative(
B))
956 CS.addVariableRowFill(
C);
961void State::addInfoForInductions(BasicBlock &BB) {
968 if (Header != &BB && Latch != &BB)
975 PHINode *PN =
nullptr;
976 const APInt *IncStep =
nullptr;
994 if (&BB == Latch && !IncStep)
1005 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB) || InLoopSucc == &BB)
1009 if (!LoopPred || !
L->isLoopInvariant(
B))
1017 const APInt *StepOffset =
nullptr;
1018 const SCEV *StartSCEV =
nullptr;
1019 OverflowingBinaryOperator *Inc =
nullptr;
1021 if (StepOffset->
isZero())
1025 const SCEV *Expr = SE.
getSCEV(PN);
1036 if (IncStep && (*IncStep != *StepOffset || StepOffset->
isNegative()))
1042 if (!(-*StepOffset).isOne())
1048 WorkList.
push_back(FactOrCheck::getConditionFact(
1051 WorkList.
push_back(FactOrCheck::getConditionFact(
1056 WorkList.
push_back(FactOrCheck::getConditionFact(
1059 WorkList.
push_back(FactOrCheck::getConditionFact(
1069 if (!(MonotonicallyIncreasingUnsigned && MonotonicallyIncreasingSigned)) {
1071 if (!MonotonicallyIncreasingUnsigned)
1072 MonotonicallyIncreasingUnsigned =
1075 if (!MonotonicallyIncreasingSigned)
1076 MonotonicallyIncreasingSigned =
1083 if (MonotonicallyIncreasingUnsigned)
1086 if (MonotonicallyIncreasingSigned)
1096 if (!StepOffset->
isOne()) {
1099 StartSCEV = SE.
getSCEV(StartValue);
1106 Value *LowerBound = StartValue;
1107 bool LowerBoundNUW =
true, LowerBoundNSW =
true;
1112 bool UOverflow =
false, SOverflow =
false;
1113 APInt Sum = StartC->getValue().uadd_ov(*StepOffset, UOverflow);
1114 (void)StartC->getValue().sadd_ov(*StepOffset, SOverflow);
1115 LowerBound = ConstantInt::get(StartValue->
getType(), Sum);
1116 LowerBoundNUW = !UOverflow;
1117 LowerBoundNSW = !SOverflow;
1125 if (!MonotonicallyIncreasingUnsigned && LowerBoundNUW)
1126 WorkList.
push_back(FactOrCheck::getConditionFact(
1128 if (!MonotonicallyIncreasingSigned && LowerBoundNSW)
1129 WorkList.
push_back(FactOrCheck::getConditionFact(
1134 B, StartBeforeBoundSLE));
1140 B, StartBeforeBoundULE));
1147 "unsupported predicate");
1149 L->getExitBlocks(ExitBBs);
1150 for (BasicBlock *EB : ExitBBs) {
1165 if (!
Offset.NW.hasNoUnsignedWrap())
1168 if (
Offset.VariableOffsets.size() != 1)
1172 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1174 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1183 std::optional<TypeSize>
Size =
1198 B = ConstantInt::get(Index->getType(), MaxIndex);
1202void State::addInfoFor(BasicBlock &BB) {
1203 addInfoForInductions(BB);
1209 bool GuaranteedToExecute =
true;
1211 for (Instruction &
I : BB) {
1213 for (Use &U :
I.uses()) {
1215 auto *DTN = DT.
getNode(UserI->getParent());
1218 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1223 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1227 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1230 if (GuaranteedToExecute) {
1232 Pred,
A,
B,
DL, TLI)) {
1240 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1245 if (!LI->isVolatile())
1246 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1249 if (!
SI->isVolatile())
1250 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1256 case Intrinsic::assume: {
1259 if (GuaranteedToExecute) {
1266 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1271 case Intrinsic::ssub_with_overflow:
1272 case Intrinsic::ucmp:
1273 case Intrinsic::scmp:
1278 case Intrinsic::umin:
1279 case Intrinsic::umax:
1280 case Intrinsic::smin:
1281 case Intrinsic::smax:
1286 case Intrinsic::uadd_sat:
1287 case Intrinsic::usub_sat:
1293 case Intrinsic::abs:
1306 if ((BO->getOpcode() == Instruction::URem ||
1307 BO->getOpcode() == Instruction::UDiv ||
1308 BO->getOpcode() == Instruction::LShr ||
1309 BO->getOpcode() == Instruction::SRem) &&
1318 for (
auto &Case :
Switch->cases()) {
1320 Value *
V = Case.getCaseValue();
1321 if (!canAddSuccessor(BB, Succ))
1350 SmallPtrSet<Value *, 8> SeenCond;
1351 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1352 if (SeenCond.
insert(V).second)
1357 while (!CondWorkList.
empty()) {
1382 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1384 DT.
getNode(Br->getSuccessor(0)), Pred,
A,
B));
1385 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1393 OS <<
"icmp " << Pred <<
' ';
1394 LHS->printAsOperand(OS,
true);
1396 RHS->printAsOperand(OS,
false);
1405struct ReproducerEntry {
1406 ICmpInst::Predicate Pred;
1441 auto &Value2Index = Info.getValue2Index(IsSigned);
1443 while (!WorkList.
empty()) {
1445 if (!Seen.
insert(V).second)
1447 if (Old2New.
find(V) != Old2New.
end())
1453 if (Value2Index.contains(V) || !
I ||
1464 for (
auto &Entry : Stack)
1467 CollectArguments(
Cond, IsSigned);
1470 for (
auto *
P : Args)
1476 Cond->getModule()->getName() +
1477 Cond->getFunction()->getName() +
"repro",
1480 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1482 Old2New[Args[
I]] =
F->getArg(
I);
1487 Builder.CreateRet(Builder.getTrue());
1488 Builder.SetInsertPoint(Entry->getTerminator());
1497 auto &Value2Index = Info.getValue2Index(IsSigned);
1498 while (!WorkList.
empty()) {
1500 if (Old2New.
find(V) != Old2New.
end())
1504 if (!Value2Index.contains(V) &&
I) {
1505 Old2New[V] =
nullptr;
1515 Old2New[
I] = Cloned;
1516 Old2New[
I]->setName(
I->getName());
1528 for (
auto &Entry : Stack) {
1537 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1538 Builder.CreateAssumption(Cmp);
1543 CloneInstructions(
Cond, IsSigned);
1544 Entry->getTerminator()->setOperand(0,
Cond);
1552 ConstraintInfo &Info) {
1555 auto TryWithConstraint = [&](
const ConstraintTy &R) -> std::optional<bool> {
1558 return std::nullopt;
1561 auto &CSToUse = Info.getCS(R.IsSigned);
1562 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1564 return std::nullopt;
1566 dbgs() <<
"Condition ";
1568 *ImpliedCondition ? Pred
1571 dbgs() <<
" implied by dominating constraints\n";
1574 return ImpliedCondition;
1576 return std::nullopt;
1579 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1580 if (
auto ImpliedCondition = TryWithConstraint(R))
1581 return ImpliedCondition;
1586 const auto &Value2Index = Info.getValue2Index(
true);
1587 if (!Value2Index.contains(
A) && !Value2Index.contains(
B))
1588 return std::nullopt;
1591 auto SR = Info.getConstraint(Pred,
A,
B, NewVariables,
1593 if (NewVariables.
empty())
1594 if (
auto ImpliedCondition = TryWithConstraint(SR))
1595 return ImpliedCondition;
1597 return std::nullopt;
1602 ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1606 auto ReplaceCmpWithConstant = [&](
Instruction *CheckInst,
bool IsTrue) {
1608 ReproducerCondStack, Info, DT);
1613 auto *DTN = DT.
getNode(UserI->getParent());
1616 if (UserI->getParent() == ContextInst->
getParent() &&
1617 UserI->comesBefore(ContextInst))
1623 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1632 for (
auto *DVR : DVRUsers) {
1633 auto *DTN = DT.
getNode(DVR->getParent());
1637 auto *MarkedI = DVR->getInstruction();
1638 if (MarkedI->getParent() == ContextInst->
getParent() &&
1639 MarkedI->comesBefore(ContextInst))
1642 DVR->replaceVariableLocationOp(CheckInst, ConstantC);
1652 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1659 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1668 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1677 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1680 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1689 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1699 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1708 Module *ReproducerModule,
1711 Info.popLastConstraint(
E.IsSigned);
1713 auto &Mapping = Info.getValue2Index(
E.IsSigned);
1714 for (
Value *V :
E.ValuesToRelease)
1716 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
1718 if (ReproducerModule)
1725 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
1734 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
1742 unsigned OldSize = DFSInStack.
size();
1745 while (OldSize < DFSInStack.
size()) {
1746 StackEntry
E = DFSInStack.
back();
1754 while (!Worklist.empty()) {
1755 Value *Val = Worklist.pop_back_val();
1763 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
1768 Worklist.push_back(
LHS);
1769 Worklist.push_back(
RHS);
1772 if (OldSize == DFSInStack.
size())
1777 [[maybe_unused]]
bool Matched =
1779 assert(Matched &&
"expected icmp-like match");
1781 if (
auto ImpliedCondition =
checkCondition(Pred,
A,
B, CmpToCheck, Info)) {
1782 if (IsOr == *ImpliedCondition)
1795 unsigned NumIn,
unsigned NumOut,
1796 SmallVectorImpl<StackEntry> &DFSInStack) {
1797 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
1800 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
1802 tightenBoundUsingNe(
A,
B, NumIn, NumOut, DFSInStack);
1805void ConstraintInfo::tightenBoundUsingNe(
1807 SmallVectorImpl<StackEntry> &DFSInStack) {
1808 if (!
A->getType()->isIntegerTy())
1811 for (
bool IsSigned : {
false,
true}) {
1818 const auto &Value2Index = getValue2Index(IsSigned);
1820 [&Value2Index](
const DecompEntry &
E) {
1821 return !Value2Index.contains(
E.Variable);
1832 if (!doesHold(NonStrict,
A,
B))
1838 dbgs() <<
"' using inequality\n");
1839 addFactImpl(
Strict,
A,
B, NumIn, NumOut, DFSInStack,
1847 unsigned NumIn,
unsigned NumOut,
1848 SmallVectorImpl<StackEntry> &DFSInStack,
1849 bool ForceSignedSystem) {
1851 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
1854 if (
R.empty() ||
R.isNe())
1859 auto &CSToUse = getCS(
R.IsSigned);
1860 if (
R.Coefficients.empty())
1863 bool Added = CSToUse.addVariableRowFill(
R.Coefficients);
1869 SmallVector<Value *, 2> ValuesToRelease;
1870 auto &Value2Index = getValue2Index(
R.IsSigned);
1871 for (
Value *V : NewVariables) {
1872 Value2Index.try_emplace(V, Value2Index.size() + 1);
1877 dbgs() <<
" constraint: ";
1883 std::move(ValuesToRelease));
1886 for (
Value *V : NewVariables) {
1888 false,
false,
false);
1889 VarPos.Coefficients[Value2Index[
V]] = -1;
1890 CSToUse.addVariableRow(VarPos.Coefficients);
1892 SmallVector<Value *, 2>());
1898 for (
auto &Coeff :
R.Coefficients)
1901 CSToUse.addVariableRowFill(
R.Coefficients);
1904 SmallVector<Value *, 2>());
1916 Sub = Builder.CreateNSWSub(
A,
B);
1917 U->replaceAllUsesWith(
Sub);
1920 U->replaceAllUsesWith(Builder.getFalse());
1925 if (U->use_empty()) {
1933 if (
II->use_empty()) {
1934 II->eraseFromParent();
1944 ConstraintInfo &Info) {
1945 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1949 auto &CSToUse = Info.getCS(R.IsSigned);
1950 return CSToUse.isConditionImpliedInSubSystem(R.Coefficients);
1954 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1961 ConstantInt::get(
A->getType(), 0), Info))
1975 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
1976 State S(DT, LI, SE, TLI);
1977 std::unique_ptr<Module> ReproducerModule(
1996 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
1997 auto HasNoConstOp = [](const FactOrCheck &B) {
1998 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
1999 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
2000 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
2004 if (
A.NumIn ==
B.NumIn) {
2005 if (A.isConditionFact() && B.isConditionFact()) {
2006 bool NoConstOpA = HasNoConstOp(A);
2007 bool NoConstOpB = HasNoConstOp(B);
2008 return NoConstOpA < NoConstOpB;
2010 if (
A.isConditionFact())
2012 if (
B.isConditionFact())
2014 auto *InstA =
A.getContextInst();
2015 auto *InstB =
B.getContextInst();
2016 return InstA->comesBefore(InstB);
2018 return A.NumIn <
B.NumIn;
2021 SmallVector<Instruction *>
ToRemove;
2026 for (FactOrCheck &CB : S.WorkList) {
2029 while (!DFSInStack.
empty()) {
2030 auto &
E = DFSInStack.
back();
2033 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
2035 if (CB.NumOut <=
E.NumOut)
2038 dbgs() <<
"Removing ";
2040 Info.getValue2Index(
E.IsSigned));
2052 Instruction *Inst = CB.getInstructionToSimplify();
2055 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
2061 Pred,
A,
B, Inst, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
2062 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
2066 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
2078 auto AddFact = [&](CmpPredicate Pred,
Value *
A,
Value *
B) {
2084 <<
"Skip adding constraint because system has too many rows.\n");
2088 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
2089 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
2098 CB.NumIn, CB.NumOut, DFSInStack);
2100 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
2114 SmallPtrSet<Value *, 4> Seen;
2115 while (!Worklist.
empty()) {
2118 if (!BO || BO->getOpcode() !=
Opc)
2120 for (
Value *
Op : {BO->getOperand(0), BO->getOperand(1)}) {
2124 Info.addFact(Pred,
Op,
B, CB.NumIn, CB.NumOut, DFSInStack);
2129 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
2132 for (
unsigned I = 0,
2133 E = (DFSInStack.
size() - ReproducerCondStack.
size());
2135 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
2141 if (!CB.isConditionFact()) {
2147 ConstantInt::get(CB.Inst->getType(), 0));
2153 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
2154 AddFact(Pred, MinMax, MinMax->getLHS());
2155 AddFact(Pred, MinMax, MinMax->getRHS());
2159 switch (USatI->getIntrinsicID()) {
2162 case Intrinsic::uadd_sat:
2163 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2164 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2166 case Intrinsic::usub_sat:
2167 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2174 if (BO->getOpcode() == Instruction::URem) {
2181 if (BO->getOpcode() == Instruction::UDiv) {
2186 if (BO->getOpcode() == Instruction::LShr) {
2191 if (BO->getOpcode() == Instruction::SRem) {
2192 Value *
X = BO->getOperand(0);
2193 Value *
N = BO->getOperand(1);
2213 auto &
DL =
F.getDataLayout();
2214 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2219 DL.getTypeStoreSize(AccessType).getFixedValue(), Pred,
A,
B,
DL,
2221 AddFact(Pred,
A,
B);
2225 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2229 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2234 if (CB.isConditionFact()) {
2235 Pred = CB.Cond.Pred;
2239 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2241 dbgs() <<
"Not adding fact ";
2243 dbgs() <<
" because precondition ";
2246 dbgs() <<
" does not hold.\n";
2251 [[maybe_unused]]
bool Matched =
2255 "Must have an assume intrinsic with a icmp like operand");
2257 AddFact(Pred,
A,
B);
2260 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2262 raw_string_ostream StringS(S);
2263 ReproducerModule->print(StringS,
nullptr);
2264 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2265 Rem <<
ore::NV(
"module") << S;
2270 unsigned SignedEntries =
2271 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2272 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2273 DFSInStack.
size() - SignedEntries &&
2274 "updates to CS and DFSInStack are out of sync");
2275 assert(
Info.getCS(
true).size() == SignedEntries &&
2276 "updates to CS and DFSInStack are out of sync");
2280 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)
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.
@ 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.