52#define DEBUG_TYPE "constraint-elimination"
54STATISTIC(NumCondsRemoved,
"Number of instructions removed");
56 "Controls which conditions are eliminated");
60 cl::desc(
"Maximum number of rows to keep in constraint system"));
64 cl::desc(
"Dump IR to reproduce successful transformations."));
72 UserI = Phi->getIncomingBlock(U)->getTerminator();
85 : Pred(Pred), Op0(Op0), Op1(Op1) {}
117 FactOrCheck(EntryTy Ty,
DomTreeNode *DTN, Instruction *Inst)
118 : Inst(Inst), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
122 :
U(
U), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
123 Ty(EntryTy::UseCheck) {}
127 :
Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
128 NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
130 static FactOrCheck getConditionFact(
DomTreeNode *DTN, CmpPredicate Pred,
133 return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
136 static FactOrCheck getInstFact(
DomTreeNode *DTN, Instruction *Inst) {
137 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
140 static FactOrCheck getCheck(
DomTreeNode *DTN, Use *U) {
141 return FactOrCheck(DTN, U);
144 static FactOrCheck getCheck(
DomTreeNode *DTN, CallInst *CI) {
145 return FactOrCheck(EntryTy::InstCheck, DTN, CI);
148 bool isCheck()
const {
149 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
153 assert(!isConditionFact());
154 if (Ty == EntryTy::UseCheck)
161 if (Ty == EntryTy::InstCheck)
167 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
175 TargetLibraryInfo &TLI;
178 State(DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE,
179 TargetLibraryInfo &TLI)
180 : DT(DT), LI(LI), SE(SE), TLI(TLI) {}
183 void addInfoFor(BasicBlock &BB);
187 void addInfoForInductions(BasicBlock &BB);
191 bool canAddSuccessor(BasicBlock &BB, BasicBlock *Succ)
const {
192 return DT.dominates(BasicBlockEdge(&BB, Succ), Succ);
201 bool IsSigned =
false;
204 SmallVector<Value *, 2> ValuesToRelease;
206 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
207 SmallVector<Value *, 2> ValuesToRelease)
208 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
209 ValuesToRelease(std::
move(ValuesToRelease)) {}
214 SmallVector<ConditionTy, 2> Preconditions;
216 bool IsSigned =
false;
218 ConstraintTy() =
default;
222 : Coefficients(std::
move(Coefficients)), IsSigned(IsSigned), IsEq(IsEq),
225 unsigned size()
const {
return Coefficients.size(); }
227 unsigned empty()
const {
return Coefficients.empty(); }
231 bool isValid(
const ConstraintInfo &Info)
const;
233 bool isEq()
const {
return IsEq; }
235 bool isNe()
const {
return IsNe; }
242 std::optional<bool> isImpliedBy(
const ConstraintSystem &CS)
const;
255class ConstraintInfo {
257 ConstraintSystem UnsignedCS;
258 ConstraintSystem SignedCS;
260 const DataLayout &DL;
264 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
265 auto &Value2Index = getValue2Index(
false);
267 for (
Value *Arg : FunctionArgs) {
269 false,
false,
false);
270 VarPos.Coefficients[Value2Index[Arg]] = -1;
271 UnsignedCS.addVariableRow(VarPos.Coefficients);
275 DenseMap<Value *, unsigned> &getValue2Index(
bool Signed) {
276 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
278 const DenseMap<Value *, unsigned> &getValue2Index(
bool Signed)
const {
279 return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
282 ConstraintSystem &getCS(
bool Signed) {
283 return Signed ? SignedCS : UnsignedCS;
285 const ConstraintSystem &getCS(
bool Signed)
const {
286 return Signed ? SignedCS : UnsignedCS;
289 void popLastConstraint(
bool Signed) { getCS(
Signed).popLastConstraint(); }
290 void popLastNVariables(
bool Signed,
unsigned N) {
291 getCS(
Signed).popLastNVariables(
N);
297 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack);
304 SmallVectorImpl<Value *> &NewVariables,
305 bool ForceSignedSystem =
false)
const;
320 unsigned NumIn,
unsigned NumOut,
321 SmallVectorImpl<StackEntry> &DFSInStack);
328 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack,
329 bool ForceSignedSystem);
337 DecompEntry(int64_t Coefficient,
Value *Variable)
338 : Coefficient(Coefficient), Variable(Variable) {}
342struct Decomposition {
346 Decomposition(int64_t Offset) : Offset(Offset) {}
347 Decomposition(
Value *V) { Vars.emplace_back(1, V); }
349 : Offset(Offset), Vars(Vars) {}
353 [[nodiscard]]
bool add(int64_t OtherOffset) {
359 [[nodiscard]]
bool add(
const Decomposition &
Other) {
368 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
369 Decomposition Tmp =
Other;
380 [[nodiscard]]
bool mul(int64_t Factor) {
383 for (
auto &Var : Vars)
384 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
393 APInt ConstantOffset;
394 SmallMapVector<Value *, APInt, 4> VariableOffsets;
397 OffsetResult() :
BasePtr(nullptr), ConstantOffset(0, uint64_t(0)) {}
399 OffsetResult(GEPOperator &
GEP,
const DataLayout &
DL)
401 ConstantOffset = APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
411 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
413 Result.ConstantOffset))
421 bool CanCollectInner = InnerGEP->collectOffset(
422 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
424 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
425 VariableOffsets2.
size() > 1 ||
426 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
430 Result.BasePtr = InnerGEP->getPointerOperand();
431 Result.ConstantOffset += ConstantOffset2;
432 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
433 Result.VariableOffsets = VariableOffsets2;
434 Result.NW &= InnerGEP->getNoWrapFlags();
453 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
456 assert(!IsSigned &&
"The logic below only supports decomposition for "
457 "unsigned predicates at the moment.");
458 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
465 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
466 for (
auto [Index, Scale] : VariableOffsets) {
467 auto IdxResult =
decompose(Index, Preconditions, IsSigned,
DL);
468 if (IdxResult.mul(Scale.getSExtValue()))
470 if (Result.add(IdxResult))
473 if (!NW.hasNoUnsignedWrap()) {
475 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
478 ConstantInt::get(Index->getType(), 0));
491 auto MergeResults = [&Preconditions, IsSigned,
493 bool IsSignedB) -> std::optional<Decomposition> {
502 if (Ty->isPointerTy() && !IsSigned) {
514 if (!Ty->isIntegerTy() || Ty->getIntegerBitWidth() > 64)
521 return CI->getSExtValue();
536 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
542 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
543 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
551 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
561 if (Shift < Ty->getIntegerBitWidth() - 1) {
562 assert(Shift < 64 &&
"Would overflow");
563 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
564 if (!Result.mul(int64_t(1) << Shift))
576 return int64_t(CI->getZExtValue());
585 ConstantInt::get(Op0->
getType(), 0));
587 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64) {
588 if (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap()) {
589 V = Trunc->getOperand(0);
590 if (!Trunc->hasNoUnsignedWrap())
592 ConstantInt::get(V->getType(), 0));
600 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
610 if (
auto Decomp = MergeResults(Op0, CI,
true))
618 ConstantInt::get(Op0->
getType(), 0));
621 ConstantInt::get(Op1->
getType(), 0));
623 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
630 if (
auto Decomp = MergeResults(Op0, CI, IsSigned))
638 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
646 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
653 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
654 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
666 bool ForceSignedSystem)
const {
667 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
669 "signed system can only be forced on eq/ne");
711 auto &Value2Index = getValue2Index(IsSigned);
713 Preconditions, IsSigned,
DL);
715 Preconditions, IsSigned,
DL);
716 int64_t Offset1 = ADec.Offset;
717 int64_t Offset2 = BDec.Offset;
720 auto &VariablesA = ADec.Vars;
721 auto &VariablesB = BDec.Vars;
725 SmallDenseMap<Value *, unsigned> NewIndexMap;
726 auto GetOrAddIndex = [&Value2Index, &NewVariables,
727 &NewIndexMap](
Value *
V) ->
unsigned {
728 auto V2I = Value2Index.find(V);
729 if (V2I != Value2Index.end())
732 V, Value2Index.size() + NewVariables.size() + 1);
734 NewVariables.push_back(V);
740 GetOrAddIndex(KV.Variable);
746 IsSigned, IsEq, IsNe);
747 auto &
R = Res.Coefficients;
748 for (
const auto &KV : VariablesA)
749 R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
751 for (
const auto &KV : VariablesB) {
752 auto &Coeff =
R[GetOrAddIndex(KV.Variable)];
761 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
764 Res.Preconditions = std::move(Preconditions);
768 while (!NewVariables.empty()) {
769 int64_t
Last =
R.back();
773 Value *RemovedV = NewVariables.pop_back_val();
774 NewIndexMap.
erase(RemovedV);
788 auto &Value2Index = getValue2Index(
false);
803 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
804 if (!NewVariables.
empty())
809bool ConstraintTy::isValid(
const ConstraintInfo &Info)
const {
810 return Coefficients.
size() > 0 &&
812 return Info.doesHold(
C.Pred,
C.Op0,
C.Op1);
817ConstraintTy::isImpliedBy(
const ConstraintSystem &CS)
const {
822 bool IsNegatedOrEqualImplied =
828 if (IsConditionImplied && IsNegatedOrEqualImplied)
835 bool IsStrictLessThanImplied =
842 if (IsNegatedImplied || IsStrictLessThanImplied)
848 if (IsConditionImplied)
853 if (IsNegatedImplied)
862 auto R = getConstraintForSolving(Pred,
A,
B);
863 return R.isValid(*
this) &&
864 getCS(
R.IsSigned).isConditionImplied(
R.Coefficients);
867void ConstraintInfo::transferToOtherSystem(
869 unsigned NumOut, SmallVectorImpl<StackEntry> &DFSInStack) {
870 auto IsKnownNonNegative = [
this](
Value *
V) {
876 if (!
A->getType()->isIntegerTy())
887 if (IsKnownNonNegative(
B)) {
897 if (IsKnownNonNegative(
A)) {
905 if (IsKnownNonNegative(
A))
912 if (IsKnownNonNegative(
B))
918 if (IsKnownNonNegative(
B))
934void State::addInfoForInductions(BasicBlock &BB) {
936 if (!L ||
L->getHeader() != &BB)
965 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB) || InLoopSucc == &BB)
970 if (!AR || AR->getLoop() != L || !LoopPred)
973 const SCEV *StartSCEV = AR->getStart();
974 Value *StartValue =
nullptr;
976 StartValue =
C->getValue();
979 assert(SE.
getSCEV(StartValue) == StartSCEV &&
"inconsistent start value");
985 bool MonotonicallyIncreasingUnsigned =
987 bool MonotonicallyIncreasingSigned =
991 if (MonotonicallyIncreasingUnsigned)
994 if (MonotonicallyIncreasingSigned)
1000 StepOffset =
C->getAPInt();
1005 if (!
L->isLoopInvariant(
B))
1011 if (!(-StepOffset).isOne())
1017 WorkList.
push_back(FactOrCheck::getConditionFact(
1020 WorkList.
push_back(FactOrCheck::getConditionFact(
1025 WorkList.
push_back(FactOrCheck::getConditionFact(
1028 WorkList.
push_back(FactOrCheck::getConditionFact(
1040 if (!StepOffset.
isOne()) {
1051 if (!MonotonicallyIncreasingUnsigned)
1052 WorkList.
push_back(FactOrCheck::getConditionFact(
1055 if (!MonotonicallyIncreasingSigned)
1056 WorkList.
push_back(FactOrCheck::getConditionFact(
1060 WorkList.
push_back(FactOrCheck::getConditionFact(
1063 WorkList.
push_back(FactOrCheck::getConditionFact(
1072 "unsupported predicate");
1075 L->getExitBlocks(ExitBBs);
1076 for (BasicBlock *EB : ExitBBs) {
1091 if (!
Offset.NW.hasNoUnsignedWrap())
1094 if (
Offset.VariableOffsets.size() != 1)
1098 auto &[Index, Scale] =
Offset.VariableOffsets.front();
1100 if (Index->getType()->getScalarSizeInBits() !=
BitWidth)
1109 std::optional<TypeSize>
Size =
1124 B = ConstantInt::get(Index->getType(), MaxIndex);
1128void State::addInfoFor(BasicBlock &BB) {
1129 addInfoForInductions(BB);
1133 bool GuaranteedToExecute =
true;
1135 for (Instruction &
I : BB) {
1137 for (Use &U :
Cmp->uses()) {
1139 auto *DTN = DT.
getNode(UserI->getParent());
1142 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1147 auto AddFactFromMemoryAccess = [&](
Value *Ptr,
Type *AccessType) {
1151 TypeSize AccessSize =
DL.getTypeStoreSize(AccessType);
1154 if (GuaranteedToExecute) {
1158 Pred,
A,
B,
DL, TLI)) {
1166 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1171 if (!LI->isVolatile())
1172 AddFactFromMemoryAccess(LI->getPointerOperand(), LI->getAccessType());
1175 if (!
SI->isVolatile())
1176 AddFactFromMemoryAccess(
SI->getPointerOperand(),
SI->getAccessType());
1182 case Intrinsic::assume: {
1187 if (GuaranteedToExecute) {
1194 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1199 case Intrinsic::ssub_with_overflow:
1200 case Intrinsic::ucmp:
1201 case Intrinsic::scmp:
1206 case Intrinsic::umin:
1207 case Intrinsic::umax:
1208 case Intrinsic::smin:
1209 case Intrinsic::smax:
1214 case Intrinsic::uadd_sat:
1215 case Intrinsic::usub_sat:
1221 case Intrinsic::abs:
1230 if ((BO->getOpcode() == Instruction::URem ||
1231 BO->getOpcode() == Instruction::UDiv) &&
1240 for (
auto &Case :
Switch->cases()) {
1242 Value *
V = Case.getCaseValue();
1243 if (!canAddSuccessor(BB, Succ))
1252 if (!Br || !Br->isConditional())
1272 SmallPtrSet<Value *, 8> SeenCond;
1273 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1274 if (SeenCond.
insert(V).second)
1279 while (!CondWorkList.
empty()) {
1284 IsOr ?
Cmp->getInverseCmpPredicate() :
Cmp->getCmpPredicate(),
1285 Cmp->getOperand(0),
Cmp->getOperand(1)));
1306 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1308 DT.
getNode(Br->getSuccessor(0)), CmpI->getCmpPredicate(),
1309 CmpI->getOperand(0), CmpI->getOperand(1)));
1310 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1312 DT.
getNode(Br->getSuccessor(1)), CmpI->getInverseCmpPredicate(),
1313 CmpI->getOperand(0), CmpI->getOperand(1)));
1319 OS <<
"icmp " << Pred <<
' ';
1320 LHS->printAsOperand(OS,
true);
1322 RHS->printAsOperand(OS,
false);
1331struct ReproducerEntry {
1332 ICmpInst::Predicate Pred;
1367 auto &Value2Index = Info.getValue2Index(IsSigned);
1369 while (!WorkList.
empty()) {
1371 if (!Seen.
insert(V).second)
1373 if (Old2New.
find(V) != Old2New.
end())
1379 if (Value2Index.contains(V) || !
I ||
1390 for (
auto &Entry : Stack)
1396 for (
auto *
P : Args)
1402 Cond->getModule()->getName() +
1403 Cond->getFunction()->getName() +
"repro",
1406 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1408 Old2New[Args[
I]] =
F->getArg(
I);
1413 Builder.CreateRet(Builder.getTrue());
1414 Builder.SetInsertPoint(Entry->getTerminator());
1423 auto &Value2Index = Info.getValue2Index(IsSigned);
1424 while (!WorkList.
empty()) {
1426 if (Old2New.
find(V) != Old2New.
end())
1430 if (!Value2Index.contains(V) &&
I) {
1431 Old2New[V] =
nullptr;
1441 Old2New[
I] = Cloned;
1442 Old2New[
I]->setName(
I->getName());
1454 for (
auto &Entry : Stack) {
1463 auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1464 Builder.CreateAssumption(Cmp);
1470 Entry->getTerminator()->setOperand(0,
Cond);
1478 ConstraintInfo &Info) {
1481 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1482 if (R.empty() || !R.isValid(Info)) {
1484 return std::nullopt;
1487 auto &CSToUse = Info.getCS(R.IsSigned);
1488 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1490 return std::nullopt;
1493 dbgs() <<
"Condition ";
1497 dbgs() <<
" implied by dominating constraints\n";
1500 return ImpliedCondition;
1503 return std::nullopt;
1507 ICmpInst *Cmp, ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1511 auto ReplaceCmpWithConstant = [&](
CmpInst *Cmp,
bool IsTrue) {
1516 Cmp->replaceUsesWithIf(ConstantC, [&DT, NumIn, NumOut, ContextInst,
1519 auto *DTN = DT.
getNode(UserI->getParent());
1522 if (UserI->getParent() == ContextInst->
getParent() &&
1523 UserI->comesBefore(ContextInst))
1529 bool ShouldReplace = !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1531 return ShouldReplace;
1540 for (
auto *DVR : DVRUsers) {
1541 auto *DTN = DT.
getNode(DVR->getParent());
1545 auto *MarkedI = DVR->getInstruction();
1546 if (MarkedI->getParent() == ContextInst->
getParent() &&
1547 MarkedI->comesBefore(ContextInst))
1550 DVR->replaceVariableLocationOp(Cmp, ConstantC);
1553 if (Cmp->use_empty())
1559 if (
auto ImpliedCondition =
1561 Cmp->getOperand(1), Cmp, Info))
1562 return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
1566 if (Cmp->hasSameSign() && Cmp->isUnsigned())
1567 if (
auto ImpliedCondition =
1569 Cmp->getOperand(1), Cmp, Info))
1570 return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
1579 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1588 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1591 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1600 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1610 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1619 Module *ReproducerModule,
1622 Info.popLastConstraint(
E.IsSigned);
1624 auto &Mapping = Info.getValue2Index(
E.IsSigned);
1625 for (
Value *V :
E.ValuesToRelease)
1627 Info.popLastNVariables(
E.IsSigned,
E.ValuesToRelease.size());
1629 if (ReproducerModule)
1636 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
1645 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
1653 unsigned OldSize = DFSInStack.
size();
1656 while (OldSize < DFSInStack.
size()) {
1657 StackEntry
E = DFSInStack.
back();
1665 while (!Worklist.empty()) {
1666 Value *Val = Worklist.pop_back_val();
1674 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
1679 Worklist.push_back(
LHS);
1680 Worklist.push_back(
RHS);
1683 if (OldSize == DFSInStack.
size())
1687 if (
auto ImpliedCondition =
1689 CmpToCheck->
getOperand(1), CmpToCheck, Info)) {
1690 if (IsOr == *ImpliedCondition)
1703 unsigned NumIn,
unsigned NumOut,
1704 SmallVectorImpl<StackEntry> &DFSInStack) {
1705 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
1708 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
1712 unsigned NumIn,
unsigned NumOut,
1713 SmallVectorImpl<StackEntry> &DFSInStack,
1714 bool ForceSignedSystem) {
1718 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
1721 if (!
R.isValid(*
this) ||
R.isNe())
1726 auto &CSToUse = getCS(
R.IsSigned);
1727 if (
R.Coefficients.empty())
1730 bool Added = CSToUse.addVariableRowFill(
R.Coefficients);
1736 SmallVector<Value *, 2> ValuesToRelease;
1737 auto &Value2Index = getValue2Index(
R.IsSigned);
1738 for (
Value *V : NewVariables) {
1739 Value2Index.try_emplace(V, Value2Index.size() + 1);
1744 dbgs() <<
" constraint: ";
1750 std::move(ValuesToRelease));
1753 for (
Value *V : NewVariables) {
1755 false,
false,
false);
1756 VarPos.Coefficients[Value2Index[
V]] = -1;
1757 CSToUse.addVariableRow(VarPos.Coefficients);
1759 SmallVector<Value *, 2>());
1765 for (
auto &Coeff :
R.Coefficients)
1767 CSToUse.addVariableRowFill(
R.Coefficients);
1770 SmallVector<Value *, 2>());
1782 Sub = Builder.CreateSub(
A,
B);
1783 U->replaceAllUsesWith(
Sub);
1786 U->replaceAllUsesWith(Builder.getFalse());
1791 if (U->use_empty()) {
1799 if (
II->use_empty()) {
1800 II->eraseFromParent();
1810 ConstraintInfo &Info) {
1811 auto R = Info.getConstraintForSolving(Pred,
A,
B);
1812 if (R.size() < 2 || !R.isValid(Info))
1815 auto &CSToUse = Info.getCS(R.IsSigned);
1816 return CSToUse.isConditionImplied(R.Coefficients);
1820 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1827 ConstantInt::get(
A->getType(), 0), Info))
1841 ConstraintInfo Info(
F.getDataLayout(), FunctionArgs);
1842 State S(DT, LI, SE, TLI);
1843 std::unique_ptr<Module> ReproducerModule(
1862 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
1863 auto HasNoConstOp = [](const FactOrCheck &B) {
1864 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
1865 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
1866 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
1870 if (
A.NumIn ==
B.NumIn) {
1871 if (A.isConditionFact() && B.isConditionFact()) {
1872 bool NoConstOpA = HasNoConstOp(A);
1873 bool NoConstOpB = HasNoConstOp(B);
1874 return NoConstOpA < NoConstOpB;
1876 if (
A.isConditionFact())
1878 if (
B.isConditionFact())
1880 auto *InstA =
A.getContextInst();
1881 auto *InstB =
B.getContextInst();
1882 return InstA->comesBefore(InstB);
1884 return A.NumIn <
B.NumIn;
1892 for (FactOrCheck &CB : S.WorkList) {
1895 while (!DFSInStack.
empty()) {
1896 auto &
E = DFSInStack.
back();
1899 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
1901 if (CB.NumOut <=
E.NumOut)
1904 dbgs() <<
"Removing ";
1906 Info.getValue2Index(
E.IsSigned));
1916 Instruction *Inst = CB.getInstructionToSimplify();
1919 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
1925 Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
1926 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
1930 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
1942 auto AddFact = [&](CmpPredicate Pred,
Value *
A,
Value *
B) {
1948 <<
"Skip adding constraint because system has too many rows.\n");
1952 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
1953 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
1962 CB.NumIn, CB.NumOut, DFSInStack);
1964 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
1968 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
1971 for (
unsigned I = 0,
1972 E = (DFSInStack.
size() - ReproducerCondStack.
size());
1974 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
1981 if (!CB.isConditionFact()) {
1987 ConstantInt::get(CB.Inst->getType(), 0));
1993 Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate());
1994 AddFact(Pred, MinMax, MinMax->getLHS());
1995 AddFact(Pred, MinMax, MinMax->getRHS());
1999 switch (USatI->getIntrinsicID()) {
2002 case Intrinsic::uadd_sat:
2003 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
2004 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
2006 case Intrinsic::usub_sat:
2007 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
2014 if (BO->getOpcode() == Instruction::URem) {
2021 if (BO->getOpcode() == Instruction::UDiv) {
2028 auto &
DL =
F.getDataLayout();
2029 auto AddFactsAboutIndices = [&](
Value *Ptr,
Type *AccessType) {
2034 DL.getTypeStoreSize(AccessType).getFixedValue(), Pred,
A,
B,
DL,
2036 AddFact(Pred,
A,
B);
2040 AddFactsAboutIndices(LI->getPointerOperand(), LI->getAccessType());
2044 AddFactsAboutIndices(
SI->getPointerOperand(),
SI->getAccessType());
2049 Value *
A =
nullptr, *
B =
nullptr;
2050 if (CB.isConditionFact()) {
2051 Pred = CB.Cond.Pred;
2055 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
2057 dbgs() <<
"Not adding fact ";
2059 dbgs() <<
" because precondition ";
2062 dbgs() <<
" does not hold.\n";
2070 assert(Matched &&
"Must have an assume intrinsic with a icmp operand");
2072 AddFact(Pred,
A,
B);
2075 if (ReproducerModule && !ReproducerModule->functions().empty()) {
2077 raw_string_ostream StringS(S);
2078 ReproducerModule->print(StringS,
nullptr);
2079 OptimizationRemark Rem(
DEBUG_TYPE,
"Reproducer", &
F);
2080 Rem <<
ore::NV(
"module") << S;
2085 unsigned SignedEntries =
2086 count_if(DFSInStack, [](
const StackEntry &
E) {
return E.IsSigned; });
2087 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2088 DFSInStack.
size() - SignedEntries &&
2089 "updates to CS and DFSInStack are out of sync");
2090 assert(
Info.getCS(
true).size() == SignedEntries &&
2091 "updates to CS and DFSInStack are out of sync");
2095 I->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
std::pair< ICmpInst *, unsigned > ConditionTy
static int64_t MaxConstraintValue
static int64_t MinSignedConstraintValue
static Instruction * getContextInstForUse(Use &U)
static Decomposition decomposeGEP(GEPOperator &GEP, SmallVectorImpl< ConditionTy > &Preconditions, bool IsSigned, const DataLayout &DL)
static bool canUseSExt(ConstantInt *CI)
static void dumpConstraint(ArrayRef< int64_t > C, const DenseMap< Value *, unsigned > &Value2Index)
static void removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack)
static std::optional< bool > checkCondition(CmpInst::Predicate Pred, Value *A, Value *B, Instruction *CheckInst, ConstraintInfo &Info)
static cl::opt< unsigned > MaxRows("constraint-elimination-max-rows", cl::init(500), cl::Hidden, cl::desc("Maximum number of rows to keep in constraint system"))
static cl::opt< bool > DumpReproducers("constraint-elimination-dump-reproducers", cl::init(false), cl::Hidden, cl::desc("Dump IR to reproduce successful transformations."))
static bool checkOrAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack, SmallVectorImpl< Instruction * > &ToRemove)
Check if either the first condition of an AND or OR is implied by the (negated in case of OR) second ...
static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE, OptimizationRemarkEmitter &ORE, TargetLibraryInfo &TLI)
static OffsetResult collectOffsets(GEPOperator &GEP, const DataLayout &DL)
static bool checkAndReplaceMinMax(MinMaxIntrinsic *MinMax, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
static void generateReproducer(CmpInst *Cond, Module *M, ArrayRef< ReproducerEntry > Stack, ConstraintInfo &Info, DominatorTree &DT)
Helper function to generate a reproducer function for simplifying Cond.
static bool checkAndReplaceCondition(ICmpInst *Cmp, ConstraintInfo &Info, unsigned NumIn, unsigned NumOut, Instruction *ContextInst, Module *ReproducerModule, ArrayRef< ReproducerEntry > ReproducerCondStack, DominatorTree &DT, SmallVectorImpl< Instruction * > &ToRemove)
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 Decomposition decompose(Value *V, SmallVectorImpl< ConditionTy > &Preconditions, bool IsSigned, const DataLayout &DL)
static bool replaceSubOverflowUses(IntrinsicInst *II, Value *A, Value *B, SmallVectorImpl< Instruction * > &ToRemove)
static bool tryToSimplifyOverflowMath(IntrinsicInst *II, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info, SmallVectorImpl< Instruction * > &ToRemove)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Machine Check Debug Module
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
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)
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
Class for arbitrary precision integers.
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
bool isNegative() const
Determine sign of this APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool slt(const APInt &RHS) const
Signed less than comparison.
bool isOne() const
Determine if this is a value of 1.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this basic block belongs to.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Represents analyses that only rely on functions' control flow.
This class is the base class for the comparison instructions.
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
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
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,...
Predicate getPredicate() const
Return the predicate for this instruction.
This class represents a ucmp/scmp intrinsic.
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
bool hasSameSign() const
Query samesign information, for optimizations.
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
const APInt & getValue() const
Return the constant as an APInt value reference.
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
static SmallVector< int64_t, 8 > negate(SmallVector< int64_t, 8 > R)
LLVM_ABI bool isConditionImplied(SmallVector< int64_t, 8 > R) const
static SmallVector< int64_t, 8 > toStrictLessThan(SmallVector< int64_t, 8 > R)
Converts the given vector to form a strict less than inequality.
static SmallVector< int64_t, 8 > negateOrEqual(SmallVector< int64_t, 8 > R)
Multiplies each coefficient in the given vector by -1.
bool addVariableRowFill(ArrayRef< int64_t > R)
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)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const KeyT &Val)
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.
unsigned getDFSNumOut() const
Analysis pass which computes a DominatorTree.
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
static GEPNoWrapFlags none()
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
@ ExternalLinkage
Externally visible function.
This instruction compares its operands according to the predicate given to the constructor.
Predicate getFlippedSignednessPredicate() const
For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->EQ.
Predicate getSignedPredicate() const
For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
bool isRelational() const
Return true if the predicate is relational (not EQ or NE).
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})
Drop all unknown metadata except for debug locations.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
Analysis pass that exposes the LoopInfo for a function.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
This class represents min/max intrinsics.
A Module instance is used to store all the information related to an LLVM module.
Value * getIncomingValueForBlock(const BasicBlock *BB) const
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI bool isSCEVable(Type *Ty) const
Test if values of the given type are analyzable within the SCEV framework.
@ MonotonicallyIncreasing
LLVM_ABI const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI APInt getConstantMultiple(const SCEV *S, const Instruction *CtxI=nullptr)
Returns the max constant multiple of S.
LLVM_ABI std::optional< MonotonicPredicateType > getMonotonicPredicateType(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred)
If, for all loop invariant X, the predicate "LHS `Pred` X" is monotonically increasing or decreasing,...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
iterator find(const KeyT &Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI const Value * stripPointerCastsSameRepresentation() const
Strip off pointer casts, all-zero GEPs and address space casts but ensures the representation of the ...
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWAdd(const LHS &L, const RHS &R)
auto m_LogicalOp()
Matches either L && R or L || R where L and R are arbitrary values.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
DisjointOr_match< LHS, RHS > m_DisjointOr(const LHS &L, const RHS &R)
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
ExtractValue_match< Ind, Val_t > m_ExtractValue(const Val_t &V)
Match a single index ExtractValue instruction.
NoWrapTrunc_match< OpTy, TruncInst::NoSignedWrap > m_NSWTrunc(const OpTy &Op)
Matches trunc nsw.
NNegZExt_match< OpTy > m_NNegZExt(const OpTy &Op)
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoSignedWrap > m_NSWShl(const LHS &L, const RHS &R)
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Shl, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWShl(const LHS &L, const RHS &R)
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWMul(const LHS &L, const RHS &R)
brc_match< Cond_t, bind_ty< BasicBlock >, bind_ty< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWSub(const LHS &L, const RHS &R)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap > m_NSWAdd(const LHS &L, const RHS &R)
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, 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.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Mul, OverflowingBinaryOperator::NoSignedWrap > m_NSWMul(const LHS &L, const RHS &R)
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.
FunctionAddr VTableAddr Value
std::enable_if_t< std::is_signed_v< T >, T > MulOverflow(T X, T Y, T &Result)
Multiply two signed integers, computing the two's complement truncated result, returning true if an o...
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI std::optional< TypeSize > getBaseObjectSize(const Value *Ptr, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Like getObjectSize(), but only returns the size of base objects (like allocas, global variables and a...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
DomTreeNodeBase< BasicBlock > DomTreeNode
auto dyn_cast_or_null(const Y &Val)
constexpr unsigned MaxAnalysisRecursionDepth
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Sub
Subtraction of integers.
LLVM_ABI void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
std::enable_if_t< std::is_signed_v< T >, T > AddOverflow(T X, T Y, T &Result)
Add two signed integers, computing the two's complement truncated result, returning true if overflow ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
std::enable_if_t< std::is_signed_v< T >, T > SubOverflow(T X, T Y, T &Result)
Subtract two signed integers, computing the two's complement truncated result, returning true if an o...
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.