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();
90 : Pred(Pred), Op0(Op0), Op1(Op1) {}
122 FactOrCheck(EntryTy Ty,
DomTreeNode *DTN, Instruction *Inst)
123 : Inst(Inst), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
127 :
U(
U), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
128 Ty(EntryTy::UseCheck) {}
132 :
Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
133 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
135 static FactOrCheck getConditionFact(
DomTreeNode *DTN, CmpPredicate Pred,
138 return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
141 static FactOrCheck getInstFact(
DomTreeNode *DTN, Instruction *Inst) {
142 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
145 static FactOrCheck getCheck(
DomTreeNode *DTN, Use *U) {
146 return FactOrCheck(DTN, U);
149 static FactOrCheck getCheck(
DomTreeNode *DTN, Instruction *
I) {
150 return FactOrCheck(EntryTy::InstCheck, DTN,
I);
153 bool isCheck()
const {
154 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
158 assert(!isConditionFact());
159 if (Ty == EntryTy::UseCheck)
166 if (Ty == EntryTy::InstCheck)
172 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
177struct MonotonicInfo {
179 bool Decreasing =
false;
181 bool Unsigned =
false;
191 TargetLibraryInfo &TLI;
194 State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE,
195 TargetLibraryInfo &TLI)
196 : DT(DT), LI(LI), SE(SE), TLI(TLI) {}
199 void addInfoFor(BasicBlock &BB);
203 void addBoundsForHeaderInductions(BasicBlock &BB);
207 void addInfoForInductions(BasicBlock &BB);
211 MonotonicInfo getMonotonicityInfo(PHINode &PN,
Value *Step);
215 bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ)
const {
216 return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
225 bool IsSigned =
false;
228 SmallVector<Value *, 2> ValuesToRelease;
230 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
231 SmallVector<Value *, 2> ValuesToRelease)
232 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
233 ValuesToRelease(std::
move(ValuesToRelease)) {}
240 unsigned NumVars = 0;
242 bool IsSigned =
false;
244 ConstraintTy() =
default;
246 ConstraintTy(RowTy Coefficients,
unsigned NumVars,
bool IsSigned,
bool IsEq,
248 : Coefficients(std::
move(Coefficients)), NumVars(NumVars),
249 IsSigned(IsSigned), IsEq(IsEq), IsNe(IsNe) {}
251 bool empty()
const {
return Coefficients.empty(); }
255 bool isConstantOnly()
const {
return Coefficients.size() < 2; }
257 bool isEq()
const {
return IsEq; }
259 bool isNe()
const {
return IsNe; }
266 std::optional<bool> isImpliedBy(
const ConstraintSystem &CS)
const;
279class ConstraintInfo {
281 ConstraintSystem UnsignedCS;
282 ConstraintSystem SignedCS;
284 const DataLayout &DL;
288 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
289 auto &Value2Index = getValue2Index(
false);
291 for (
Value *Arg : FunctionArgs)
292 UnsignedCS.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(Arg))},
296 DenseMap<Value *, unsigned> &getValue2Index(
bool Signed) {
297 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
299 const DenseMap<Value *, unsigned> &getValue2Index(
bool Signed)
const {
300 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
303 ConstraintSystem &getCS(
bool Signed) {
304 return Signed ? SignedCS : UnsignedCS;
306 const ConstraintSystem &getCS(
bool Signed)
const {
307 return Signed ? SignedCS : UnsignedCS;
310 void popLastConstraint(
bool Signed) { getCS(
Signed).popLastConstraint(); }
311 void popLastNVariables(
bool Signed,
unsigned N) {
312 getCS(
Signed).popLastNVariables(
N);
322 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
329 SmallVectorImpl<Value *> &NewVariables,
330 bool ForceSignedSystem =
false)
const;
345 unsigned NumIn,
unsigned NumOut,
346 SmallVectorImpl<StackEntry> &DFSInStack);
353 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
354 bool ForceSignedSystem);
358 void tightenBoundUsingNe(
Value *
A,
Value *
B,
unsigned NumIn,
unsigned NumOut,
359 SmallVectorImpl<StackEntry> &DFSInStack);
367 DecompEntry(int64_t Coefficient,
Value *Variable)
368 : Coefficient(Coefficient), Variable(Variable) {}
372struct Decomposition {
376 Decomposition(int64_t Offset) : Offset(Offset) {}
377 Decomposition(
Value *V) { Vars.emplace_back(1, V); }
379 : Offset(Offset), Vars(Vars) {}
383 [[nodiscard]]
bool add(int64_t OtherOffset) {
389 [[nodiscard]]
bool add(
const Decomposition &
Other) {
398 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
399 Decomposition Tmp =
Other;
410 [[nodiscard]]
bool mul(int64_t Factor) {
413 for (
auto &Var : Vars)
414 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
423 APInt ConstantOffset;
424 SmallMapVector<Value *, APInt, 4> VariableOffsets;
429 OffsetResult(GEPOperator &
GEP,
const DataLayout &
DL)
431 ConstantOffset = APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
441 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
443 Result.ConstantOffset))
451 bool CanCollectInner = InnerGEP->collectOffset(
452 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
454 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
455 VariableOffsets2.
size() > 1 ||
456 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
460 Result.BasePtr = InnerGEP->getPointerOperand();
461 Result.ConstantOffset += ConstantOffset2;
462 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
463 Result.VariableOffsets = std::move(VariableOffsets2);
464 Result.NW &= InnerGEP->getNoWrapFlags();
469static Decomposition
decompose(
Value *V,
const ConstraintInfo &Info,
481 return Info.doesHold(Pred,
Op, ConstantInt::get(
Op->getType(),
RHS));
488 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
491 assert(!IsSigned &&
"The logic below only supports decomposition for "
492 "unsigned predicates at the moment.");
493 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
502 if (!NW.hasNoUnsignedSignedWrap() && ConstantOffset.isNegative())
505 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
506 for (
auto [Index, Scale] : VariableOffsets) {
507 if (!NW.hasNoUnsignedWrap()) {
510 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
516 auto IdxResult =
decompose(Index, Info, IsSigned,
DL);
517 if (IdxResult.mul(Scale.getSExtValue()))
519 if (Result.add(IdxResult))
533 auto MergeResults = [&Info, IsSigned,
535 bool IsSignedB) -> std::optional<Decomposition> {
544 if (Ty->isPointerTy() && !IsSigned) {
556 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
563 return CI->getSExtValue();
578 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
585 Decomposition Result(-1);
586 if (!Result.sub(
decompose(Op0, Info, IsSigned,
DL)))
611 if (Shift < Ty->getIntegerBitWidth() - 1) {
612 assert(Shift < 64 &&
"Would overflow");
614 if (!Result.mul(int64_t(1) << Shift))
626 return int64_t(CI->getZExtValue());
638 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64 &&
639 (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap())) {
640 Value *Src = Trunc->getOperand(0);
643 if (!Trunc->hasNoUnsignedWrap() &&
653 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
664 if (
auto Decomp = MergeResults(Op0, CI,
true))
678 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
721 bool ForceSignedSystem)
const {
722 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
724 "signed system can only be forced on eq/ne");
765 auto &Value2Index = getValue2Index(IsSigned);
770 int64_t Offset1 = ADec.Offset;
771 int64_t Offset2 = BDec.Offset;
775 auto &VariablesA = ADec.Vars;
776 auto &VariablesB = BDec.Vars;
780 auto GetOrAddIndex = [&Value2Index, &NewVariables](
Value *
V) ->
unsigned {
781 auto V2I = Value2Index.find(V);
782 if (V2I != Value2Index.end())
784 unsigned Idx =
find(NewVariables, V) - NewVariables.
begin();
785 if (Idx == NewVariables.
size())
787 return Value2Index.size() + Idx + 1;
793 auto GetCoefficient = [&
R](
unsigned Idx) -> int64_t & {
798 if (
I ==
R.end() ||
I->Id != Idx)
800 return I->Coefficient;
802 for (
const auto &KV : VariablesA)
803 GetCoefficient(GetOrAddIndex(KV.Variable)) += KV.Coefficient;
805 for (
const auto &KV : VariablesB) {
806 auto &Coeff = GetCoefficient(GetOrAddIndex(KV.Variable));
815 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
817 R[0].Coefficient = OffsetSum;
820 erase_if(R, [](
const Entry &
E) {
return E.Id != 0 &&
E.Coefficient == 0; });
823 unsigned NumV2I = Value2Index.size();
824 NewVariables.
truncate(
R.back().Id > NumV2I ?
R.back().Id - NumV2I : 0);
826 return ConstraintTy(std::move(R), Value2Index.size() + NewVariables.
size(),
827 IsSigned, IsEq, IsNe);
839 return ConstraintTy(RowTy(1,
Entry(0, 0)), 0,
840 false,
false,
false);
852 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
853 if (!NewVariables.
empty())
859ConstraintTy::isImpliedBy(
const ConstraintSystem &CS)
const {
860 const auto &[SubCS, NewCoefficients] = CS.
getSubSystem(Coefficients);
861 bool IsConditionImplied = SubCS.isConditionImplied(NewCoefficients);
865 bool IsNegatedOrEqualImplied =
866 !NegatedOrEqual.empty() && SubCS.isConditionImplied(NegatedOrEqual);
871 if (IsConditionImplied && IsNegatedOrEqualImplied)
875 bool IsNegatedImplied =
876 !Negated.empty() && SubCS.isConditionImplied(Negated);
879 bool IsStrictLessThanImplied =
880 !StrictLessThan.empty() && SubCS.isConditionImplied(StrictLessThan);
886 if (IsNegatedImplied || IsStrictLessThanImplied)
892 if (IsConditionImplied)
896 auto IsNegatedImplied = !Negated.empty() && SubCS.isConditionImplied(Negated);
897 if (IsNegatedImplied)
906 auto R = getConstraintForSolving(Pred,
A,
B);
908 getCS(
R.IsSigned).isConditionImpliedInSubSystem(
R.Coefficients);
911bool ConstraintInfo::isKnownNonNegative(
Value *V)
const {
916void ConstraintInfo::transferToOtherSystem(
918 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
921 if (!
A->getType()->isIntegerTy())
984static std::pair<Value *, Value *>
987 "LoopPred must be a predecessor of the phi's block");
989 return {
nullptr,
nullptr};
994MonotonicInfo State::getMonotonicityInfo(PHINode &PN,
Value *Step) {
996 const APInt *StepOffset =
nullptr;
1000 Info.Unsigned = !
Info.Decreasing &&
Add->hasNoUnsignedWrap();
1001 Info.Signed =
Add->hasNoSignedWrap();
1006 APInt GEPOffset(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
1007 Info.Unsigned =
GEP->getPointerOperand() == &PN &&
1008 (
GEP->hasNoUnsignedWrap() ||
1009 ((
GEP->hasNoUnsignedSignedWrap() &&
1010 GEP->accumulateConstantOffset(
DL, GEPOffset) &&
1011 !GEPOffset.isNegative())));
1016 if (
Info.Unsigned ||
Info.Signed || !StepOffset)
1033void State::addBoundsForHeaderInductions(BasicBlock &BB) {
1035 if (!L ||
L->getHeader() != &BB)
1042 for (PHINode &PN : BB.
phis()) {
1050 MonotonicInfo
Info = getMonotonicityInfo(PN, Step);
1054 Info.Unsigned =
false;
1055 if (!
Info.Unsigned && !
Info.Signed)
1061 if (
Info.Decreasing)
1065 WorkList.
push_back(FactOrCheck::getConditionFact(DTN, Pred,
LHS,
RHS));
1069void State::addInfoForInductions(BasicBlock &BB) {
1076 if (Header != &BB && Latch != &BB)
1083 PHINode *PN =
nullptr;
1084 const APInt *IncStep =
nullptr;
1094 std::optional<bool> PeeledOnEdge;
1095 if (!
match(Br->getCondition(), CountingCmp)) {
1099 PeeledOnEdge =
true;
1101 PeeledOnEdge =
false;
1116 if (&BB == Latch && !IncStep)
1119 bool ContinueOnTrue =
1123 BasicBlock *InLoopSucc = Br->getSuccessor(ContinueOnTrue ? 0 : 1);
1127 if (PeeledOnEdge && *PeeledOnEdge != ContinueOnTrue)
1130 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB))
1134 if (!LoopPred || !
L->isLoopInvariant(
B))
1147 WorkList.
push_back(FactOrCheck::getConditionFact(
1148 DTN, ContinuePred, PN,
B,
ConditionTy(ContinuePred, StartValue,
B)));
1155 const APInt *StepOffset =
nullptr;
1156 const SCEV *StartSCEV =
nullptr;
1158 if (StepOffset->
isZero())
1161 const SCEV *Expr = SE.
getSCEV(PN);
1170 if (IncStep && *IncStep != *StepOffset)
1173 MonotonicInfo
Info = getMonotonicityInfo(*PN, Backedge);
1178 if (!(-*StepOffset).isOne())
1188 ConditionTy BBeforeStartUnsigned = {UPrecond,
B, StartValue};
1194 WorkList.
push_back(FactOrCheck::getConditionFact(
1196 if (!(
Info.Decreasing &&
Info.Signed))
1197 WorkList.
push_back(FactOrCheck::getConditionFact(
1201 B, BBeforeStartUnsigned));
1203 B, BBeforeStartSigned));
1213 if (!StepOffset->
isOne()) {
1216 StartSCEV = SE.
getSCEV(StartValue);
1230 ConditionTy StartBeforeBoundUnsigned = {UPrecond, StartValue,
B};
1236 WorkList.
push_back(FactOrCheck::getConditionFact(
1239 WorkList.
push_back(FactOrCheck::getConditionFact(
1243 B, StartBeforeBoundSigned));
1244 WorkList.
push_back(FactOrCheck::getConditionFact(
1253 L->getExitBlocks(ExitBBs);
1254 for (BasicBlock *EB : ExitBBs) {
1269 if (!
Offset.NW.hasNoUnsignedWrap())
1272 if (
Offset.VariableOffsets.size() != 1)
1276 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1278 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1287 std::optional<TypeSize>
Size =
1302 B = ConstantInt::get(Index->getType(), MaxIndex);
1310 if (!BO || !BO->getType()->isIntegerTy())
1313 switch (BO->getOpcode()) {
1314 case Instruction::Sub:
1317 return !BO->hasNoUnsignedWrap() && !
isa<Constant>(BO->getOperand(1));
1318 case Instruction::Add:
1320 return (!BO->hasNoUnsignedWrap() || !BO->hasNoSignedWrap()) &&
1322 case Instruction::Mul:
1323 case Instruction::Shl:
1324 if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
1339 if (R.isEmptySet() || (
Signed ? R.isSignWrappedSet() : R.isWrappedSet()))
1345 unsigned BitWidth = R.getBitWidth();
1346 APInt Min =
Signed ? R.getSignedMin() : R.getUnsignedMin();
1347 APInt Max =
Signed ? R.getSignedMax() : R.getUnsignedMax();
1352 Type *Ty =
Op->getType();
1353 if (Min != MinVal &&
1355 ConstantInt::get(Ty, Min)))
1357 if (Max != MaxVal &&
1359 ConstantInt::get(Ty, Max)))
1365 ConstraintInfo &Info) {
1376 if (!
I->hasNoUnsignedWrap() &&
1379 Opcode,
Other, OBO::NoUnsignedWrap),
1382 I->setHasNoUnsignedWrap();
1385 if (!
I->hasNoSignedWrap() &&
1388 Opcode,
Other, OBO::NoSignedWrap),
1391 I->setHasNoSignedWrap();
1403 Value *Op0 =
I->getOperand(0), *Op1 =
I->getOperand(1);
1404 switch (
I->getOpcode()) {
1405 case Instruction::Sub: {
1410 I->setHasNoUnsignedWrap();
1413 case Instruction::Add:
1415 case Instruction::Mul:
1416 case Instruction::Shl: {
1419 if (!
I->hasNoUnsignedWrap() &&
I->hasNoSignedWrap() &&
1420 Info.isKnownNonNegative(Op0) &&
1421 (Opcode == Instruction::Shl || Info.isKnownNonNegative(Op1))) {
1423 I->setHasNoUnsignedWrap();
1433void State::addInfoFor(BasicBlock &BB) {
1434 addBoundsForHeaderInductions(BB);
1435 addInfoForInductions(BB);
1441 bool GuaranteedToExecute =
true;
1443 for (Instruction &
I : BB) {
1445 for (Use &U :
I.uses()) {
1447 auto *DTN = DT.
getNode(UserI->getParent());
1450 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1455 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1459 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1462 if (GuaranteedToExecute) {
1464 Pred,
A,
B,
DL, TLI)) {
1472 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1477 if (!LI->isVolatile())
1478 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1481 if (!
SI->isVolatile())
1482 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1488 case Intrinsic::assume: {
1491 if (GuaranteedToExecute) {
1498 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1503 case Intrinsic::ssub_with_overflow:
1504 case Intrinsic::ucmp:
1505 case Intrinsic::scmp:
1510 case Intrinsic::umin:
1511 case Intrinsic::umax:
1512 case Intrinsic::smin:
1513 case Intrinsic::smax:
1514 case Intrinsic::usub_sat:
1519 case Intrinsic::uadd_sat:
1525 case Intrinsic::abs:
1538 if ((BO->getOpcode() == Instruction::URem ||
1539 BO->getOpcode() == Instruction::UDiv ||
1540 BO->getOpcode() == Instruction::LShr ||
1541 BO->getOpcode() == Instruction::SRem) &&
1555 for (
auto &Case :
Switch->cases()) {
1557 Value *
V = Case.getCaseValue();
1558 if (!canAddSuccessor(BB, Succ))
1587 SmallPtrSet<Value *, 8> SeenCond;
1588 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1589 if (SeenCond.
insert(V).second)
1594 while (!CondWorkList.
empty()) {
1619 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1621 DT.
getNode(Br->getSuccessor(0)), Pred,
A,
B));
1622 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1630 OS <<
"icmp " << Pred <<
' ';
1631 LHS->printAsOperand(OS,
true);
1633 RHS->printAsOperand(OS,
false);
1642struct ReproducerEntry {
1643 ICmpInst::Predicate Pred;
1678 auto &Value2Index = Info.getValue2Index(IsSigned);
1680 while (!WorkList.
empty()) {
1682 if (!Seen.
insert(V).second)
1684 if (Old2New.
find(V) != Old2New.
end())
1690 if (Value2Index.contains(V) || !
I ||
1701 for (
auto &Entry : Stack)
1704 CollectArguments(
Cond, IsSigned);
1707 for (
auto *
P : Args)
1713 Cond->getModule()->getName() +
1714 Cond->getFunction()->getName() +
"repro",
1717 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1719 Old2New[Args[
I]] =
F->getArg(
I);
1724 Builder.CreateRet(Builder.getTrue());
1725 Builder.SetInsertPoint(Entry->getTerminator());
1734 auto &Value2Index = Info.getValue2Index(IsSigned);
1735 while (!WorkList.
empty()) {
1737 if (Old2New.
find(V) != Old2New.
end())
1741 if (!Value2Index.contains(V) &&
I) {
1742 Old2New[V] =
nullptr;
1752 Old2New[
I] = Cloned;
1753 Old2New[
I]->setName(
I->getName());
1765 for (
auto &Entry : Stack) {
1774 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1775 Builder.CreateAssumption(Cmp);
1780 CloneInstructions(
Cond, IsSigned);
1781 Entry->getTerminator()->setOperand(0,
Cond);
1789 ConstraintInfo &Info) {
1792 auto TryWithConstraint = [&](
const ConstraintTy &R) -> std::optional<bool> {
1795 return std::nullopt;
1798 auto &CSToUse = Info.getCS(R.IsSigned);
1799 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1801 return std::nullopt;
1803 dbgs() <<
"Condition ";
1805 *ImpliedCondition ? Pred
1808 dbgs() <<
" implied by dominating constraints\n";
1811 return ImpliedCondition;
1813 return std::nullopt;
1816 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1817 if (
auto ImpliedCondition = TryWithConstraint(R))
1818 return ImpliedCondition;
1826 if (NewVariables.
empty() && !SR.empty() && Info.isKnownNonNegative(
A) &&
1827 Info.isKnownNonNegative(
B))
1828 if (
auto ImpliedCondition = TryWithConstraint(SR))
1829 return ImpliedCondition;
1835 const auto &Value2Index = Info.getValue2Index(
true);
1836 if (!Value2Index.contains(
A) && !Value2Index.contains(
B))
1837 return std::nullopt;
1840 auto SR = Info.getConstraint(Pred,
A,
B, NewVariables,
1842 if (NewVariables.
empty())
1843 if (
auto ImpliedCondition = TryWithConstraint(SR))
1844 return ImpliedCondition;
1846 return std::nullopt;
1851 ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1855 auto ReplaceCmpWithConstant = [&](
Instruction *CheckInst,
bool IsTrue) {
1857 ReproducerCondStack, Info, DT);
1862 auto *DTN = DT.
getNode(UserI->getParent());
1865 if (UserI->getParent() == ContextInst->
getParent() &&
1866 UserI->comesBefore(ContextInst))
1872 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1881 for (
auto *DVR : DVRUsers) {
1882 auto *DTN = DT.
getNode(DVR->getParent());
1886 auto *MarkedI = DVR->getInstruction();
1887 if (MarkedI->getParent() == ContextInst->
getParent() &&
1888 MarkedI->comesBefore(ContextInst))
1891 DVR->replaceVariableLocationOp(CheckInst, ConstantC);
1901 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1908 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1917 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1926 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1929 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1938 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1948 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1966 Value *
Sub = Builder.CreateSub(
A,
B,
"",
true,
1967 Info.isKnownNonNegative(
A));
1969 Sub->takeName(USub);
1976 Module *ReproducerModule,
1979 Info.popLastConstraint(
E.IsSigned);
1981 auto &Mapping = Info.getValue2Index(
E.IsSigned);
1982 for (
Value *V :
E.ValuesToRelease)
1984 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
1986 if (ReproducerModule)
1993 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
2002 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
2010 unsigned OldSize = DFSInStack.
size();
2013 while (OldSize < DFSInStack.
size()) {
2014 StackEntry
E = DFSInStack.
back();
2022 while (!Worklist.empty()) {
2023 Value *Val = Worklist.pop_back_val();
2031 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
2036 Worklist.push_back(
LHS);
2037 Worklist.push_back(
RHS);
2040 if (OldSize == DFSInStack.
size())
2045 [[maybe_unused]]
bool Matched =
2047 assert(Matched &&
"expected icmp-like match");
2049 if (
auto ImpliedCondition =
checkCondition(Pred,
A,
B, CmpToCheck, Info)) {
2050 if (IsOr == *ImpliedCondition)
2063 unsigned NumIn,
unsigned NumOut,
2064 SmallVectorImpl<StackEntry> &DFSInStack) {
2065 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
2068 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
2070 tightenBoundUsingNe(
A,
B, NumIn, NumOut, DFSInStack);
2073void ConstraintInfo::tightenBoundUsingNe(
2075 SmallVectorImpl<StackEntry> &DFSInStack) {
2076 if (!
A->getType()->isIntegerTy())
2079 for (
bool IsSigned : {
false,
true}) {
2086 const auto &Value2Index = getValue2Index(IsSigned);
2088 [&Value2Index](
const DecompEntry &
E) {
2089 return !Value2Index.contains(
E.Variable);
2100 if (!doesHold(NonStrict,
A,
B))
2106 dbgs() <<
"' using inequality\n");
2107 addFactImpl(
Strict,
A,
B, NumIn, NumOut, DFSInStack,
2115 unsigned NumIn,
unsigned NumOut,
2116 SmallVectorImpl<StackEntry> &DFSInStack,
2117 bool ForceSignedSystem) {
2119 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
2122 if (
R.empty() ||
R.isNe())
2127 auto &CSToUse = getCS(
R.IsSigned);
2128 bool Added = CSToUse.addRow(
R.Coefficients,
R.NumVars);
2134 SmallVector<Value *, 2> ValuesToRelease;
2135 auto &Value2Index = getValue2Index(
R.IsSigned);
2136 for (
Value *V : NewVariables) {
2137 Value2Index.try_emplace(V, Value2Index.size() + 1);
2142 dbgs() <<
" constraint: ";
2148 std::move(ValuesToRelease));
2151 for (
Value *V : NewVariables) {
2153 CSToUse.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(V))},
2154 Value2Index.size());
2156 SmallVector<Value *, 2>());
2162 for (Entry &
E :
R.Coefficients)
2165 CSToUse.addRow(
R.Coefficients,
R.NumVars);
2168 SmallVector<Value *, 2>());
2180 Sub = Builder.CreateNSWSub(
A,
B);
2181 U->replaceAllUsesWith(
Sub);
2184 U->replaceAllUsesWith(Builder.getFalse());
2189 if (U->use_empty()) {
2197 if (
II->use_empty()) {
2199 for (
Use &Arg :
II->args())
2211 ConstraintInfo &Info) {
2212 auto R = Info.getConstraintForSolving(Pred,
A,
B);
2215 if (R.isConstantOnly())
2218 auto &CSToUse = Info.getCS(R.IsSigned);
2219 return CSToUse.isConditionImpliedInSubSystem(R.Coefficients);
2223 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
2230 ConstantInt::get(
A->getType(), 0), Info))
2244 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
2245 State S(DT, LI, SE, TLI);
2246 std::unique_ptr<Module> ReproducerModule(
2265 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
2266 auto HasNoConstOp = [](const FactOrCheck &B) {
2267 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
2268 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
2269 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
2273 if (
A.NumIn ==
B.NumIn) {
2274 if (A.isConditionFact() && B.isConditionFact()) {
2275 bool NoConstOpA = HasNoConstOp(A);
2276 bool NoConstOpB = HasNoConstOp(B);
2277 return NoConstOpA < NoConstOpB;
2279 if (
A.isConditionFact())
2281 if (
B.isConditionFact())
2283 auto *InstA =
A.getContextInst();
2284 auto *InstB =
B.getContextInst();
2285 return InstA->comesBefore(InstB);
2287 return A.NumIn <
B.NumIn;
2290 SmallVector<Instruction *>
ToRemove;
2295 for (FactOrCheck &CB : S.WorkList) {
2298 while (!DFSInStack.
empty()) {
2299 auto &
E = DFSInStack.
back();
2302 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
2304 if (CB.NumOut <=
E.NumOut)
2307 dbgs() <<
"Removing ";
2309 Info.getValue2Index(
E.IsSigned));
2321 Instruction *Inst = CB.getInstructionToSimplify();
2328 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
2334 Pred,
A,
B, Inst, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
2335 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
2339 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
2354 auto AddFact = [&](CmpPredicate Pred,
Value *
A,
Value *
B) {
2360 <<
"Skip adding constraint because system has too many rows.\n");
2364 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
2365 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
2374 CB.NumIn, CB.NumOut, DFSInStack);
2376 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
2390 SmallPtrSet<Value *, 4> Seen;
2391 while (!Worklist.
empty()) {
2394 if (!BO || BO->getOpcode() !=
Opc)
2396 for (
Value *
Op : {BO->getOperand(0), BO->getOperand(1)}) {
2400 Info.addFact(Pred,
Op,
B, CB.NumIn, CB.NumOut, DFSInStack);
2405 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
2408 for (
unsigned I = 0,
2409 E = (DFSInStack.
size() - ReproducerCondStack.
size());
2411 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
2417 if (!CB.isConditionFact()) {
2423 ConstantInt::get(CB.Inst->getType(), 0));
2429 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
2430 AddFact(Pred, MinMax, MinMax->getLHS());
2431 AddFact(Pred, MinMax, MinMax->getRHS());
2435 switch (USatI->getIntrinsicID()) {
2438 case Intrinsic::uadd_sat:
2439 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2440 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2442 case Intrinsic::usub_sat:
2443 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2450 if (BO->getOpcode() == Instruction::URem) {
2457 if (BO->getOpcode() == Instruction::UDiv) {
2462 if (BO->getOpcode() == Instruction::LShr) {
2467 if (BO->getOpcode() == Instruction::SRem) {
2468 Value *
X = BO->getOperand(0);
2469 Value *
N = BO->getOperand(1);
2489 auto &
DL =
F.getDataLayout();
2490 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2495 DL.getTypeStoreSize(AccessType).getFixedValue(), Pred,
A,
B,
DL,
2497 AddFact(Pred,
A,
B);
2501 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2505 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2510 if (CB.isConditionFact()) {
2511 Pred = CB.Cond.Pred;
2515 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2517 dbgs() <<
"Not adding fact ";
2519 dbgs() <<
" because precondition ";
2522 dbgs() <<
" does not hold.\n";
2527 [[maybe_unused]]
bool Matched =
2531 "Must have an assume intrinsic with a icmp like operand");
2533 AddFact(Pred,
A,
B);
2536 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2538 raw_string_ostream StringS(S);
2539 ReproducerModule->print(StringS,
nullptr);
2540 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2541 Rem <<
ore::NV(
"module") << S;
2546 unsigned SignedEntries =
2547 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2548 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2549 DFSInStack.
size() - SignedEntries &&
2550 "updates to CS and DFSInStack are out of sync");
2551 assert(
Info.getCS(
true).size() == SignedEntries &&
2552 "updates to CS and DFSInStack are out of sync");
2556 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 bool canStrengthenFlags(Instruction *I)
Returns true if I is a candidate whose poison-generating flags may be strengthened using the constrai...
static int64_t MinSignedConstraintValue
static Instruction * getContextInstForUse(Use &U)
static bool doesHoldInRange(const ConstraintInfo &Info, Value *Op, const ConstantRange &R, bool Signed)
Returns true if Info implies that Op is in R, interpreting R as a signed range if Signed is set and a...
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 bool tryToStrengthenBinOpFlags(Instruction *I, Value *Op0, Value *Op1, ConstraintInfo &Info)
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 void dumpConstraint(ArrayRef< Entry > C, const DenseMap< Value *, unsigned > &Value2Index)
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 checkAndReplaceUSubSat(SaturatingInst *USub, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
Try to replace USub by a plain subtract, if Info proves it cannot saturate.
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 tryToStrengthenFlags(Instruction *I, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
Try to strengthen I's poison generating flags using Info.
static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
static std::pair< Value *, Value * > getStartAndBackedgeValue(const PHINode &PN, const BasicBlock *LoopPred)
Splits the induction phi PN into the start value, coming from the loop predecessor LoopPred,...
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.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
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.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
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.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
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.
CmpInst::Predicate dropSameSign() const
Drops samesign information.
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 class represents a range of values.
static LLVM_ABI ConstantRange makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, const ConstantRange &Other, unsigned NoWrapKind)
Produce the largest range containing all X such that "X BinOp Y" is guaranteed not to wrap (overflow)...
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 &)
bool addRow(ArrayRef< Entry > R, size_t NumVars)
static RowTy negate(RowTy R)
LLVM_ABI std::pair< ConstraintSystem, RowTy > getSubSystem(ArrayRef< Entry > R) const
Build and return a sub-system of constraints connected (transitively) to query R, with variables comp...
static RowTy toStrictLessThan(RowTy R)
Converts the given row to form a strict less than inequality.
SmallVector< Entry, 8 > RowTy
A single constraint of the form 'c >= v1 * c1 + ... + vn * cn'.
static RowTy negateOrEqual(RowTy R)
Multiplies each coefficient in the given row by -1.
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)
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.
static bool isLT(Predicate P)
Return true if the predicate is SLT or ULT.
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.
static bool isLE(Predicate P)
Return true if the predicate is SLE or ULE.
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.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
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.
Utility class for integer operators which may exhibit overflow - Add, Sub, Mul, and Shl.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
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.
Represents a saturating add/sub intrinsic.
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.
MonotonicPredicateType
A predicate is said to be monotonically increasing if may go from being false to being true as the lo...
@ MonotonicallyDecreasing
@ 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 truncate(size_type N)
Like resize, but requires that N is less than size().
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.
bool isPointerTy() const
True if this is an instance of PointerType.
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.
bool isIntegerTy() const
True if this is an instance of IntegerType.
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.
AllOnesConstantMatch m_AllOnes()
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.
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)
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.
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))
match_combine_or< OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap >, DisjointOr_match< LHS, RHS > > m_NSWAddLike(const LHS &L, const RHS &R)
Match either "add nsw" or "or disjoint".
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap > m_NSWAdd(const LHS &L, const RHS &R)
LogicalOp_match< LHS, RHS, Instruction::And, true > m_c_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R with LHS and RHS in either order.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
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.
match_combine_or< OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap >, DisjointOr_match< LHS, RHS > > m_NUWAddLike(const LHS &L, const RHS &R)
Match either "add nuw" or "or disjoint".
LogicalOp_match< LHS, RHS, Instruction::Or, true > m_c_LogicalOr(const LHS &L, const RHS &R)
Matches L || R with LHS and RHS in either order.
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.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
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...
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.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
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.