55#define DEBUG_TYPE "constraint-elimination"
57STATISTIC(NumCondsRemoved,
"Number of instructions removed");
59 "Controls which conditions are eliminated");
63 cl::desc(
"Maximum number of rows to keep in constraint system"));
67 cl::desc(
"Dump IR to reproduce successful transformations."));
75 UserI = Phi->getIncomingBlock(U)->getTerminator();
84 for (
Use &U :
I.uses()) {
105 Value *Op0 =
nullptr;
106 Value *Op1 =
nullptr;
110 : Pred(Pred), Op0(Op0), Op1(Op1) {}
148 FactOrCheck(EntryTy Ty,
DomTreeNode *DTN, Instruction *Inst,
149 Instruction *ContextInst =
nullptr)
150 : Inst(Inst), ContextInst(ContextInst ? ContextInst : Inst),
151 NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()), Ty(Ty) {}
154 :
U(
U), ContextInst(nullptr), NumIn(DTN->getDFSNumIn()),
155 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::UseCheck) {}
159 :
Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
160 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
162 static FactOrCheck getConditionFact(
DomTreeNode *DTN, CmpPredicate Pred,
165 return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
168 static FactOrCheck getInstFact(
DomTreeNode *DTN, Instruction *Inst) {
169 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
172 static FactOrCheck getCheck(
DomTreeNode *DTN, Use *U) {
173 return FactOrCheck(DTN, U);
176 static FactOrCheck getCheck(
DomTreeNode *DTN, Instruction *
I,
177 Instruction *ContextInst =
nullptr) {
179 "anchoring instruction must be in DTN's block");
180 return FactOrCheck(EntryTy::InstCheck, DTN,
I, ContextInst);
183 bool isCheck()
const {
184 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
188 assert(!isConditionFact());
189 if (Ty == EntryTy::UseCheck)
196 if (Ty == EntryTy::InstCheck)
202 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
207struct MonotonicInfo {
209 bool Decreasing =
false;
211 bool Unsigned =
false;
222 TargetLibraryInfo &TLI;
225 State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution *SE,
226 TargetLibraryInfo &TLI)
227 : DT(DT), LI(LI), SE(SE), TLI(TLI) {}
230 void addInfoFor(BasicBlock &BB);
234 void addBoundsForHeaderInductions(BasicBlock &BB);
238 void addInfoForInductions(BasicBlock &BB);
242 MonotonicInfo getMonotonicityInfo(PHINode &PN,
Value *Step);
246 bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ)
const {
247 return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
256 bool IsSigned =
false;
259 SmallVector<Value *, 2> ValuesToRelease;
261 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
262 SmallVector<Value *, 2> ValuesToRelease)
263 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
264 ValuesToRelease(std::
move(ValuesToRelease)) {}
271 unsigned NumVars = 0;
273 bool IsSigned =
false;
275 ConstraintTy() =
default;
277 ConstraintTy(RowTy Coefficients,
unsigned NumVars,
bool IsSigned,
bool IsEq,
279 : Coefficients(std::
move(Coefficients)), NumVars(NumVars),
280 IsSigned(IsSigned), IsEq(IsEq), IsNe(IsNe) {}
282 bool empty()
const {
return Coefficients.empty(); }
284 bool isEq()
const {
return IsEq; }
286 bool isNe()
const {
return IsNe; }
293 std::optional<bool> isImpliedBy(
const ConstraintSystem &CS)
const;
305 DecompEntry(int64_t Coefficient,
Value *Variable)
306 : Coefficient(Coefficient), Variable(Variable) {}
310struct Decomposition {
314 Decomposition(int64_t Offset) : Offset(Offset) {}
315 Decomposition(
Value *V) { Vars.emplace_back(1, V); }
317 : Offset(Offset), Vars(Vars) {}
321 [[nodiscard]]
bool add(int64_t OtherOffset) {
327 [[nodiscard]]
bool add(
const Decomposition &
Other) {
336 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
337 Decomposition Tmp =
Other;
348 [[nodiscard]]
bool mul(int64_t Factor) {
351 for (
auto &Var : Vars)
352 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
364class ConstraintInfo {
366 ConstraintSystem UnsignedCS;
367 ConstraintSystem SignedCS;
369 const DataLayout &DL;
373 DenseMap<PointerIntPair<Value *, 1, bool>, Decomposition> DecomposeCache;
376 DenseMap<PointerIntPair<Value *, 1, bool>, Decomposition> &
377 getDecomposeCache() {
378 return DecomposeCache;
382 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
383 auto &Value2Index = getValue2Index(
false);
385 for (
Value *Arg : FunctionArgs)
386 UnsignedCS.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(Arg))},
390 DenseMap<Value *, unsigned> &getValue2Index(
bool Signed) {
391 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
393 const DenseMap<Value *, unsigned> &getValue2Index(
bool Signed)
const {
394 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
397 ConstraintSystem &getCS(
bool Signed) {
398 return Signed ? SignedCS : UnsignedCS;
400 const ConstraintSystem &getCS(
bool Signed)
const {
401 return Signed ? SignedCS : UnsignedCS;
404 void popLastConstraint(
bool Signed) {
405 assert(DecomposeCache.empty() &&
"Cache must be cleared");
406 getCS(
Signed).popLastConstraint();
408 void popLastNVariables(
bool Signed,
unsigned N) {
409 assert(DecomposeCache.empty() &&
"Cache must be cleared");
410 getCS(
Signed).popLastNVariables(
N);
424 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
431 SmallVectorImpl<Value *> &NewVariables,
432 bool ForceSignedSystem =
false);
447 unsigned NumIn,
unsigned NumOut,
448 SmallVectorImpl<StackEntry> &DFSInStack);
455 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
456 bool ForceSignedSystem);
460 void tightenBoundUsingNe(
Value *
A,
Value *
B,
unsigned NumIn,
unsigned NumOut,
461 SmallVectorImpl<StackEntry> &DFSInStack);
467 APInt ConstantOffset;
468 SmallMapVector<Value *, APInt, 4> VariableOffsets;
473 OffsetResult(GEPOperator &
GEP,
const DataLayout &
DL)
475 ConstantOffset = APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
485 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
487 Result.ConstantOffset))
495 bool CanCollectInner = InnerGEP->collectOffset(
496 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
498 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
499 VariableOffsets2.
size() > 1 ||
500 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
504 Result.BasePtr = InnerGEP->getPointerOperand();
505 Result.ConstantOffset += ConstantOffset2;
506 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
507 Result.VariableOffsets = std::move(VariableOffsets2);
508 Result.NW &= InnerGEP->getNoWrapFlags();
513static Decomposition
decompose(
Value *V, ConstraintInfo &Info,
bool IsSigned,
525 if (R.isEmptySet() || (
Signed ? R.isSignWrappedSet() : R.isWrappedSet()))
531 unsigned BitWidth = R.getBitWidth();
532 APInt Min =
Signed ? R.getSignedMin() : R.getUnsignedMin();
533 APInt Max =
Signed ? R.getSignedMax() : R.getUnsignedMax();
545 ConstantInt::get(Ty, Min)))
549 ConstantInt::get(Ty, Max)))
557 unsigned NoWrapFlags, ConstraintInfo &Info,
561 if (NoWrapFlags & (
Signed ? OBO::NoSignedWrap : OBO::NoUnsignedWrap))
564 if (Opcode == Instruction::Sub) {
570 if (Info.isKnownNonNegative(Op1) &&
575 if (!
Signed && (NoWrapFlags & OBO::NoSignedWrap) &&
576 (Opcode == Instruction::Shl || Info.isKnownNonNegative(Op1)) &&
577 Info.isKnownNonNegative(Op0))
588 Opcode,
C->getValue(),
589 Signed ? OBO::NoSignedWrap : OBO::NoUnsignedWrap),
600 return isKnownNoWrap(WO->getBinaryOp(), WO->getLHS(), WO->getRHS(),
605 return Trunc->hasNoSignedWrap();
609 return Trunc->hasNoUnsignedWrap() ||
610 (Trunc->hasNoSignedWrap() &&
611 Info.isKnownNonNegative(Trunc->getOperand(0)));
617 BO->getOperand(0), BO->getOperand(1),
618 BO->getNoWrapKind(), Info,
Signed);
625 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
628 assert(!IsSigned &&
"The logic below only supports decomposition for "
629 "unsigned predicates at the moment.");
630 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
639 if (!NW.hasNoUnsignedSignedWrap() && ConstantOffset.isNegative())
642 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
643 for (
auto [Index, Scale] : VariableOffsets) {
644 if (!NW.hasNoUnsignedWrap()) {
647 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
648 if (!Info.isKnownNonNegative(Index))
652 auto IdxResult =
decompose(Index, Info, IsSigned,
DL);
653 if (IdxResult.mul(Scale.getSExtValue()))
655 if (Result.add(IdxResult))
675 switch (
Op->getOpcode()) {
676 case Instruction::GetElementPtr:
677 case Instruction::Add:
678 case Instruction::Sub:
679 case Instruction::Mul:
680 case Instruction::Shl:
681 case Instruction::ZExt:
682 case Instruction::SExt:
683 case Instruction::Trunc:
684 case Instruction::Or:
685 case Instruction::Xor:
698 auto &Cache = Info.getDecomposeCache();
699 auto It = Cache.find(
Key);
700 if (It != Cache.end())
704 Info.getDecomposeCache().insert({
Key, Result});
710 auto MergeResults = [&Info, IsSigned,
712 bool IsSignedB) -> std::optional<Decomposition> {
721 if (Ty->isPointerTy() && !IsSigned) {
733 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
739 return CI->getSExtValue();
741 return int64_t(CI->getZExtValue());
757 if (!IsSigned && !Info.isKnownNonNegative(Op0))
761 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64 &&
763 V = Trunc->getOperand(0);
768 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
778 if (
auto Decomp = MergeResults(Op0, CI,
true))
785 Decomposition Result(-1);
786 if (!Result.sub(
decompose(Op0, Info, IsSigned,
DL)))
817 int64_t MaxShift = IsSigned ? Ty->getIntegerBitWidth() - 1 : 63;
835 const Decomposition &BDec,
841 if (
SubOverflow(BDec.Offset, ADec.Offset, OffsetSum))
843 RowTy R(1, Entry(OffsetSum, 0));
844 auto GetCoefficient = [&R](
unsigned Idx) -> int64_t & {
849 if (
I == R.end() ||
I->Id != Idx)
850 I = R.insert(
I, Entry(0, Idx));
851 return I->Coefficient;
855 auto GetOrAddIndex = [&Value2Index, &NewVariables](
Value *V) ->
unsigned {
856 auto V2I = Value2Index.
find(V);
857 if (V2I != Value2Index.
end())
859 unsigned Idx =
find(NewVariables, V) - NewVariables.
begin();
860 if (Idx == NewVariables.
size())
862 return Value2Index.
size() + Idx + 1;
864 for (
const DecompEntry &KV : ADec.Vars)
865 GetCoefficient(GetOrAddIndex(KV.Variable)) += KV.Coefficient;
867 for (
const DecompEntry &KV : BDec.Vars) {
868 auto &Coeff = GetCoefficient(GetOrAddIndex(KV.Variable));
874 erase_if(R, [](
const Entry &
E) {
return E.Id != 0 &&
E.Coefficient == 0; });
881 bool ForceSignedSystem) {
882 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
884 "signed system can only be forced on eq/ne");
925 auto &Value2Index = getValue2Index(IsSigned);
935 if (
AddOverflow(R[0].Coefficient, int64_t(-1), R[0].Coefficient))
939 unsigned NumV2I = Value2Index.size();
940 NewVariables.
truncate(
R.back().Id > NumV2I ?
R.back().Id - NumV2I : 0);
942 return ConstraintTy(std::move(R), Value2Index.size() + NewVariables.
size(),
943 IsSigned, IsEq, IsNe);
954 return ConstraintTy(RowTy(1,
Entry(0, 0)), 0,
955 false,
false,
false);
967 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
968 if (!NewVariables.
empty())
974ConstraintTy::isImpliedBy(
const ConstraintSystem &CS)
const {
975 const auto &[SubCS, NewCoefficients] = CS.
getSubSystem(Coefficients);
976 bool IsConditionImplied = SubCS.isConditionImplied(NewCoefficients);
980 bool IsNegatedOrEqualImplied =
981 !NegatedOrEqual.empty() && SubCS.isConditionImplied(NegatedOrEqual);
986 if (IsConditionImplied && IsNegatedOrEqualImplied)
990 bool IsNegatedImplied =
991 !Negated.empty() && SubCS.isConditionImplied(Negated);
994 bool IsStrictLessThanImplied =
995 !StrictLessThan.empty() && SubCS.isConditionImplied(StrictLessThan);
1001 if (IsNegatedImplied || IsStrictLessThanImplied)
1004 return std::nullopt;
1007 if (IsConditionImplied)
1011 auto IsNegatedImplied = !Negated.empty() && SubCS.isConditionImplied(Negated);
1012 if (IsNegatedImplied)
1016 return std::nullopt;
1020 auto R = getConstraintForSolving(Pred,
A,
B);
1021 return !
R.empty() &&
1022 getCS(
R.IsSigned).isConditionImpliedInSubSystem(
R.Coefficients);
1025bool ConstraintInfo::isKnownNonNegative(
Value *V) {
1027 return !CI->isNegative();
1028 return ::isKnownNonNegative(V,
DL) ||
1032bool ConstraintInfo::isKnownPositive(
Value *V) {
1034 return CI->getValue().isStrictlyPositive();
1035 return ::isKnownPositive(V,
DL) ||
1039void ConstraintInfo::transferToOtherSystem(
1041 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
1044 if (!
A->getType()->isIntegerTy())
1057 NumOut, DFSInStack);
1067 NumOut, DFSInStack);
1081 NumOut, DFSInStack);
1107static std::pair<Value *, Value *>
1110 "LoopPred must be a predecessor of the phi's block");
1112 return {
nullptr,
nullptr};
1119template <
typename PhiMatchTy>
1128MonotonicInfo State::getMonotonicityInfo(PHINode &PN,
Value *Step) {
1130 const APInt *StepOffset =
nullptr;
1134 Info.Unsigned = !
Info.Decreasing &&
Add->hasNoUnsignedWrap();
1135 Info.Signed =
Add->hasNoSignedWrap();
1141 APInt GEPOffset(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
1142 Info.Unsigned =
GEP->getPointerOperand() == &PN &&
1143 (
GEP->hasNoUnsignedWrap() ||
1144 ((
GEP->hasNoUnsignedSignedWrap() &&
1145 GEP->accumulateConstantOffset(
DL, GEPOffset) &&
1146 !GEPOffset.isNegative())));
1151 if (
Info.Unsigned ||
Info.Signed || !StepOffset)
1168void State::addBoundsForHeaderInductions(BasicBlock &BB) {
1170 if (!L ||
L->getHeader() != &BB)
1177 for (PHINode &PN : BB.
phis()) {
1185 MonotonicInfo
Info = getMonotonicityInfo(PN, Step);
1189 Info.Unsigned =
false;
1190 if (!
Info.Unsigned && !
Info.Signed)
1196 if (
Info.Decreasing)
1200 WorkList.
push_back(FactOrCheck::getConditionFact(DTN, Pred,
LHS,
RHS));
1204void State::addInfoForInductions(BasicBlock &BB) {
1211 if (Header != &BB && Latch != &BB)
1218 PHINode *PN =
nullptr;
1219 const APInt *IncStep =
nullptr;
1229 std::optional<bool> PeeledOnEdge;
1230 if (!
match(Br->getCondition(), CountingCmp)) {
1234 PeeledOnEdge =
true;
1236 PeeledOnEdge =
false;
1251 if (&BB == Latch && !IncStep)
1254 bool ContinueOnTrue =
1258 BasicBlock *InLoopSucc = Br->getSuccessor(ContinueOnTrue ? 0 : 1);
1262 if (PeeledOnEdge && *PeeledOnEdge != ContinueOnTrue)
1265 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB))
1269 if (!LoopPred || !
L->isLoopInvariant(
B))
1282 WorkList.
push_back(FactOrCheck::getConditionFact(
1283 DTN, ContinuePred, PN,
B,
ConditionTy(ContinuePred, StartValue,
B)));
1288 if (ICmpInst::isSigned(ContinuePred)) {
1291 "Expected a signed less-than continuation predicate");
1292 MonotonicInfo
Info = getMonotonicityInfo(*PN, Backedge);
1293 if (
Info.Signed && !
Info.Decreasing) {
1295 WorkList.
push_back(FactOrCheck::getConditionFact(
1305 const APInt *StepOffset =
nullptr;
1306 const SCEV *StartSCEV =
nullptr;
1308 if (StepOffset->
isZero())
1311 const SCEV *Expr = SE->
getSCEV(PN);
1320 if (IncStep && *IncStep != *StepOffset)
1323 MonotonicInfo
Info = getMonotonicityInfo(*PN, Backedge);
1328 if (!(-*StepOffset).isOne())
1338 ConditionTy BBeforeStartUnsigned = {UPrecond,
B, StartValue};
1344 WorkList.
push_back(FactOrCheck::getConditionFact(
1346 if (!(
Info.Decreasing &&
Info.Signed))
1347 WorkList.
push_back(FactOrCheck::getConditionFact(
1351 B, BBeforeStartUnsigned));
1353 B, BBeforeStartSigned));
1363 if (!StepOffset->
isOne()) {
1366 StartSCEV = SE->
getSCEV(StartValue);
1380 ConditionTy StartBeforeBoundUnsigned = {UPrecond, StartValue,
B};
1386 WorkList.
push_back(FactOrCheck::getConditionFact(
1389 WorkList.
push_back(FactOrCheck::getConditionFact(
1393 B, StartBeforeBoundSigned));
1394 WorkList.
push_back(FactOrCheck::getConditionFact(
1403 L->getExitBlocks(ExitBBs);
1404 for (BasicBlock *EB : ExitBBs) {
1418 if (!
GEP.hasNoUnsignedWrap())
1423 Base = InnerGEP->getPointerOperand();
1439 if (
Offset.VariableOffsets.size() != 1)
1443 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1445 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1458 B = ConstantInt::get(Index->getType(), MaxIndex);
1466 return Trunc->getType()->isIntegerTy() && Trunc->hasNoSignedWrap() &&
1467 !Trunc->hasNoUnsignedWrap();
1470 if (!BO || !BO->getType()->isIntegerTy())
1473 switch (BO->getOpcode()) {
1474 case Instruction::Sub:
1475 if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
1480 case Instruction::Add:
1481 case Instruction::Mul:
1482 case Instruction::Shl:
1483 if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
1502 I->setHasNoSignedWrap();
1507 I->setHasNoUnsignedWrap();
1513void State::addInfoFor(BasicBlock &BB) {
1514 addBoundsForHeaderInductions(BB);
1515 addInfoForInductions(BB);
1521 bool GuaranteedToExecute =
true;
1523 for (Instruction &
I : BB) {
1525 for (Use &U :
I.uses()) {
1527 auto *DTN = DT.
getNode(UserI->getParent());
1530 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1535 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1539 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1542 if (GuaranteedToExecute) {
1544 Pred,
A,
B,
DL, TLI)) {
1552 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1557 if (!LI->isVolatile())
1558 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1561 if (!
SI->isVolatile())
1562 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1568 case Intrinsic::assume: {
1571 if (GuaranteedToExecute) {
1578 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1583 case Intrinsic::uadd_with_overflow:
1584 case Intrinsic::sadd_with_overflow:
1585 case Intrinsic::usub_with_overflow:
1586 case Intrinsic::ssub_with_overflow:
1587 case Intrinsic::umul_with_overflow:
1588 case Intrinsic::smul_with_overflow:
1589 case Intrinsic::ucmp:
1590 case Intrinsic::scmp:
1595 case Intrinsic::umin:
1596 case Intrinsic::umax:
1597 case Intrinsic::smin:
1598 case Intrinsic::smax:
1599 case Intrinsic::usub_sat:
1604 case Intrinsic::uadd_sat:
1610 case Intrinsic::abs:
1625 if ((BO->getOpcode() == Instruction::URem ||
1626 BO->getOpcode() == Instruction::UDiv ||
1627 BO->getOpcode() == Instruction::LShr ||
1628 BO->getOpcode() == Instruction::SRem ||
1629 BO->getOpcode() == Instruction::SDiv) &&
1638 WorkList.
push_back(FactOrCheck::getCheck(
1646 for (
auto &Case :
Switch->cases()) {
1648 Value *
V = Case.getCaseValue();
1649 if (!canAddSuccessor(BB, Succ))
1678 SmallPtrSet<Value *, 8> SeenCond;
1679 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1680 if (SeenCond.
insert(V).second)
1685 while (!CondWorkList.
empty()) {
1710 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1712 DT.
getNode(Br->getSuccessor(0)), Pred,
A,
B));
1713 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1721 OS <<
"icmp " << Pred <<
' ';
1722 LHS->printAsOperand(OS,
true);
1724 RHS->printAsOperand(OS,
false);
1733struct ReproducerEntry {
1734 ICmpInst::Predicate Pred;
1769 auto &Value2Index = Info.getValue2Index(IsSigned);
1771 while (!WorkList.
empty()) {
1773 if (!Seen.
insert(V).second)
1775 if (Old2New.
find(V) != Old2New.
end())
1781 if (Value2Index.contains(V) || !
I ||
1792 for (
auto &Entry : Stack)
1795 CollectArguments(
Cond, IsSigned);
1798 for (
auto *
P : Args)
1804 Cond->getModule()->getName() +
1805 Cond->getFunction()->getName() +
"repro",
1808 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1810 Old2New[Args[
I]] =
F->getArg(
I);
1815 Builder.CreateRet(Builder.getTrue());
1816 Builder.SetInsertPoint(Entry->getTerminator());
1825 auto &Value2Index = Info.getValue2Index(IsSigned);
1826 while (!WorkList.
empty()) {
1828 if (Old2New.
find(V) != Old2New.
end())
1832 if (!Value2Index.contains(V) &&
I) {
1833 Old2New[V] =
nullptr;
1843 Old2New[
I] = Cloned;
1844 Old2New[
I]->setName(
I->getName());
1856 for (
auto &Entry : Stack) {
1865 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1866 Builder.CreateAssumption(Cmp);
1871 CloneInstructions(
Cond, IsSigned);
1872 Entry->getTerminator()->setOperand(0,
Cond);
1883 ConstraintInfo &Info,
1885 const auto &Value2Index = Info.getValue2Index(
C.IsSigned);
1886 auto It = Value2Index.find(V);
1887 if (It == Value2Index.end() ||
1889 [Id = It->second](
const Entry &
E) { return E.Id == Id; }))
1895 Value2Index, NewVariables);
1896 return NewVariables.
empty() ? Row : RowTy();
1901 ConstraintInfo &Info) {
1904 auto TryWithConstraint = [&](
const ConstraintTy &R) -> std::optional<bool> {
1907 return std::nullopt;
1910 auto &CSToUse = Info.getCS(R.IsSigned);
1911 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1913 return std::nullopt;
1915 dbgs() <<
"Condition ";
1917 *ImpliedCondition ? Pred
1920 dbgs() <<
" implied by dominating constraints\n";
1923 return ImpliedCondition;
1925 return std::nullopt;
1930 auto TryWithLinkedDecomposition =
1931 [&](
const ConstraintTy &
C) -> std::optional<bool> {
1933 return std::nullopt;
1935 auto &CS = Info.getCS(
C.IsSigned);
1936 unsigned NumVars = Info.getValue2Index(
C.IsSigned).size();
1937 unsigned NumPushed = 0;
1942 if (Row.empty() || Negated.empty())
1944 NumPushed += CS.
addRow(Row, NumVars);
1945 NumPushed += CS.
addRow(Negated, NumVars);
1948 return std::nullopt;
1950 std::optional<bool> Res = TryWithConstraint(
C);
1956 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1957 if (
auto ImpliedCondition = TryWithConstraint(R))
1958 return ImpliedCondition;
1959 if (
auto ImpliedCondition = TryWithLinkedDecomposition(R))
1960 return ImpliedCondition;
1968 if (NewVariables.
empty() && !SR.empty() && Info.isKnownNonNegative(
A) &&
1969 Info.isKnownNonNegative(
B))
1970 if (
auto ImpliedCondition = TryWithConstraint(SR))
1971 return ImpliedCondition;
1977 const auto &Value2Index = Info.getValue2Index(
true);
1978 if (!Value2Index.contains(
A) && !Value2Index.contains(
B))
1979 return std::nullopt;
1982 auto SR = Info.getConstraint(Pred,
A,
B, NewVariables,
1984 if (NewVariables.
empty()) {
1985 if (
auto ImpliedCondition = TryWithConstraint(SR))
1986 return ImpliedCondition;
1987 if (
auto ImpliedCondition = TryWithLinkedDecomposition(SR))
1988 return ImpliedCondition;
1991 return std::nullopt;
1996 ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
2000 auto ReplaceCmpWithConstant = [&](
Instruction *CheckInst,
bool IsTrue) {
2002 ReproducerCondStack, Info, DT);
2007 auto *DTN = DT.
getNode(UserI->getParent());
2010 if (UserI->getParent() == ContextInst->
getParent() &&
2011 UserI->comesBefore(ContextInst))
2017 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
2026 for (
auto *DVR : DVRUsers) {
2027 auto *DTN = DT.
getNode(DVR->getParent());
2031 auto *MarkedI = DVR->getInstruction();
2032 if (MarkedI->getParent() == ContextInst->
getParent() &&
2033 MarkedI->comesBefore(ContextInst))
2036 DVR->replaceVariableLocationOp(CheckInst, ConstantC);
2046 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
2053 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
2062 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
2071 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
2074 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
2083 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
2093 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
2111 Value *
Sub = Builder.CreateSub(
A,
B,
"",
true,
2112 Info.isKnownNonNegative(
A));
2114 Sub->takeName(USub);
2121 Module *ReproducerModule,
2124 Info.getDecomposeCache().clear();
2125 Info.popLastConstraint(
E.IsSigned);
2127 auto &Mapping = Info.getValue2Index(
E.IsSigned);
2128 for (
Value *V :
E.ValuesToRelease)
2130 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
2132 if (ReproducerModule)
2139 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
2148 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
2156 unsigned OldSize = DFSInStack.
size();
2159 while (OldSize < DFSInStack.
size()) {
2160 StackEntry
E = DFSInStack.
back();
2168 while (!Worklist.empty()) {
2169 Value *Val = Worklist.pop_back_val();
2177 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
2182 Worklist.push_back(
LHS);
2183 Worklist.push_back(
RHS);
2186 if (OldSize == DFSInStack.
size())
2191 [[maybe_unused]]
bool Matched =
2193 assert(Matched &&
"expected icmp-like match");
2195 if (
auto ImpliedCondition =
checkCondition(Pred,
A,
B, CmpToCheck, Info)) {
2196 if (IsOr == *ImpliedCondition)
2209 unsigned NumIn,
unsigned NumOut,
2210 SmallVectorImpl<StackEntry> &DFSInStack) {
2211 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
2214 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
2216 tightenBoundUsingNe(
A,
B, NumIn, NumOut, DFSInStack);
2219void ConstraintInfo::tightenBoundUsingNe(
2221 SmallVectorImpl<StackEntry> &DFSInStack) {
2222 if (!
A->getType()->isIntOrPtrTy())
2225 for (
bool IsSigned : {
false,
true}) {
2232 const auto &Value2Index = getValue2Index(IsSigned);
2234 [&Value2Index](
const DecompEntry &
E) {
2235 return !Value2Index.contains(
E.Variable);
2246 if (!doesHold(NonStrict,
A,
B))
2252 dbgs() <<
"' using inequality\n");
2253 addFactImpl(
Strict,
A,
B, NumIn, NumOut, DFSInStack,
2261 unsigned NumIn,
unsigned NumOut,
2262 SmallVectorImpl<StackEntry> &DFSInStack,
2263 bool ForceSignedSystem) {
2265 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
2268 if (
R.empty() ||
R.isNe())
2271 auto &CSToUse = getCS(
R.IsSigned);
2274 if (!
R.isEq() && NewVariables.
empty() &&
2275 CSToUse.isImpliedBySingleRow(
R.Coefficients))
2279 bool Added = CSToUse.addRow(
R.Coefficients,
R.NumVars);
2283 DecomposeCache.
clear();
2287 SmallVector<Value *, 2> ValuesToRelease;
2288 auto &Value2Index = getValue2Index(
R.IsSigned);
2289 for (
Value *V : NewVariables) {
2290 Value2Index.try_emplace(V, Value2Index.size() + 1);
2295 dbgs() <<
" constraint: ";
2301 std::move(ValuesToRelease));
2304 for (
Value *V : NewVariables) {
2306 CSToUse.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(V))},
2307 Value2Index.size());
2309 SmallVector<Value *, 2>());
2315 for (Entry &
E :
R.Coefficients)
2318 CSToUse.addRow(
R.Coefficients,
R.NumVars);
2321 SmallVector<Value *, 2>());
2331 Value *Res =
nullptr;
2335 Res = Builder.CreateNoWrapBinOp(
II->getBinaryOp(),
II->getLHS(),
2342 U->replaceAllUsesWith(Builder.getFalse());
2347 if (U->use_empty()) {
2355 if (
II->use_empty()) {
2357 for (
Use &Arg :
II->args())
2380 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
2381 State S(DT, LI, SE, TLI);
2382 std::unique_ptr<Module> ReproducerModule(
2401 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
2402 auto HasNoConstOp = [](const FactOrCheck &B) {
2403 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
2404 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
2405 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
2409 if (
A.NumIn ==
B.NumIn) {
2410 if (A.isConditionFact() && B.isConditionFact()) {
2411 bool NoConstOpA = HasNoConstOp(A);
2412 bool NoConstOpB = HasNoConstOp(B);
2413 return NoConstOpA < NoConstOpB;
2415 if (
A.isConditionFact())
2417 if (
B.isConditionFact())
2419 auto *InstA =
A.getContextInst();
2420 auto *InstB =
B.getContextInst();
2421 return InstA->comesBefore(InstB);
2423 return A.NumIn <
B.NumIn;
2426 SmallVector<Instruction *>
ToRemove;
2431 for (FactOrCheck &CB : S.WorkList) {
2434 while (!DFSInStack.
empty()) {
2435 auto &
E = DFSInStack.
back();
2438 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
2440 if (CB.NumOut <=
E.NumOut)
2443 dbgs() <<
"Removing ";
2445 Info.getValue2Index(
E.IsSigned));
2457 Instruction *Inst = CB.getInstructionToSimplify();
2464 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
2470 Pred,
A,
B, Inst, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
2471 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
2475 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
2490 auto AddFact = [&](CmpPredicate Pred,
Value *
A,
Value *
B) {
2496 <<
"Skip adding constraint because system has too many rows.\n");
2500 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
2501 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
2510 CB.NumIn, CB.NumOut, DFSInStack);
2512 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
2526 SmallPtrSet<Value *, 4> Seen;
2527 while (!Worklist.
empty()) {
2530 if (!BO || BO->getOpcode() !=
Opc)
2532 for (
Value *
Op : {BO->getOperand(0), BO->getOperand(1)}) {
2536 Info.addFact(Pred,
Op,
B, CB.NumIn, CB.NumOut, DFSInStack);
2541 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
2544 for (
unsigned I = 0,
2545 E = (DFSInStack.
size() - ReproducerCondStack.
size());
2547 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
2553 if (!CB.isConditionFact()) {
2559 ConstantInt::get(CB.Inst->getType(), 0));
2565 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
2566 AddFact(Pred, MinMax, MinMax->getLHS());
2567 AddFact(Pred, MinMax, MinMax->getRHS());
2571 switch (USatI->getIntrinsicID()) {
2574 case Intrinsic::uadd_sat:
2575 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2576 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2578 case Intrinsic::usub_sat:
2579 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2586 if (BO->getOpcode() == Instruction::URem) {
2593 if (BO->getOpcode() == Instruction::UDiv) {
2598 if (BO->getOpcode() == Instruction::LShr) {
2603 if (BO->getOpcode() == Instruction::SRem) {
2604 Value *
X = BO->getOperand(0);
2605 Value *
N = BO->getOperand(1);
2623 if (BO->getOpcode() == Instruction::SDiv) {
2624 Value *
X = BO->getOperand(0);
2625 Value *
N = BO->getOperand(1);
2626 if (!
Info.isKnownNonNegative(
X) || !
Info.isKnownPositive(
N))
2629 bool IsStrict =
Info.isKnownPositive(
X) &&
2631 ConstantInt::get(
N->getType(), 1));
2638 auto &
DL =
F.getDataLayout();
2639 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2644 DL.getTypeStoreSize(AccessType).getFixedValue(), Pred,
A,
B,
DL,
2646 AddFact(Pred,
A,
B);
2650 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2654 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2659 if (CB.isConditionFact()) {
2660 Pred = CB.Cond.Pred;
2664 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2666 dbgs() <<
"Not adding fact ";
2668 dbgs() <<
" because precondition ";
2671 dbgs() <<
" does not hold.\n";
2676 [[maybe_unused]]
bool Matched =
2680 "Must have an assume intrinsic with a icmp like operand");
2682 AddFact(Pred,
A,
B);
2685 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2687 raw_string_ostream StringS(S);
2688 ReproducerModule->print(StringS,
nullptr);
2689 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2690 Rem <<
ore::NV(
"module") << S;
2695 unsigned SignedEntries =
2696 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2697 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2698 DFSInStack.
size() - SignedEntries &&
2699 "updates to CS and DFSInStack are out of sync");
2700 assert(
Info.getCS(
true).size() == SignedEntries &&
2701 "updates to CS and DFSInStack are out of sync");
2705 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 eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, ScalarEvolution *SE, OptimizationRemarkEmitter &ORE, TargetLibraryInfo &TLI)
static bool canStrengthenFlags(Instruction *I)
Returns true if I is a candidate whose poison-generating flags may be strengthened using the constrai...
static bool doesHoldInRange(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 RowTy getDecompositionLinkRow(Value *V, const ConstraintTy &C, ConstraintInfo &Info, const DataLayout &DL)
If V is a variable in the system and constraint C does not contain V, we managed to decompose V at th...
static int64_t MinSignedConstraintValue
static bool tryToSimplifyOverflowMath(WithOverflowInst *II, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
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 isKnownNoWrap(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, unsigned NoWrapFlags, ConstraintInfo &Info, bool Signed)
Returns true if Opcode applied to Op0 and Op1 with NoWrapFlags is known to not wrap in signed or unsi...
static bool mayLookThrough(Value *V)
Returns true if V is an operation decomposeImpl can look through.
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 Decomposition decompose(Value *V, ConstraintInfo &Info, bool IsSigned, const DataLayout &DL)
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 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 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 replaceOverflowUses(WithOverflowInst *II, SmallVectorImpl< Instruction * > &ToRemove)
Replace the uses of II, which is known not to overflow, by the corresponding plain binary operation a...
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 Instruction * findCommonDominatorOfUses(Instruction &I, DominatorTree &DT)
Returns the closest program point dominating all uses of I.
static Decomposition decomposeImpl(Value *V, ConstraintInfo &Info, bool IsSigned, const DataLayout &DL)
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 Decomposition decomposeGEP(GEPOperator &GEP, ConstraintInfo &Info, bool IsSigned, const DataLayout &DL)
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
This file defines the PointerIntPair class.
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 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.
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.
PointerIntPair - This class implements a pair of a pointer and small integer.
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 * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEVFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
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...
Represents an op.with.overflow intrinsic.
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...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ 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.