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();
83 for (
Use &U :
I.uses()) {
104 Value *Op0 =
nullptr;
105 Value *Op1 =
nullptr;
109 : Pred(Pred), Op0(Op0), Op1(Op1) {}
147 FactOrCheck(EntryTy Ty,
DomTreeNode *DTN, Instruction *Inst,
148 Instruction *ContextInst =
nullptr)
149 : Inst(Inst), ContextInst(ContextInst ? ContextInst : Inst),
150 NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()), Ty(Ty) {}
153 :
U(
U), ContextInst(nullptr), NumIn(DTN->getDFSNumIn()),
154 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::UseCheck) {}
158 :
Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
159 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
161 static FactOrCheck getConditionFact(
DomTreeNode *DTN, CmpPredicate Pred,
164 return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
167 static FactOrCheck getInstFact(
DomTreeNode *DTN, Instruction *Inst) {
168 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
171 static FactOrCheck getCheck(
DomTreeNode *DTN, Use *U) {
172 return FactOrCheck(DTN, U);
175 static FactOrCheck getCheck(
DomTreeNode *DTN, Instruction *
I,
176 Instruction *ContextInst =
nullptr) {
178 "anchoring instruction must be in DTN's block");
179 return FactOrCheck(EntryTy::InstCheck, DTN,
I, ContextInst);
182 bool isCheck()
const {
183 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
187 assert(!isConditionFact());
188 if (Ty == EntryTy::UseCheck)
195 if (Ty == EntryTy::InstCheck)
201 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
206struct MonotonicInfo {
208 bool Decreasing =
false;
210 bool Unsigned =
false;
220 TargetLibraryInfo &TLI;
223 State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE,
224 TargetLibraryInfo &TLI)
225 : DT(DT), LI(LI), SE(SE), TLI(TLI) {}
228 void addInfoFor(BasicBlock &BB);
232 void addBoundsForHeaderInductions(BasicBlock &BB);
236 void addInfoForInductions(BasicBlock &BB);
240 MonotonicInfo getMonotonicityInfo(PHINode &PN,
Value *Step);
244 bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ)
const {
245 return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
254 bool IsSigned =
false;
257 SmallVector<Value *, 2> ValuesToRelease;
259 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
260 SmallVector<Value *, 2> ValuesToRelease)
261 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
262 ValuesToRelease(std::
move(ValuesToRelease)) {}
269 unsigned NumVars = 0;
271 bool IsSigned =
false;
273 ConstraintTy() =
default;
275 ConstraintTy(RowTy Coefficients,
unsigned NumVars,
bool IsSigned,
bool IsEq,
277 : Coefficients(std::
move(Coefficients)), NumVars(NumVars),
278 IsSigned(IsSigned), IsEq(IsEq), IsNe(IsNe) {}
280 bool empty()
const {
return Coefficients.empty(); }
282 bool isEq()
const {
return IsEq; }
284 bool isNe()
const {
return IsNe; }
291 std::optional<bool> isImpliedBy(
const ConstraintSystem &CS)
const;
304class ConstraintInfo {
306 ConstraintSystem UnsignedCS;
307 ConstraintSystem SignedCS;
309 const DataLayout &DL;
313 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
314 auto &Value2Index = getValue2Index(
false);
316 for (
Value *Arg : FunctionArgs)
317 UnsignedCS.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(Arg))},
321 DenseMap<Value *, unsigned> &getValue2Index(
bool Signed) {
322 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
324 const DenseMap<Value *, unsigned> &getValue2Index(
bool Signed)
const {
325 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
328 ConstraintSystem &getCS(
bool Signed) {
329 return Signed ? SignedCS : UnsignedCS;
331 const ConstraintSystem &getCS(
bool Signed)
const {
332 return Signed ? SignedCS : UnsignedCS;
335 void popLastConstraint(
bool Signed) { getCS(
Signed).popLastConstraint(); }
336 void popLastNVariables(
bool Signed,
unsigned N) {
337 getCS(
Signed).popLastNVariables(
N);
347 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
354 SmallVectorImpl<Value *> &NewVariables,
355 bool ForceSignedSystem =
false)
const;
370 unsigned NumIn,
unsigned NumOut,
371 SmallVectorImpl<StackEntry> &DFSInStack);
378 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
379 bool ForceSignedSystem);
383 void tightenBoundUsingNe(
Value *
A,
Value *
B,
unsigned NumIn,
unsigned NumOut,
384 SmallVectorImpl<StackEntry> &DFSInStack);
392 DecompEntry(int64_t Coefficient,
Value *Variable)
393 : Coefficient(Coefficient), Variable(Variable) {}
397struct Decomposition {
401 Decomposition(int64_t Offset) : Offset(Offset) {}
402 Decomposition(
Value *V) { Vars.emplace_back(1, V); }
404 : Offset(Offset), Vars(Vars) {}
408 [[nodiscard]]
bool add(int64_t OtherOffset) {
414 [[nodiscard]]
bool add(
const Decomposition &
Other) {
423 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
424 Decomposition Tmp =
Other;
435 [[nodiscard]]
bool mul(int64_t Factor) {
438 for (
auto &Var : Vars)
439 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
448 APInt ConstantOffset;
449 SmallMapVector<Value *, APInt, 4> VariableOffsets;
454 OffsetResult(GEPOperator &
GEP,
const DataLayout &
DL)
456 ConstantOffset = APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
466 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
468 Result.ConstantOffset))
476 bool CanCollectInner = InnerGEP->collectOffset(
477 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
479 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
480 VariableOffsets2.
size() > 1 ||
481 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
485 Result.BasePtr = InnerGEP->getPointerOperand();
486 Result.ConstantOffset += ConstantOffset2;
487 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
488 Result.VariableOffsets = std::move(VariableOffsets2);
489 Result.NW &= InnerGEP->getNoWrapFlags();
494static Decomposition
decompose(
Value *V,
const ConstraintInfo &Info,
506 if (R.isEmptySet() || (
Signed ? R.isSignWrappedSet() : R.isWrappedSet()))
512 unsigned BitWidth = R.getBitWidth();
513 APInt Min =
Signed ? R.getSignedMin() : R.getUnsignedMin();
514 APInt Max =
Signed ? R.getSignedMax() : R.getUnsignedMax();
526 ConstantInt::get(Ty, Min)))
530 ConstantInt::get(Ty, Max)))
538 unsigned NoWrapFlags,
const ConstraintInfo &Info,
542 if (NoWrapFlags & (
Signed ? OBO::NoSignedWrap : OBO::NoUnsignedWrap))
545 if (Opcode == Instruction::Sub) {
551 if (Info.isKnownNonNegative(Op1) &&
556 if (!
Signed && (NoWrapFlags & OBO::NoSignedWrap) &&
557 (Opcode == Instruction::Shl || Info.isKnownNonNegative(Op1)) &&
558 Info.isKnownNonNegative(Op0))
569 Opcode,
C->getValue(),
570 Signed ? OBO::NoSignedWrap : OBO::NoUnsignedWrap),
582 return Trunc->hasNoSignedWrap();
586 return Trunc->hasNoUnsignedWrap() ||
587 (Trunc->hasNoSignedWrap() &&
588 Info.isKnownNonNegative(Trunc->getOperand(0)));
594 BO->getOperand(0), BO->getOperand(1),
595 BO->getNoWrapKind(), Info,
Signed);
602 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
605 assert(!IsSigned &&
"The logic below only supports decomposition for "
606 "unsigned predicates at the moment.");
607 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
616 if (!NW.hasNoUnsignedSignedWrap() && ConstantOffset.isNegative())
619 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
620 for (
auto [Index, Scale] : VariableOffsets) {
621 if (!NW.hasNoUnsignedWrap()) {
624 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
625 if (!Info.isKnownNonNegative(Index))
629 auto IdxResult =
decompose(Index, Info, IsSigned,
DL);
630 if (IdxResult.mul(Scale.getSExtValue()))
632 if (Result.add(IdxResult))
646 auto MergeResults = [&Info, IsSigned,
648 bool IsSignedB) -> std::optional<Decomposition> {
657 if (Ty->isPointerTy() && !IsSigned) {
669 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
675 return CI->getSExtValue();
677 return int64_t(CI->getZExtValue());
693 if (!IsSigned && !Info.isKnownNonNegative(Op0))
697 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64 &&
699 V = Trunc->getOperand(0);
704 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
714 if (
auto Decomp = MergeResults(Op0, CI,
true))
721 Decomposition Result(-1);
722 if (!Result.sub(
decompose(Op0, Info, IsSigned,
DL)))
753 int64_t MaxShift = IsSigned ? Ty->getIntegerBitWidth() - 1 : 63;
771 const Decomposition &BDec,
777 if (
SubOverflow(BDec.Offset, ADec.Offset, OffsetSum))
779 RowTy R(1, Entry(OffsetSum, 0));
780 auto GetCoefficient = [&R](
unsigned Idx) -> int64_t & {
785 if (
I == R.end() ||
I->Id != Idx)
786 I = R.insert(
I, Entry(0, Idx));
787 return I->Coefficient;
791 auto GetOrAddIndex = [&Value2Index, &NewVariables](
Value *V) ->
unsigned {
792 auto V2I = Value2Index.
find(V);
793 if (V2I != Value2Index.
end())
795 unsigned Idx =
find(NewVariables, V) - NewVariables.
begin();
796 if (Idx == NewVariables.
size())
798 return Value2Index.
size() + Idx + 1;
800 for (
const DecompEntry &KV : ADec.Vars)
801 GetCoefficient(GetOrAddIndex(KV.Variable)) += KV.Coefficient;
803 for (
const DecompEntry &KV : BDec.Vars) {
804 auto &Coeff = GetCoefficient(GetOrAddIndex(KV.Variable));
810 erase_if(R, [](
const Entry &
E) {
return E.Id != 0 &&
E.Coefficient == 0; });
817 bool ForceSignedSystem)
const {
818 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
820 "signed system can only be forced on eq/ne");
861 auto &Value2Index = getValue2Index(IsSigned);
871 if (
AddOverflow(R[0].Coefficient, int64_t(-1), R[0].Coefficient))
875 unsigned NumV2I = Value2Index.size();
876 NewVariables.
truncate(
R.back().Id > NumV2I ?
R.back().Id - NumV2I : 0);
878 return ConstraintTy(std::move(R), Value2Index.size() + NewVariables.
size(),
879 IsSigned, IsEq, IsNe);
891 return ConstraintTy(RowTy(1,
Entry(0, 0)), 0,
892 false,
false,
false);
904 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
905 if (!NewVariables.
empty())
911ConstraintTy::isImpliedBy(
const ConstraintSystem &CS)
const {
912 const auto &[SubCS, NewCoefficients] = CS.
getSubSystem(Coefficients);
913 bool IsConditionImplied = SubCS.isConditionImplied(NewCoefficients);
917 bool IsNegatedOrEqualImplied =
918 !NegatedOrEqual.empty() && SubCS.isConditionImplied(NegatedOrEqual);
923 if (IsConditionImplied && IsNegatedOrEqualImplied)
927 bool IsNegatedImplied =
928 !Negated.empty() && SubCS.isConditionImplied(Negated);
931 bool IsStrictLessThanImplied =
932 !StrictLessThan.empty() && SubCS.isConditionImplied(StrictLessThan);
938 if (IsNegatedImplied || IsStrictLessThanImplied)
944 if (IsConditionImplied)
948 auto IsNegatedImplied = !Negated.empty() && SubCS.isConditionImplied(Negated);
949 if (IsNegatedImplied)
958 auto R = getConstraintForSolving(Pred,
A,
B);
960 getCS(
R.IsSigned).isConditionImpliedInSubSystem(
R.Coefficients);
963bool ConstraintInfo::isKnownNonNegative(
Value *V)
const {
965 return !CI->isNegative();
966 return ::isKnownNonNegative(V,
DL) ||
970void ConstraintInfo::transferToOtherSystem(
972 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
975 if (!
A->getType()->isIntegerTy())
1012 NumOut, DFSInStack);
1038static std::pair<Value *, Value *>
1041 "LoopPred must be a predecessor of the phi's block");
1043 return {
nullptr,
nullptr};
1050template <
typename PhiMatchTy>
1059MonotonicInfo State::getMonotonicityInfo(PHINode &PN,
Value *Step) {
1061 const APInt *StepOffset =
nullptr;
1065 Info.Unsigned = !
Info.Decreasing &&
Add->hasNoUnsignedWrap();
1066 Info.Signed =
Add->hasNoSignedWrap();
1072 APInt GEPOffset(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
1073 Info.Unsigned =
GEP->getPointerOperand() == &PN &&
1074 (
GEP->hasNoUnsignedWrap() ||
1075 ((
GEP->hasNoUnsignedSignedWrap() &&
1076 GEP->accumulateConstantOffset(
DL, GEPOffset) &&
1077 !GEPOffset.isNegative())));
1082 if (
Info.Unsigned ||
Info.Signed || !StepOffset)
1099void State::addBoundsForHeaderInductions(BasicBlock &BB) {
1101 if (!L ||
L->getHeader() != &BB)
1108 for (PHINode &PN : BB.
phis()) {
1116 MonotonicInfo
Info = getMonotonicityInfo(PN, Step);
1120 Info.Unsigned =
false;
1121 if (!
Info.Unsigned && !
Info.Signed)
1127 if (
Info.Decreasing)
1131 WorkList.
push_back(FactOrCheck::getConditionFact(DTN, Pred,
LHS,
RHS));
1135void State::addInfoForInductions(BasicBlock &BB) {
1142 if (Header != &BB && Latch != &BB)
1149 PHINode *PN =
nullptr;
1150 const APInt *IncStep =
nullptr;
1160 std::optional<bool> PeeledOnEdge;
1161 if (!
match(Br->getCondition(), CountingCmp)) {
1165 PeeledOnEdge =
true;
1167 PeeledOnEdge =
false;
1182 if (&BB == Latch && !IncStep)
1185 bool ContinueOnTrue =
1189 BasicBlock *InLoopSucc = Br->getSuccessor(ContinueOnTrue ? 0 : 1);
1193 if (PeeledOnEdge && *PeeledOnEdge != ContinueOnTrue)
1196 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB))
1200 if (!LoopPred || !
L->isLoopInvariant(
B))
1213 WorkList.
push_back(FactOrCheck::getConditionFact(
1214 DTN, ContinuePred, PN,
B,
ConditionTy(ContinuePred, StartValue,
B)));
1219 if (ICmpInst::isSigned(ContinuePred)) {
1222 "Expected a signed less-than continuation predicate");
1223 MonotonicInfo
Info = getMonotonicityInfo(*PN, Backedge);
1224 if (
Info.Signed && !
Info.Decreasing) {
1226 WorkList.
push_back(FactOrCheck::getConditionFact(
1236 const APInt *StepOffset =
nullptr;
1237 const SCEV *StartSCEV =
nullptr;
1239 if (StepOffset->
isZero())
1242 const SCEV *Expr = SE.
getSCEV(PN);
1251 if (IncStep && *IncStep != *StepOffset)
1254 MonotonicInfo
Info = getMonotonicityInfo(*PN, Backedge);
1259 if (!(-*StepOffset).isOne())
1269 ConditionTy BBeforeStartUnsigned = {UPrecond,
B, StartValue};
1275 WorkList.
push_back(FactOrCheck::getConditionFact(
1277 if (!(
Info.Decreasing &&
Info.Signed))
1278 WorkList.
push_back(FactOrCheck::getConditionFact(
1282 B, BBeforeStartUnsigned));
1284 B, BBeforeStartSigned));
1294 if (!StepOffset->
isOne()) {
1297 StartSCEV = SE.
getSCEV(StartValue);
1311 ConditionTy StartBeforeBoundUnsigned = {UPrecond, StartValue,
B};
1317 WorkList.
push_back(FactOrCheck::getConditionFact(
1320 WorkList.
push_back(FactOrCheck::getConditionFact(
1324 B, StartBeforeBoundSigned));
1325 WorkList.
push_back(FactOrCheck::getConditionFact(
1334 L->getExitBlocks(ExitBBs);
1335 for (BasicBlock *EB : ExitBBs) {
1350 if (!
Offset.NW.hasNoUnsignedWrap())
1353 if (
Offset.VariableOffsets.size() != 1)
1357 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1359 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1368 std::optional<TypeSize>
Size =
1383 B = ConstantInt::get(Index->getType(), MaxIndex);
1391 return Trunc->getType()->isIntegerTy() && Trunc->hasNoSignedWrap() &&
1392 !Trunc->hasNoUnsignedWrap();
1395 if (!BO || !BO->getType()->isIntegerTy())
1398 switch (BO->getOpcode()) {
1399 case Instruction::Sub:
1400 if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
1405 case Instruction::Add:
1406 case Instruction::Mul:
1407 case Instruction::Shl:
1408 if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
1427 I->setHasNoSignedWrap();
1432 I->setHasNoUnsignedWrap();
1438void State::addInfoFor(BasicBlock &BB) {
1439 addBoundsForHeaderInductions(BB);
1440 addInfoForInductions(BB);
1446 bool GuaranteedToExecute =
true;
1448 for (Instruction &
I : BB) {
1450 for (Use &U :
I.uses()) {
1452 auto *DTN = DT.
getNode(UserI->getParent());
1455 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1460 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1464 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1467 if (GuaranteedToExecute) {
1469 Pred,
A,
B,
DL, TLI)) {
1477 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1482 if (!LI->isVolatile())
1483 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1486 if (!
SI->isVolatile())
1487 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1493 case Intrinsic::assume: {
1496 if (GuaranteedToExecute) {
1503 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1508 case Intrinsic::sadd_with_overflow:
1509 case Intrinsic::ssub_with_overflow:
1510 case Intrinsic::ucmp:
1511 case Intrinsic::scmp:
1516 case Intrinsic::umin:
1517 case Intrinsic::umax:
1518 case Intrinsic::smin:
1519 case Intrinsic::smax:
1520 case Intrinsic::usub_sat:
1525 case Intrinsic::uadd_sat:
1531 case Intrinsic::abs:
1544 if ((BO->getOpcode() == Instruction::URem ||
1545 BO->getOpcode() == Instruction::UDiv ||
1546 BO->getOpcode() == Instruction::LShr ||
1547 BO->getOpcode() == Instruction::SRem) &&
1556 WorkList.
push_back(FactOrCheck::getCheck(
1564 for (
auto &Case :
Switch->cases()) {
1566 Value *
V = Case.getCaseValue();
1567 if (!canAddSuccessor(BB, Succ))
1596 SmallPtrSet<Value *, 8> SeenCond;
1597 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1598 if (SeenCond.
insert(V).second)
1603 while (!CondWorkList.
empty()) {
1628 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1630 DT.
getNode(Br->getSuccessor(0)), Pred,
A,
B));
1631 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1639 OS <<
"icmp " << Pred <<
' ';
1640 LHS->printAsOperand(OS,
true);
1642 RHS->printAsOperand(OS,
false);
1651struct ReproducerEntry {
1652 ICmpInst::Predicate Pred;
1687 auto &Value2Index = Info.getValue2Index(IsSigned);
1689 while (!WorkList.
empty()) {
1691 if (!Seen.
insert(V).second)
1693 if (Old2New.
find(V) != Old2New.
end())
1699 if (Value2Index.contains(V) || !
I ||
1710 for (
auto &Entry : Stack)
1713 CollectArguments(
Cond, IsSigned);
1716 for (
auto *
P : Args)
1722 Cond->getModule()->getName() +
1723 Cond->getFunction()->getName() +
"repro",
1726 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1728 Old2New[Args[
I]] =
F->getArg(
I);
1733 Builder.CreateRet(Builder.getTrue());
1734 Builder.SetInsertPoint(Entry->getTerminator());
1743 auto &Value2Index = Info.getValue2Index(IsSigned);
1744 while (!WorkList.
empty()) {
1746 if (Old2New.
find(V) != Old2New.
end())
1750 if (!Value2Index.contains(V) &&
I) {
1751 Old2New[V] =
nullptr;
1761 Old2New[
I] = Cloned;
1762 Old2New[
I]->setName(
I->getName());
1774 for (
auto &Entry : Stack) {
1783 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1784 Builder.CreateAssumption(Cmp);
1789 CloneInstructions(
Cond, IsSigned);
1790 Entry->getTerminator()->setOperand(0,
Cond);
1798 ConstraintInfo &Info) {
1801 auto TryWithConstraint = [&](
const ConstraintTy &R) -> std::optional<bool> {
1804 return std::nullopt;
1807 auto &CSToUse = Info.getCS(R.IsSigned);
1808 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1810 return std::nullopt;
1812 dbgs() <<
"Condition ";
1814 *ImpliedCondition ? Pred
1817 dbgs() <<
" implied by dominating constraints\n";
1820 return ImpliedCondition;
1822 return std::nullopt;
1825 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1826 if (
auto ImpliedCondition = TryWithConstraint(R))
1827 return ImpliedCondition;
1835 if (NewVariables.
empty() && !SR.empty() && Info.isKnownNonNegative(
A) &&
1836 Info.isKnownNonNegative(
B))
1837 if (
auto ImpliedCondition = TryWithConstraint(SR))
1838 return ImpliedCondition;
1844 const auto &Value2Index = Info.getValue2Index(
true);
1845 if (!Value2Index.contains(
A) && !Value2Index.contains(
B))
1846 return std::nullopt;
1849 auto SR = Info.getConstraint(Pred,
A,
B, NewVariables,
1851 if (NewVariables.
empty())
1852 if (
auto ImpliedCondition = TryWithConstraint(SR))
1853 return ImpliedCondition;
1855 return std::nullopt;
1860 ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1864 auto ReplaceCmpWithConstant = [&](
Instruction *CheckInst,
bool IsTrue) {
1866 ReproducerCondStack, Info, DT);
1871 auto *DTN = DT.
getNode(UserI->getParent());
1874 if (UserI->getParent() == ContextInst->
getParent() &&
1875 UserI->comesBefore(ContextInst))
1881 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1890 for (
auto *DVR : DVRUsers) {
1891 auto *DTN = DT.
getNode(DVR->getParent());
1895 auto *MarkedI = DVR->getInstruction();
1896 if (MarkedI->getParent() == ContextInst->
getParent() &&
1897 MarkedI->comesBefore(ContextInst))
1900 DVR->replaceVariableLocationOp(CheckInst, ConstantC);
1910 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1917 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
1926 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1935 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1938 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1947 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1957 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1975 Value *
Sub = Builder.CreateSub(
A,
B,
"",
true,
1976 Info.isKnownNonNegative(
A));
1978 Sub->takeName(USub);
1985 Module *ReproducerModule,
1988 Info.popLastConstraint(
E.IsSigned);
1990 auto &Mapping = Info.getValue2Index(
E.IsSigned);
1991 for (
Value *V :
E.ValuesToRelease)
1993 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
1995 if (ReproducerModule)
2002 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
2011 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
2019 unsigned OldSize = DFSInStack.
size();
2022 while (OldSize < DFSInStack.
size()) {
2023 StackEntry
E = DFSInStack.
back();
2031 while (!Worklist.empty()) {
2032 Value *Val = Worklist.pop_back_val();
2040 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
2045 Worklist.push_back(
LHS);
2046 Worklist.push_back(
RHS);
2049 if (OldSize == DFSInStack.
size())
2054 [[maybe_unused]]
bool Matched =
2056 assert(Matched &&
"expected icmp-like match");
2058 if (
auto ImpliedCondition =
checkCondition(Pred,
A,
B, CmpToCheck, Info)) {
2059 if (IsOr == *ImpliedCondition)
2072 unsigned NumIn,
unsigned NumOut,
2073 SmallVectorImpl<StackEntry> &DFSInStack) {
2074 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
2077 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
2079 tightenBoundUsingNe(
A,
B, NumIn, NumOut, DFSInStack);
2082void ConstraintInfo::tightenBoundUsingNe(
2084 SmallVectorImpl<StackEntry> &DFSInStack) {
2085 if (!
A->getType()->isIntegerTy())
2088 for (
bool IsSigned : {
false,
true}) {
2095 const auto &Value2Index = getValue2Index(IsSigned);
2097 [&Value2Index](
const DecompEntry &
E) {
2098 return !Value2Index.contains(
E.Variable);
2109 if (!doesHold(NonStrict,
A,
B))
2115 dbgs() <<
"' using inequality\n");
2116 addFactImpl(
Strict,
A,
B, NumIn, NumOut, DFSInStack,
2124 unsigned NumIn,
unsigned NumOut,
2125 SmallVectorImpl<StackEntry> &DFSInStack,
2126 bool ForceSignedSystem) {
2128 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
2131 if (
R.empty() ||
R.isNe())
2136 auto &CSToUse = getCS(
R.IsSigned);
2137 bool Added = CSToUse.addRow(
R.Coefficients,
R.NumVars);
2143 SmallVector<Value *, 2> ValuesToRelease;
2144 auto &Value2Index = getValue2Index(
R.IsSigned);
2145 for (
Value *V : NewVariables) {
2146 Value2Index.try_emplace(V, Value2Index.size() + 1);
2151 dbgs() <<
" constraint: ";
2157 std::move(ValuesToRelease));
2160 for (
Value *V : NewVariables) {
2162 CSToUse.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(V))},
2163 Value2Index.size());
2165 SmallVector<Value *, 2>());
2171 for (Entry &
E :
R.Coefficients)
2174 CSToUse.addRow(
R.Coefficients,
R.NumVars);
2177 SmallVector<Value *, 2>());
2189 Value *Res =
nullptr;
2193 Res = Builder.CreateNoWrapBinOp(Opcode,
A,
B,
false,
2198 U->replaceAllUsesWith(Builder.getFalse());
2203 if (U->use_empty()) {
2211 if (
II->use_empty()) {
2213 for (
Use &Arg :
II->args())
2224 switch (
II->getIntrinsicID()) {
2225 case Intrinsic::ssub_with_overflow: {
2235 case Intrinsic::sadd_with_overflow: {
2260 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
2261 State S(DT, LI, SE, TLI);
2262 std::unique_ptr<Module> ReproducerModule(
2281 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
2282 auto HasNoConstOp = [](const FactOrCheck &B) {
2283 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
2284 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
2285 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
2289 if (
A.NumIn ==
B.NumIn) {
2290 if (A.isConditionFact() && B.isConditionFact()) {
2291 bool NoConstOpA = HasNoConstOp(A);
2292 bool NoConstOpB = HasNoConstOp(B);
2293 return NoConstOpA < NoConstOpB;
2295 if (
A.isConditionFact())
2297 if (
B.isConditionFact())
2299 auto *InstA =
A.getContextInst();
2300 auto *InstB =
B.getContextInst();
2301 return InstA->comesBefore(InstB);
2303 return A.NumIn <
B.NumIn;
2306 SmallVector<Instruction *>
ToRemove;
2311 for (FactOrCheck &CB : S.WorkList) {
2314 while (!DFSInStack.
empty()) {
2315 auto &
E = DFSInStack.
back();
2318 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
2320 if (CB.NumOut <=
E.NumOut)
2323 dbgs() <<
"Removing ";
2325 Info.getValue2Index(
E.IsSigned));
2337 Instruction *Inst = CB.getInstructionToSimplify();
2344 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
2350 Pred,
A,
B, Inst, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
2351 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
2355 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
2370 auto AddFact = [&](CmpPredicate Pred,
Value *
A,
Value *
B) {
2376 <<
"Skip adding constraint because system has too many rows.\n");
2380 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
2381 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
2390 CB.NumIn, CB.NumOut, DFSInStack);
2392 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
2406 SmallPtrSet<Value *, 4> Seen;
2407 while (!Worklist.
empty()) {
2410 if (!BO || BO->getOpcode() !=
Opc)
2412 for (
Value *
Op : {BO->getOperand(0), BO->getOperand(1)}) {
2416 Info.addFact(Pred,
Op,
B, CB.NumIn, CB.NumOut, DFSInStack);
2421 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
2424 for (
unsigned I = 0,
2425 E = (DFSInStack.
size() - ReproducerCondStack.
size());
2427 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
2433 if (!CB.isConditionFact()) {
2439 ConstantInt::get(CB.Inst->getType(), 0));
2445 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
2446 AddFact(Pred, MinMax, MinMax->getLHS());
2447 AddFact(Pred, MinMax, MinMax->getRHS());
2451 switch (USatI->getIntrinsicID()) {
2454 case Intrinsic::uadd_sat:
2455 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2456 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2458 case Intrinsic::usub_sat:
2459 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2466 if (BO->getOpcode() == Instruction::URem) {
2473 if (BO->getOpcode() == Instruction::UDiv) {
2478 if (BO->getOpcode() == Instruction::LShr) {
2483 if (BO->getOpcode() == Instruction::SRem) {
2484 Value *
X = BO->getOperand(0);
2485 Value *
N = BO->getOperand(1);
2505 auto &
DL =
F.getDataLayout();
2506 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2511 DL.getTypeStoreSize(AccessType).getFixedValue(), Pred,
A,
B,
DL,
2513 AddFact(Pred,
A,
B);
2517 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2521 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2526 if (CB.isConditionFact()) {
2527 Pred = CB.Cond.Pred;
2531 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2533 dbgs() <<
"Not adding fact ";
2535 dbgs() <<
" because precondition ";
2538 dbgs() <<
" does not hold.\n";
2543 [[maybe_unused]]
bool Matched =
2547 "Must have an assume intrinsic with a icmp like operand");
2549 AddFact(Pred,
A,
B);
2552 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2554 raw_string_ostream StringS(S);
2555 ReproducerModule->print(StringS,
nullptr);
2556 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2557 Rem <<
ore::NV(
"module") << S;
2562 unsigned SignedEntries =
2563 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2564 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2565 DFSInStack.
size() - SignedEntries &&
2566 "updates to CS and DFSInStack are out of sync");
2567 assert(
Info.getCS(
true).size() == SignedEntries &&
2568 "updates to CS and DFSInStack are out of sync");
2572 I->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
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 auto m_IncrementOf(const PhiMatchTy &PhiM, const APInt *&Off)
Matches an increment of PhiM by a constant offset, captured in Off.
static Instruction * getContextInstForUse(Use &U)
static bool replaceOverflowUses(IntrinsicInst *II, Instruction::BinaryOps Opcode, Value *A, Value *B, SmallVectorImpl< Instruction * > &ToRemove)
Replace the uses of the overflow intrinsic II, which has been proven not to signed-overflow,...
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 canUseSExt(ConstantInt *CI)
static void removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack)
static std::optional< bool > checkCondition(CmpInst::Predicate Pred, Value *A, Value *B, Instruction *CheckInst, ConstraintInfo &Info)
static cl::opt< unsigned > MaxRows("constraint-elimination-max-rows", cl::init(500), cl::Hidden, cl::desc("Maximum number of rows to keep in constraint system"))
static cl::opt< bool > DumpReproducers("constraint-elimination-dump-reproducers", cl::init(false), cl::Hidden, cl::desc("Dump IR to reproduce successful transformations."))
static bool checkOrAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack, SmallVectorImpl< Instruction * > &ToRemove)
Check if either the first condition of an AND or OR is implied by the (negated in case of OR) second ...
static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE, OptimizationRemarkEmitter &ORE, TargetLibraryInfo &TLI)
static OffsetResult collectOffsets(GEPOperator &GEP, const DataLayout &DL)
static bool checkAndReplaceMinMax(MinMaxIntrinsic *MinMax, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
static bool tryToStrengthenFlags(Instruction *I, ConstraintInfo &Info)
Try to strengthen I's poison generating flags using Info.
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 RowTy getRowForLessEqual(const Decomposition &ADec, const Decomposition &BDec, const DenseMap< Value *, unsigned > &Value2Index, SmallVectorImpl< Value * > &NewVariables)
Build the row for 'ADec <= BDec', using the indices from Value2Index.
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 tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
static Instruction * findCommonDominatorOfUses(Instruction &I, DominatorTree &DT)
Returns the closest program point dominating all uses of I.
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,...
static bool isKnownNoWrap(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, unsigned NoWrapFlags, const ConstraintInfo &Info, bool Signed)
Returns true if Opcode applied to Op0 and Op1 with NoWrapFlags is known to not wrap in signed or unsi...
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Machine Check Debug Module
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
const SmallVectorImpl< MachineOperand > & Cond
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.
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)...
static LLVM_ABI ConstantRange makeExactNoWrapRegion(Instruction::BinaryOps BinOp, const APInt &Other, unsigned NoWrapKind)
Produce the range that contains X if and only if "X BinOp Other" does not wrap.
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)
iterator find(const_arg_type_t< 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 Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
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'.
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.
auto m_LogicalOp()
Matches either L && R or L || R where L and R are arbitrary values.
CommutativeBinaryIntrinsic_match< IntrID, T0, T1 > m_c_Intrinsic(const T0 &Op0, const T1 &Op1)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
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.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
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.
match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)
Match either "add" or "or disjoint".
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
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.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
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.
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.
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.