55#define DEBUG_TYPE "constraint-elimination"
57STATISTIC(NumCondsRemoved,
"Number of instructions removed");
59 "Controls which conditions are eliminated");
67 UserI = Phi->getIncomingBlock(U)->getTerminator();
76 for (
Use &U :
I.uses()) {
140 FactOrCheck(EntryTy Ty,
DomTreeNode *DTN, Instruction *Inst,
141 Instruction *ContextInst =
nullptr)
142 : Inst(Inst), ContextInst(ContextInst ? ContextInst : Inst),
143 NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()), Ty(Ty) {}
146 :
U(
U), ContextInst(nullptr), NumIn(DTN->getDFSNumIn()),
147 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::UseCheck) {}
151 :
Cond(
Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
152 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
154 static FactOrCheck getConditionFact(
DomTreeNode *DTN, CmpPredicate
Pred,
157 return FactOrCheck(DTN,
Pred, Op0, Op1, Precond);
160 static FactOrCheck getInstFact(
DomTreeNode *DTN, Instruction *Inst) {
161 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
164 static FactOrCheck getCheck(
DomTreeNode *DTN, Use *U) {
165 return FactOrCheck(DTN, U);
168 static FactOrCheck getCheck(
DomTreeNode *DTN, Instruction *
I,
169 Instruction *ContextInst =
nullptr) {
171 "anchoring instruction must be in DTN's block");
172 return FactOrCheck(EntryTy::InstCheck, DTN,
I, ContextInst);
175 bool isCheck()
const {
176 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
180 assert(!isConditionFact());
181 if (Ty == EntryTy::UseCheck)
188 if (Ty == EntryTy::InstCheck)
194 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
199struct MonotonicInfo {
201 bool Decreasing =
false;
203 bool Unsigned =
false;
214 TargetLibraryInfo &TLI;
217 State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution *SE,
218 TargetLibraryInfo &TLI)
219 : DT(DT), LI(LI), SE(SE), TLI(TLI) {}
222 void addInfoFor(BasicBlock &BB);
226 void addBoundsForHeaderInductions(BasicBlock &BB);
230 void addInfoForInductions(BasicBlock &BB);
234 MonotonicInfo getMonotonicityInfo(PHINode &PN,
Value *Step);
238 bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ)
const {
239 return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
248 bool IsSigned =
false;
251 SmallVector<Value *, 2> ValuesToRelease;
253 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
254 SmallVector<Value *, 2> ValuesToRelease)
255 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
256 ValuesToRelease(std::
move(ValuesToRelease)) {}
263 unsigned NumVars = 0;
265 bool IsSigned =
false;
267 ConstraintTy() =
default;
269 ConstraintTy(RowTy Coefficients,
unsigned NumVars,
bool IsSigned,
bool IsEq,
271 : Coefficients(std::
move(Coefficients)), NumVars(NumVars),
272 IsSigned(IsSigned), IsEq(IsEq), IsNe(IsNe) {}
274 bool empty()
const {
return Coefficients.empty(); }
276 bool isEq()
const {
return IsEq; }
278 bool isNe()
const {
return IsNe; }
285 std::optional<bool> isImpliedBy(
const ConstraintSystem &CS)
const;
297 DecompEntry(int64_t Coefficient,
Value *Variable)
298 : Coefficient(Coefficient), Variable(Variable) {}
302struct Decomposition {
306 Decomposition(int64_t Offset) : Offset(Offset) {}
307 Decomposition(
Value *
V) { Vars.emplace_back(1,
V); }
309 : Offset(Offset), Vars(Vars) {}
313 [[nodiscard]]
bool add(int64_t OtherOffset) {
319 [[nodiscard]]
bool add(
const Decomposition &
Other) {
328 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
329 Decomposition Tmp =
Other;
340 [[nodiscard]]
bool mul(int64_t Factor) {
343 for (
auto &Var : Vars)
344 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
356class ConstraintInfo {
358 ConstraintSystem UnsignedCS;
359 ConstraintSystem SignedCS;
361 const DataLayout &DL;
365 DenseMap<PointerIntPair<Value *, 1, bool>, Decomposition> DecomposeCache;
368 DenseMap<PointerIntPair<Value *, 1, bool>, Decomposition> &
369 getDecomposeCache() {
370 return DecomposeCache;
374 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
375 auto &Value2Index = getValue2Index(
false);
377 for (
Value *Arg : FunctionArgs)
378 UnsignedCS.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(Arg))},
382 DenseMap<Value *, unsigned> &getValue2Index(
bool Signed) {
383 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
385 const DenseMap<Value *, unsigned> &getValue2Index(
bool Signed)
const {
386 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
389 ConstraintSystem &getCS(
bool Signed) {
390 return Signed ? SignedCS : UnsignedCS;
392 const ConstraintSystem &getCS(
bool Signed)
const {
393 return Signed ? SignedCS : UnsignedCS;
396 void popLastConstraint(
bool Signed) {
397 assert(DecomposeCache.empty() &&
"Cache must be cleared");
398 getCS(
Signed).popLastConstraint();
400 void popLastNVariables(
bool Signed,
unsigned N) {
401 assert(DecomposeCache.empty() &&
"Cache must be cleared");
402 getCS(
Signed).popLastNVariables(
N);
412 function_ref<std::optional<bool>()> Solve);
430 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
437 SmallVectorImpl<Value *> &NewVariables,
438 bool ForceSignedSystem =
false);
453 unsigned NumIn,
unsigned NumOut,
454 SmallVectorImpl<StackEntry> &DFSInStack);
461 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
462 bool ForceSignedSystem);
466 void tightenBoundUsingNe(
Value *
A,
Value *
B,
unsigned NumIn,
unsigned NumOut,
467 SmallVectorImpl<StackEntry> &DFSInStack);
473 APInt ConstantOffset;
474 SmallMapVector<Value *, APInt, 4> VariableOffsets;
479 OffsetResult(GEPOperator &
GEP,
const DataLayout &
DL)
481 ConstantOffset = APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
491 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
493 Result.ConstantOffset))
501 bool CanCollectInner = InnerGEP->collectOffset(
502 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
504 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
505 VariableOffsets2.
size() > 1 ||
506 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
512 bool Overflow =
false;
513 APInt CombinedOffset =
514 Result.ConstantOffset.sadd_ov(ConstantOffset2, Overflow);
518 Result.BasePtr = InnerGEP->getPointerOperand();
519 Result.ConstantOffset = CombinedOffset;
520 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
521 Result.VariableOffsets = std::move(VariableOffsets2);
522 Result.NW &= InnerGEP->getNoWrapFlags();
527static Decomposition
decompose(
Value *
V, ConstraintInfo &Info,
bool IsSigned,
543 int64_t RequiredOffset = -
static_cast<int64_t
>(Slack.
getZExtValue());
545 const auto &Value2Index = Info.getValue2Index(
Signed);
546 unsigned OpIdx = Value2Index.lookup(
Op);
550 int64_t OpCoefficient =
Upper ? 1 : -1;
551 unsigned OpSize =
Op->getType()->getScalarSizeInBits();
555 if (Row.size() != 3 || Row[0].Id != 0 ||
556 Row[0].Coefficient > RequiredOffset)
558 bool OpFirst = Row[1].Id == OpIdx;
559 const Entry &OpE = Row[OpFirst ? 1 : 2];
560 const Entry &WitnessE = Row[OpFirst ? 2 : 1];
561 if (OpE.Id != OpIdx || OpE.Coefficient != OpCoefficient ||
562 WitnessE.Coefficient != -OpCoefficient)
566 Value2Index, [&](
const auto &KV) {
return KV.second == WitnessE.Id; });
567 assert(Witness != Value2Index.end() &&
"row variables must be mapped");
568 Type *WitnessTy = Witness->first->getType();
579 if (R.isEmptySet() || (
Signed ? R.isSignWrappedSet() : R.isWrappedSet()))
585 unsigned BitWidth = R.getBitWidth();
586 APInt Min =
Signed ? R.getSignedMin() : R.getUnsignedMin();
587 APInt Max =
Signed ? R.getSignedMax() : R.getUnsignedMax();
593 APInt UpperSlack = MaxVal - Max;
601 ConstantInt::get(Ty, Min)) &&
606 ConstantInt::get(Ty, Max)) &&
615 unsigned NoWrapFlags, ConstraintInfo &Info,
619 if (NoWrapFlags & (
Signed ? OBO::NoSignedWrap : OBO::NoUnsignedWrap))
622 if (Opcode == Instruction::Sub) {
628 if (Info.isKnownNonNegative(Op1) &&
634 if (
Signed && Opcode == Instruction::Add) {
635 std::optional<bool> Op0Sign =
636 Info.getKnownSign(Op0,
false);
637 std::optional<bool> Op1Sign =
638 Info.getKnownSign(Op1,
false);
639 if (Op0Sign && Op1Sign && *Op0Sign != *Op1Sign)
643 if (!
Signed && (NoWrapFlags & OBO::NoSignedWrap) &&
644 (Opcode == Instruction::Shl || Info.isKnownNonNegative(Op1)) &&
645 Info.isKnownNonNegative(Op0))
656 Opcode,
C->getValue(),
657 Signed ? OBO::NoSignedWrap : OBO::NoUnsignedWrap),
668 return isKnownNoWrap(WO->getBinaryOp(), WO->getLHS(), WO->getRHS(),
673 return Trunc->hasNoSignedWrap();
677 return Trunc->hasNoUnsignedWrap() ||
678 (Trunc->hasNoSignedWrap() &&
679 Info.isKnownNonNegative(Trunc->getOperand(0)));
685 BO->getOperand(0), BO->getOperand(1),
686 BO->getNoWrapKind(), Info,
Signed);
693 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
696 assert(!IsSigned &&
"The logic below only supports decomposition for "
697 "unsigned predicates at the moment.");
698 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
707 if (!NW.hasNoUnsignedSignedWrap() && ConstantOffset.isNegative())
710 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
711 for (
auto [Index, Scale] : VariableOffsets) {
714 if (Index->getType()->getScalarSizeInBits() != Scale.getBitWidth())
716 if (!NW.hasNoUnsignedWrap()) {
719 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
720 if (!Info.isKnownNonNegative(Index))
722 }
else if (!NW.hasNoUnsignedSignedWrap()) {
725 if (Scale.isNegative())
729 auto IdxResult =
decompose(Index, Info, IsSigned,
DL);
730 if (IdxResult.mul(Scale.getSExtValue()))
732 if (Result.add(IdxResult))
752 switch (
Op->getOpcode()) {
753 case Instruction::GetElementPtr:
754 case Instruction::Add:
755 case Instruction::Sub:
756 case Instruction::Mul:
757 case Instruction::Shl:
758 case Instruction::LShr:
759 case Instruction::AShr:
760 case Instruction::ZExt:
761 case Instruction::SExt:
762 case Instruction::Trunc:
763 case Instruction::Or:
764 case Instruction::Xor:
777 auto &Cache = Info.getDecomposeCache();
778 auto It = Cache.find(
Key);
779 if (It != Cache.end())
783 Info.getDecomposeCache().insert({
Key, Result});
789 auto MergeResults = [&Info, IsSigned,
791 bool IsSignedB) -> std::optional<Decomposition> {
799 Type *Ty =
V->getType()->getScalarType();
800 if (Ty->isPointerTy() && !IsSigned) {
812 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
818 return CI->getSExtValue();
820 return int64_t(CI->getZExtValue());
836 if (!IsSigned && !Info.isKnownNonNegative(Op0))
840 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64 &&
842 V = Trunc->getOperand(0);
847 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
857 if (
auto Decomp = MergeResults(Op0, CI,
true))
864 Decomposition Result(-1);
865 if (!Result.sub(
decompose(Op0, Info, IsSigned,
DL)))
895 (IsSigned == IsAShr || Info.isKnownNonNegative(Op0))) {
898 if (Result.Offset % Factor == 0 &&
899 all_of(Result.Vars, [Factor](
const DecompEntry &
E) {
900 return E.Coefficient % Factor == 0;
902 Result.Offset /= Factor;
903 for (
auto &
E : Result.Vars)
904 E.Coefficient /= Factor;
915 int64_t MaxShift = IsSigned ? Ty->getIntegerBitWidth() - 1 : 63;
933 const Decomposition &BDec,
939 if (
SubOverflow(BDec.Offset, ADec.Offset, OffsetSum))
941 RowTy R(1, Entry(OffsetSum, 0));
942 auto GetCoefficient = [&R](
unsigned Idx) -> int64_t & {
947 if (
I == R.end() ||
I->Id != Idx)
948 I = R.insert(
I, Entry(0, Idx));
949 return I->Coefficient;
953 auto GetOrAddIndex = [&Value2Index, &NewVariables](
Value *
V) ->
unsigned {
954 auto V2I = Value2Index.
find(
V);
955 if (V2I != Value2Index.
end())
957 unsigned Idx =
find(NewVariables,
V) - NewVariables.
begin();
958 if (Idx == NewVariables.
size())
960 return Value2Index.
size() + Idx + 1;
962 for (
const DecompEntry &KV : ADec.Vars)
963 GetCoefficient(GetOrAddIndex(KV.Variable)) += KV.Coefficient;
965 for (
const DecompEntry &KV : BDec.Vars) {
966 auto &Coeff = GetCoefficient(GetOrAddIndex(KV.Variable));
972 erase_if(R, [](
const Entry &
E) {
return E.Id != 0 &&
E.Coefficient == 0; });
979 bool ForceSignedSystem) {
980 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
982 "signed system can only be forced on eq/ne");
1023 auto &Value2Index = getValue2Index(IsSigned);
1033 if (
AddOverflow(R[0].Coefficient, int64_t(-1), R[0].Coefficient))
1037 unsigned NumV2I = Value2Index.size();
1038 NewVariables.
truncate(
R.back().Id > NumV2I ?
R.back().Id - NumV2I : 0);
1040 return ConstraintTy(std::move(R), Value2Index.size() + NewVariables.
size(),
1041 IsSigned, IsEq, IsNe);
1052 return ConstraintTy(RowTy(1,
Entry(0, 0)), 0,
1053 false,
false,
false);
1065 ConstraintTy
R = getConstraint(
Pred, Op0, Op1, NewVariables);
1066 if (!NewVariables.
empty())
1072ConstraintTy::isImpliedBy(
const ConstraintSystem &CS)
const {
1073 const auto &[SubCS, NewCoefficients] = CS.
getSubSystem(Coefficients);
1074 bool IsConditionImplied = SubCS.isConditionImplied(NewCoefficients);
1078 bool IsNegatedOrEqualImplied =
1079 !NegatedOrEqual.empty() && SubCS.isConditionImplied(NegatedOrEqual);
1084 if (IsConditionImplied && IsNegatedOrEqualImplied)
1088 bool IsNegatedImplied =
1089 !Negated.empty() && SubCS.isConditionImplied(Negated);
1092 bool IsStrictLessThanImplied =
1093 !StrictLessThan.empty() && SubCS.isConditionImplied(StrictLessThan);
1099 if (IsNegatedImplied || IsStrictLessThanImplied)
1102 return std::nullopt;
1105 if (IsConditionImplied)
1109 auto IsNegatedImplied = !Negated.empty() && SubCS.isConditionImplied(Negated);
1110 if (IsNegatedImplied)
1114 return std::nullopt;
1118 ConstraintInfo &Info,
1119 const DataLayout &
DL);
1122ConstraintInfo::tryWithLinkRows(
Value *
A,
Value *
B,
const ConstraintTy &
C,
1123 function_ref<std::optional<bool>()> Solve) {
1124 if (std::optional<bool> Res = Solve())
1127 return std::nullopt;
1129 auto &CS = getCS(
C.IsSigned);
1130 unsigned NumVars = getValue2Index(
C.IsSigned).size();
1131 unsigned NumPushed = 0;
1135 if (Row.empty() || Negated.empty())
1137 NumPushed += CS.
addRow(Row, NumVars);
1138 NumPushed += CS.
addRow(Negated, NumVars);
1141 return std::nullopt;
1143 unsigned NumRows = CS.
size();
1145 std::optional<bool> Res = Solve();
1146 assert(CS.
size() == NumRows &&
"rows added while link rows are pushed");
1153 auto R = getConstraintForSolving(
Pred,
A,
B);
1156 auto &CS = getCS(
R.IsSigned);
1157 return tryWithLinkRows(
A,
B, R,
1158 [&]() -> std::optional<bool> {
1161 return std::nullopt;
1166bool ConstraintInfo::isKnownNonNegative(
Value *
V) {
1168 return !CI->isNegative();
1169 return ::isKnownNonNegative(
V,
DL) ||
1173bool ConstraintInfo::isKnownPositive(
Value *
V) {
1175 return CI->getValue().isStrictlyPositive();
1176 return ::isKnownPositive(
V,
DL) ||
1180std::optional<bool> ConstraintInfo::getKnownSign(
Value *
V,
1181 bool StrictlyNegative) {
1183 if (
Known.isNonNegative())
1185 if (StrictlyNegative ?
Known.isNegative() :
Known.isNonPositive())
1191 if (doesHold(NegativePred,
V,
Zero))
1193 return std::nullopt;
1196void ConstraintInfo::transferToOtherSystem(
1198 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
1201 if (!
A->getType()->isIntegerTy())
1214 NumOut, DFSInStack);
1224 NumOut, DFSInStack);
1238 NumOut, DFSInStack);
1264static std::pair<Value *, Value *>
1267 "LoopPred must be a predecessor of the phi's block");
1269 return {
nullptr,
nullptr};
1276template <
typename PhiMatchTy>
1285MonotonicInfo State::getMonotonicityInfo(PHINode &PN,
Value *Step) {
1287 const APInt *StepOffset =
nullptr;
1291 Info.Unsigned = !
Info.Decreasing &&
Add->hasNoUnsignedWrap();
1292 Info.Signed =
Add->hasNoSignedWrap();
1298 APInt GEPOffset(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
1299 Info.Unsigned =
GEP->getPointerOperand() == &PN &&
1300 (
GEP->hasNoUnsignedWrap() ||
1301 ((
GEP->hasNoUnsignedSignedWrap() &&
1302 GEP->accumulateConstantOffset(
DL, GEPOffset) &&
1303 !GEPOffset.isNegative())));
1308 if (
Info.Unsigned ||
Info.Signed || !StepOffset)
1325void State::addBoundsForHeaderInductions(BasicBlock &BB) {
1327 if (!L ||
L->getHeader() != &BB)
1334 for (PHINode &PN : BB.
phis()) {
1342 MonotonicInfo
Info = getMonotonicityInfo(PN, Step);
1346 Info.Unsigned =
false;
1347 if (!
Info.Unsigned && !
Info.Signed)
1353 if (
Info.Decreasing)
1361void State::addInfoForInductions(BasicBlock &BB) {
1368 if (Header != &BB && Latch != &BB)
1375 PHINode *PN =
nullptr;
1376 const APInt *IncStep =
nullptr;
1386 std::optional<bool> PeeledOnEdge;
1387 if (!
match(Br->getCondition(), CountingCmp)) {
1391 PeeledOnEdge =
true;
1393 PeeledOnEdge =
false;
1402 bool ContinueOnTrue =
1406 BasicBlock *InLoopSucc = Br->getSuccessor(ContinueOnTrue ? 0 : 1);
1410 if (PeeledOnEdge && *PeeledOnEdge != ContinueOnTrue)
1413 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB))
1417 if (!LoopPred || !
L->isLoopInvariant(
B))
1429 bool HasHeaderBound =
1433 if (HasHeaderBound) {
1435 WorkList.
push_back(FactOrCheck::getConditionFact(
1436 HeaderDTN, BoundPred, PN,
B,
ConditionTy(BoundPred, StartValue,
B)));
1445 if (&BB == Latch && !IncStep)
1455 WorkList.
push_back(FactOrCheck::getConditionFact(
1456 HeaderDTN, ContinuePred, PN,
B,
1462 if (ICmpInst::isSigned(ContinuePred)) {
1465 "Expected a signed less-than continuation predicate");
1466 MonotonicInfo
Info = getMonotonicityInfo(*PN, Backedge);
1467 if (
Info.Signed && !
Info.Decreasing) {
1469 WorkList.
push_back(FactOrCheck::getConditionFact(
1470 HeaderDTN, UPred, PN,
B,
ConditionTy(UPred, StartValue,
B)));
1479 const APInt *StepOffset =
nullptr;
1480 const SCEV *StartSCEV =
nullptr;
1482 if (StepOffset->
isZero())
1485 const SCEV *Expr = SE->
getSCEV(PN);
1494 if (IncStep && *IncStep != *StepOffset)
1497 MonotonicInfo
Info = getMonotonicityInfo(*PN, Backedge);
1502 if (!(-*StepOffset).isOne())
1512 ConditionTy BBeforeStartUnsigned = {UPrecond,
B, StartValue};
1518 WorkList.
push_back(FactOrCheck::getConditionFact(
1520 if (!(
Info.Decreasing &&
Info.Signed))
1521 WorkList.
push_back(FactOrCheck::getConditionFact(
1525 B, BBeforeStartUnsigned));
1527 B, BBeforeStartSigned));
1537 if (!StepOffset->
isOne()) {
1540 StartSCEV = SE->
getSCEV(StartValue);
1554 ConditionTy StartBeforeBoundUnsigned = {UPrecond, StartValue,
B};
1560 WorkList.
push_back(FactOrCheck::getConditionFact(
1563 WorkList.
push_back(FactOrCheck::getConditionFact(
1568 if (!HasHeaderBound || !canAddSuccessor(BB, InLoopSucc)) {
1569 WorkList.
push_back(FactOrCheck::getConditionFact(
1571 WorkList.
push_back(FactOrCheck::getConditionFact(
1584 L->getExitBlocks(ExitBBs);
1585 for (BasicBlock *EB : ExitBBs) {
1599 if (!
GEP.hasNoUnsignedWrap())
1604 Base = InnerGEP->getPointerOperand();
1620 if (
Offset.VariableOffsets.size() != 1)
1624 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1626 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1639 B = ConstantInt::get(Index->getType(), MaxIndex);
1647 return Trunc->getType()->isIntegerTy() && Trunc->hasNoSignedWrap() &&
1648 !Trunc->hasNoUnsignedWrap();
1651 if (!BO || !BO->getType()->isIntegerTy())
1654 switch (BO->getOpcode()) {
1655 case Instruction::Sub:
1656 if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
1661 case Instruction::Add:
1662 case Instruction::Mul:
1663 case Instruction::Shl:
1664 if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())
1683 I->setHasNoSignedWrap();
1688 I->setHasNoUnsignedWrap();
1694void State::addInfoFor(BasicBlock &BB) {
1695 addBoundsForHeaderInductions(BB);
1696 addInfoForInductions(BB);
1702 bool GuaranteedToExecute =
true;
1704 for (Instruction &
I : BB) {
1706 for (Use &U :
I.uses()) {
1708 auto *DTN = DT.
getNode(UserI->getParent());
1711 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1716 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1720 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1723 if (GuaranteedToExecute) {
1733 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1738 if (!LI->isVolatile())
1739 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1742 if (!
SI->isVolatile())
1743 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1749 case Intrinsic::assume: {
1752 if (GuaranteedToExecute) {
1759 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1764 case Intrinsic::uadd_with_overflow:
1765 case Intrinsic::sadd_with_overflow:
1766 case Intrinsic::usub_with_overflow:
1767 case Intrinsic::ssub_with_overflow:
1768 case Intrinsic::umul_with_overflow:
1769 case Intrinsic::smul_with_overflow:
1770 case Intrinsic::ucmp:
1771 case Intrinsic::scmp:
1776 case Intrinsic::umin:
1777 case Intrinsic::umax:
1778 case Intrinsic::smin:
1779 case Intrinsic::smax:
1780 case Intrinsic::usub_sat:
1785 case Intrinsic::uadd_sat:
1791 case Intrinsic::abs:
1806 if ((BO->getOpcode() == Instruction::URem ||
1807 BO->getOpcode() == Instruction::UDiv ||
1808 BO->getOpcode() == Instruction::LShr ||
1809 BO->getOpcode() == Instruction::SRem ||
1810 BO->getOpcode() == Instruction::SDiv) &&
1819 WorkList.
push_back(FactOrCheck::getCheck(
1827 for (
auto &Case :
Switch->cases()) {
1829 Value *
V = Case.getCaseValue();
1830 if (!canAddSuccessor(BB, Succ))
1859 SmallPtrSet<Value *, 8> SeenCond;
1860 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1861 if (SeenCond.
insert(
V).second)
1866 while (!CondWorkList.
empty()) {
1891 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1894 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1902 OS <<
"icmp " <<
Pred <<
' ';
1903 LHS->printAsOperand(OS,
true);
1905 RHS->printAsOperand(OS,
false);
1914struct ReproducerEntry {
1915 ICmpInst::Predicate
Pred;
1950 auto &Value2Index = Info.getValue2Index(IsSigned);
1952 while (!WorkList.
empty()) {
1956 if (Old2New.
find(
V) != Old2New.
end())
1962 if (Value2Index.contains(
V) || !
I ||
1973 for (
auto &Entry : Stack)
1976 CollectArguments(
Cond, IsSigned);
1979 for (
auto *
P : Args)
1985 Cond->getModule()->getName() +
1986 Cond->getFunction()->getName() +
"repro",
1989 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1991 Old2New[Args[
I]] =
F->getArg(
I);
1996 Builder.CreateRet(Builder.getTrue());
1997 Builder.SetInsertPoint(Entry->getTerminator());
2006 auto &Value2Index = Info.getValue2Index(IsSigned);
2007 while (!WorkList.
empty()) {
2009 if (Old2New.
find(
V) != Old2New.
end())
2013 if (!Value2Index.contains(
V) &&
I) {
2014 Old2New[
V] =
nullptr;
2024 Old2New[
I] = Cloned;
2025 Old2New[
I]->setName(
I->getName());
2037 for (
auto &Entry : Stack) {
2046 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
2047 Builder.CreateAssumption(Cmp);
2052 CloneInstructions(
Cond, IsSigned);
2053 Entry->getTerminator()->setOperand(0,
Cond);
2064 ConstraintInfo &Info,
2066 const auto &Value2Index = Info.getValue2Index(
C.IsSigned);
2067 auto It = Value2Index.find(
V);
2068 if (It == Value2Index.end() ||
2070 [Id = It->second](
const Entry &
E) { return E.Id == Id; }))
2076 Value2Index, NewVariables);
2077 return NewVariables.
empty() ? Row : RowTy();
2082 ConstraintInfo &Info) {
2085 auto TryWithConstraint = [&](
const ConstraintTy &R) -> std::optional<bool> {
2088 return std::nullopt;
2091 auto &CSToUse = Info.getCS(R.IsSigned);
2092 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
2094 return std::nullopt;
2096 dbgs() <<
"Condition ";
2098 *ImpliedCondition ?
Pred
2101 dbgs() <<
" implied by dominating constraints\n";
2104 return ImpliedCondition;
2106 return std::nullopt;
2111 auto TryWithLinkedDecomposition =
2112 [&](
const ConstraintTy &
C) -> std::optional<bool> {
2113 return Info.tryWithLinkRows(
A,
B,
C, [&] {
return TryWithConstraint(
C); });
2116 auto R = Info.getConstraintForSolving(
Pred,
A,
B);
2117 if (
auto ImpliedCondition = TryWithLinkedDecomposition(R))
2118 return ImpliedCondition;
2126 if (NewVariables.
empty() && !SR.empty() && Info.isKnownNonNegative(
A) &&
2127 Info.isKnownNonNegative(
B))
2128 if (
auto ImpliedCondition = TryWithConstraint(SR))
2129 return ImpliedCondition;
2135 const auto &Value2Index = Info.getValue2Index(
true);
2136 if (!Value2Index.contains(
A) && !Value2Index.contains(
B))
2137 return std::nullopt;
2140 auto SR = Info.getConstraint(
Pred,
A,
B, NewVariables,
2142 if (NewVariables.
empty()) {
2143 if (
auto ImpliedCondition = TryWithLinkedDecomposition(SR))
2144 return ImpliedCondition;
2147 return std::nullopt;
2152 ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
2156 auto ReplaceCmpWithConstant = [&](
Instruction *CheckInst,
bool IsTrue) {
2158 ReproducerCondStack, Info, DT);
2163 auto *DTN = DT.
getNode(UserI->getParent());
2166 if (UserI->getParent() == ContextInst->
getParent() &&
2167 UserI->comesBefore(ContextInst))
2173 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
2182 for (
auto *DVR : DVRUsers) {
2183 auto *DTN = DT.
getNode(DVR->getParent());
2187 auto *MarkedI = DVR->getInstruction();
2188 if (MarkedI->getParent() == ContextInst->
getParent() &&
2189 MarkedI->comesBefore(ContextInst))
2192 DVR->replaceVariableLocationOp(CheckInst, ConstantC);
2202 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
2209 return ReplaceCmpWithConstant(CheckInst, *ImpliedCondition);
2218 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
2227 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
2230 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
2239 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
2249 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
2267 Value *
Sub = Builder.CreateSub(
A,
B,
"",
true,
2268 Info.isKnownNonNegative(
A));
2270 Sub->takeName(USub);
2277 Module *ReproducerModule,
2280 Info.getDecomposeCache().clear();
2281 Info.popLastConstraint(
E.IsSigned);
2283 auto &Mapping = Info.getValue2Index(
E.IsSigned);
2284 for (
Value *
V :
E.ValuesToRelease)
2286 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
2288 if (ReproducerModule)
2295 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
2304 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
2312 unsigned OldSize = DFSInStack.
size();
2315 while (OldSize < DFSInStack.
size()) {
2316 StackEntry
E = DFSInStack.
back();
2324 while (!Worklist.empty()) {
2325 Value *Val = Worklist.pop_back_val();
2333 Info.addFact(
Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
2338 Worklist.push_back(
LHS);
2339 Worklist.push_back(
RHS);
2342 if (OldSize == DFSInStack.
size())
2347 [[maybe_unused]]
bool Matched =
2349 assert(Matched &&
"expected icmp-like match");
2352 if (IsOr == *ImpliedCondition)
2365 unsigned NumIn,
unsigned NumOut,
2366 SmallVectorImpl<StackEntry> &DFSInStack) {
2367 addFactImpl(
Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
2370 addFactImpl(
Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
2372 tightenBoundUsingNe(
A,
B, NumIn, NumOut, DFSInStack);
2375void ConstraintInfo::tightenBoundUsingNe(
2377 SmallVectorImpl<StackEntry> &DFSInStack) {
2378 if (!
A->getType()->isIntOrPtrTy())
2381 for (
bool IsSigned : {
false,
true}) {
2388 const auto &Value2Index = getValue2Index(IsSigned);
2390 [&Value2Index](
const DecompEntry &
E) {
2391 return !Value2Index.contains(
E.Variable);
2402 if (!doesHold(NonStrict,
A,
B))
2408 dbgs() <<
"' using inequality\n");
2409 addFactImpl(
Strict,
A,
B, NumIn, NumOut, DFSInStack,
2417 unsigned NumIn,
unsigned NumOut,
2418 SmallVectorImpl<StackEntry> &DFSInStack,
2419 bool ForceSignedSystem) {
2421 auto R = getConstraint(
Pred,
A,
B, NewVariables, ForceSignedSystem);
2424 if (
R.empty() ||
R.isNe())
2427 auto &CSToUse = getCS(
R.IsSigned);
2431 if (!
R.isEq() && NewVariables.
empty()) {
2433 if (CSToUse.isImpliedBySingleRow(
R.Coefficients))
2438 bool Added = CSToUse.addRow(
R.Coefficients,
R.NumVars);
2442 DecomposeCache.
clear();
2446 SmallVector<Value *, 2> ValuesToRelease;
2447 auto &Value2Index = getValue2Index(
R.IsSigned);
2448 for (
Value *
V : NewVariables) {
2449 Value2Index.try_emplace(
V, Value2Index.size() + 1);
2454 dbgs() <<
" constraint: ";
2460 std::move(ValuesToRelease));
2463 for (
Value *
V : NewVariables) {
2465 CSToUse.addRow({
Entry(0, 0),
Entry(-1, Value2Index.at(
V))},
2466 Value2Index.size());
2468 SmallVector<Value *, 2>());
2474 for (Entry &
E :
R.Coefficients)
2477 CSToUse.addRow(
R.Coefficients,
R.NumVars);
2480 SmallVector<Value *, 2>());
2490 Value *Res =
nullptr;
2494 Res = Builder.CreateNoWrapBinOp(
II->getBinaryOp(),
II->getLHS(),
2506 if (U->use_empty()) {
2514 if (
II->use_empty()) {
2516 for (
Use &Arg :
II->args())
2540 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
2541 State S(DT, LI, SE,
TLI);
2542 std::unique_ptr<Module> ReproducerModule(
2543 Opts.constraint_elimination_dump_reproducers
2544 ?
new Module(
F.getName(),
F.getContext())
2563 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
2564 auto HasNoConstOp = [](const FactOrCheck &B) {
2565 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
2566 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
2567 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
2571 if (
A.NumIn ==
B.NumIn) {
2572 if (A.isConditionFact() && B.isConditionFact()) {
2573 bool NoConstOpA = HasNoConstOp(A);
2574 bool NoConstOpB = HasNoConstOp(B);
2575 return NoConstOpA < NoConstOpB;
2577 if (
A.isConditionFact())
2579 if (
B.isConditionFact())
2581 auto *InstA =
A.getContextInst();
2582 auto *InstB =
B.getContextInst();
2583 return InstA->comesBefore(InstB);
2585 return A.NumIn <
B.NumIn;
2588 SmallVector<Instruction *>
ToRemove;
2593 for (FactOrCheck &CB : S.WorkList) {
2596 while (!DFSInStack.
empty()) {
2597 auto &
E = DFSInStack.
back();
2600 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
2602 if (CB.NumOut <=
E.NumOut)
2605 dbgs() <<
"Removing ";
2607 Info.getValue2Index(
E.IsSigned));
2619 Instruction *Inst = CB.getInstructionToSimplify();
2626 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
2632 Pred,
A,
B, Inst, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
2633 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
2637 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
2656 Opts.constraint_elimination_max_rows) {
2659 <<
"Skip adding constraint because system has too many rows.\n");
2663 Info.addFact(
Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
2664 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
2671 if (
Pred.hasSameSign()) {
2673 CB.NumIn, CB.NumOut, DFSInStack);
2676 if (
A->getType()->isIntegerTy()) {
2677 std::optional<bool> ASign =
2678 Info.getKnownSign(
A,
true);
2679 std::optional<bool> BSign =
2680 Info.getKnownSign(
B,
true);
2681 if (ASign.has_value() != BSign.has_value()) {
2682 bool IsNegative = ASign ? *ASign : *BSign;
2683 Value *OtherOp = ASign ?
B :
A;
2686 CB.NumIn, CB.NumOut, DFSInStack);
2690 Info.transferToOtherSystem(
Pred,
A,
B, CB.NumIn, CB.NumOut,
2705 SmallPtrSet<Value *, 4> Seen;
2706 while (!Worklist.
empty()) {
2709 if (!BO || BO->getOpcode() !=
Opc)
2711 for (
Value *
Op : {BO->getOperand(0), BO->getOperand(1)}) {
2715 Info.addFact(
Pred,
Op,
B, CB.NumIn, CB.NumOut, DFSInStack);
2720 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
2723 for (
unsigned I = 0,
2724 E = (DFSInStack.
size() - ReproducerCondStack.
size());
2726 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
2732 if (!CB.isConditionFact()) {
2738 ConstantInt::get(CB.Inst->getType(), 0));
2744 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
2745 AddFact(
Pred, MinMax, MinMax->getLHS());
2746 AddFact(
Pred, MinMax, MinMax->getRHS());
2750 switch (USatI->getIntrinsicID()) {
2753 case Intrinsic::uadd_sat:
2754 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2755 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2757 case Intrinsic::usub_sat:
2758 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2765 if (BO->getOpcode() == Instruction::URem) {
2772 if (BO->getOpcode() == Instruction::UDiv) {
2777 if (BO->getOpcode() == Instruction::LShr) {
2782 if (BO->getOpcode() == Instruction::SRem) {
2783 Value *
X = BO->getOperand(0);
2784 Value *
N = BO->getOperand(1);
2802 if (BO->getOpcode() == Instruction::SDiv) {
2803 Value *
X = BO->getOperand(0);
2804 Value *
N = BO->getOperand(1);
2805 if (!
Info.isKnownNonNegative(
X) || !
Info.isKnownPositive(
N))
2808 bool IsStrict =
Info.isKnownPositive(
X) &&
2810 ConstantInt::get(
N->getType(), 1));
2817 auto &
DL =
F.getDataLayout();
2818 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2823 DL.getTypeStoreSize(AccessType).getFixedValue(),
Pred,
A,
B,
DL,
2829 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2833 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2838 if (CB.isConditionFact()) {
2839 Pred = CB.Cond.Pred;
2843 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2845 dbgs() <<
"Not adding fact ";
2847 dbgs() <<
" because precondition ";
2850 dbgs() <<
" does not hold.\n";
2855 [[maybe_unused]]
bool Matched =
2859 "Must have an assume intrinsic with a icmp like operand");
2864 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2866 raw_string_ostream StringS(S);
2867 ReproducerModule->print(StringS,
nullptr);
2868 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2869 Rem <<
ore::NV(
"module") << S;
2874 unsigned SignedEntries =
2875 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2876 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2877 DFSInStack.
size() - SignedEntries &&
2878 "updates to CS and DFSInStack are out of sync");
2879 assert(
Info.getCS(
true).size() == SignedEntries &&
2880 "updates to CS and DFSInStack are out of sync");
2884 I->eraseFromParent();
const TargetLowering & TLI
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 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 hasLimitWitness(const ConstraintInfo &Info, Value *Op, const APInt &Slack, bool Signed, bool Upper)
Returns true if Op <= MaxVal - Slack holds in the system for Signed, by scanning it for a row of the ...
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.
static std::optional< bool > getKnownSign(Value *Op, const SimplifyQuery &SQ)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
uint64_t IntrinsicInst * II
This file defines the PointerIntPair class.
static StringRef getName(Value *V)
SmallVector< MachineOperand, 4 > 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.
uint64_t getZExtValue() const
Get zero extended value.
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.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
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 isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
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.
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.
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
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)
unsigned size() const
Returns the number of rows in the constraint system.
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.
static LLVM_ABI void normalizeByGCD(MutableArrayRef< Entry > R)
Divide the variable coefficients of R by their greatest common divisor G and round the constant down ...
LLVM_ABI bool isConditionImpliedInSubSystem(ArrayRef< Entry > R) const
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.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
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)
BinOpPred_match< LHS, RHS, is_right_shift_op > m_Shr(const LHS &L, const RHS &R)
Matches logical shift operations.
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.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
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))
Exact_match< T > m_Exact(const T &SubPattern)
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.
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)
@ 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.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
@ Known
Known to have no common set bits.
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...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
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,...
const ScalarOptions & getScalarOptions(const LLVMContext &C)
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
LLVM_ABI bool isKnownPositive(const WithCache< const Value * > &V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the given value is known be positive (i.e.
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 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.