48using namespace PatternMatch;
50#define DEBUG_TYPE "constraint-elimination"
52STATISTIC(NumCondsRemoved,
"Number of instructions removed");
54 "Controls which conditions are eliminated");
58 cl::desc(
"Maximum number of rows to keep in constraint system"));
62 cl::desc(
"Dump IR to reproduce successful transformations."));
68 Instruction *UserI = cast<Instruction>(U.getUser());
69 if (
auto *Phi = dyn_cast<PHINode>(UserI))
70 UserI = Phi->getIncomingBlock(U)->getTerminator();
83 : Pred(Pred), Op0(Op0), Op1(Op1) {}
116 : Inst(Inst), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
120 :
U(
U), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
121 Ty(EntryTy::UseCheck) {}
124 ConditionTy Precond = {})
126 NumOut(DTN->
getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
130 ConditionTy Precond = {}) {
131 return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
135 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
139 return FactOrCheck(DTN, U);
143 return FactOrCheck(EntryTy::InstCheck, DTN, CI);
146 bool isCheck()
const {
147 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
151 assert(!isConditionFact());
152 if (Ty == EntryTy::UseCheck)
159 if (Ty == EntryTy::InstCheck)
162 return dyn_cast<Instruction>(*U);
165 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
176 : DT(DT), LI(LI), SE(SE) {}
197 bool IsSigned =
false;
202 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
204 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
205 ValuesToRelease(
std::
move(ValuesToRelease)) {}
214 bool IsSigned =
false;
216 ConstraintTy() =
default;
220 : Coefficients(
std::
move(Coefficients)), IsSigned(IsSigned), IsEq(IsEq),
223 unsigned size()
const {
return Coefficients.
size(); }
225 unsigned empty()
const {
return Coefficients.
empty(); }
229 bool isValid(
const ConstraintInfo &Info)
const;
231 bool isEq()
const {
return IsEq; }
233 bool isNe()
const {
return IsNe; }
253class ConstraintInfo {
262 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs),
DL(
DL) {
263 auto &Value2Index = getValue2Index(
false);
265 for (
Value *Arg : FunctionArgs) {
267 false,
false,
false);
268 VarPos.Coefficients[Value2Index[Arg]] = -1;
281 return Signed ? SignedCS : UnsignedCS;
284 return Signed ? SignedCS : UnsignedCS;
288 void popLastNVariables(
bool Signed,
unsigned N) {
289 getCS(
Signed).popLastNVariables(
N);
303 bool ForceSignedSystem =
false)
const;
318 unsigned NumIn,
unsigned NumOut,
327 bool ForceSignedSystem);
335 bool IsKnownNonNegative;
337 DecompEntry(int64_t Coefficient,
Value *Variable,
338 bool IsKnownNonNegative =
false)
339 : Coefficient(Coefficient), Variable(Variable),
340 IsKnownNonNegative(IsKnownNonNegative) {}
344struct Decomposition {
349 Decomposition(
Value *V,
bool IsKnownNonNegative =
false) {
357 [[nodiscard]]
bool add(int64_t OtherOffset) {
363 [[nodiscard]]
bool add(
const Decomposition &
Other) {
372 [[nodiscard]]
bool sub(
const Decomposition &
Other) {
373 Decomposition Tmp =
Other;
384 [[nodiscard]]
bool mul(int64_t Factor) {
387 for (
auto &Var : Vars)
388 if (
MulOverflow(Var.Coefficient, Factor, Var.Coefficient))
397 APInt ConstantOffset;
405 ConstantOffset =
APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
415 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
417 Result.ConstantOffset))
422 if (
auto *InnerGEP = dyn_cast<GetElementPtrInst>(Result.BasePtr)) {
425 bool CanCollectInner = InnerGEP->collectOffset(
426 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
428 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
429 VariableOffsets2.
size() > 1 ||
430 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
434 Result.BasePtr = InnerGEP->getPointerOperand();
435 Result.ConstantOffset += ConstantOffset2;
436 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
437 Result.VariableOffsets = VariableOffsets2;
438 Result.NW &= InnerGEP->getNoWrapFlags();
457 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
460 assert(!IsSigned &&
"The logic below only supports decomposition for "
461 "unsigned predicates at the moment.");
462 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
469 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
470 for (
auto [Index, Scale] : VariableOffsets) {
471 auto IdxResult =
decompose(Index, Preconditions, IsSigned,
DL);
472 if (IdxResult.mul(Scale.getSExtValue()))
474 if (Result.add(IdxResult))
477 if (!NW.hasNoUnsignedWrap()) {
479 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
482 ConstantInt::get(Index->getType(), 0));
495 auto MergeResults = [&Preconditions, IsSigned,
497 bool IsSignedB) -> std::optional<Decomposition> {
505 Type *Ty = V->getType()->getScalarType();
507 if (
auto *
GEP = dyn_cast<GEPOperator>(V))
509 if (isa<ConstantPointerNull>(V))
521 bool IsKnownNonNegative =
false;
525 if (
auto *CI = dyn_cast<ConstantInt>(V)) {
527 return CI->getSExtValue();
536 IsKnownNonNegative =
true;
543 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
545 return {V, IsKnownNonNegative};
549 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
550 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
553 return {V, IsKnownNonNegative};
558 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
561 return {V, IsKnownNonNegative};
568 if (Shift < Ty->getIntegerBitWidth() - 1) {
569 assert(Shift < 64 &&
"Would overflow");
570 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
571 if (!Result.mul(int64_t(1) << Shift))
573 return {V, IsKnownNonNegative};
577 return {V, IsKnownNonNegative};
580 if (
auto *CI = dyn_cast<ConstantInt>(V)) {
583 return int64_t(CI->getZExtValue());
588 IsKnownNonNegative =
true;
593 ConstantInt::get(Op0->
getType(), 0));
594 }
else if (
auto *Trunc = dyn_cast<TruncInst>(V)) {
595 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64) {
596 if (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap()) {
597 V = Trunc->getOperand(0);
598 if (!Trunc->hasNoUnsignedWrap())
600 ConstantInt::get(V->getType(), 0));
608 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
610 return {V, IsKnownNonNegative};
616 ConstantInt::get(Op0->
getType(), 0));
619 ConstantInt::get(Op1->
getType(), 0));
621 if (
auto Decomp = MergeResults(Op0, Op1, IsSigned))
623 return {V, IsKnownNonNegative};
631 if (
auto Decomp = MergeResults(Op0, CI,
true))
633 return {V, IsKnownNonNegative};
638 if (
auto Decomp = MergeResults(Op0, CI, IsSigned))
640 return {V, IsKnownNonNegative};
645 return {V, IsKnownNonNegative};
646 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
649 return {V, IsKnownNonNegative};
654 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
657 return {V, IsKnownNonNegative};
661 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
662 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
665 return {V, IsKnownNonNegative};
668 return {V, IsKnownNonNegative};
674 bool ForceSignedSystem)
const {
675 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
677 "signed system can only be forced on eq/ne");
719 auto &Value2Index = getValue2Index(IsSigned);
721 Preconditions, IsSigned,
DL);
723 Preconditions, IsSigned,
DL);
724 int64_t Offset1 = ADec.Offset;
725 int64_t Offset2 = BDec.Offset;
728 auto &VariablesA = ADec.Vars;
729 auto &VariablesB = BDec.Vars;
734 auto GetOrAddIndex = [&Value2Index, &NewVariables,
735 &NewIndexMap](
Value *
V) ->
unsigned {
736 auto V2I = Value2Index.
find(V);
737 if (V2I != Value2Index.end())
740 NewIndexMap.
insert({V, Value2Index.size() + NewVariables.size() + 1});
742 NewVariables.push_back(V);
743 return Insert.first->second;
747 for (
const auto &KV : concat<DecompEntry>(VariablesA, VariablesB))
748 GetOrAddIndex(KV.Variable);
754 IsSigned, IsEq, IsNe);
758 auto &
R = Res.Coefficients;
759 for (
const auto &KV : VariablesA) {
760 R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
762 KnownNonNegativeVariables.
insert({KV.Variable, KV.IsKnownNonNegative});
763 I.first->second &= KV.IsKnownNonNegative;
766 for (
const auto &KV : VariablesB) {
767 auto &Coeff =
R[GetOrAddIndex(KV.Variable)];
771 KnownNonNegativeVariables.
insert({KV.Variable, KV.IsKnownNonNegative});
772 I.first->second &= KV.IsKnownNonNegative;
779 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
782 Res.Preconditions = std::move(Preconditions);
786 while (!NewVariables.empty()) {
787 int64_t
Last =
R.back();
791 Value *RemovedV = NewVariables.pop_back_val();
792 NewIndexMap.
erase(RemovedV);
796 for (
auto &KV : KnownNonNegativeVariables) {
798 (!Value2Index.contains(KV.first) && !NewIndexMap.
contains(KV.first)))
800 auto &
C = Res.ExtraInfo.emplace_back(
801 Value2Index.size() + NewVariables.size() + 1, 0);
802 C[GetOrAddIndex(KV.first)] = -1;
815 auto &Value2Index = getValue2Index(
false);
830 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
831 if (!NewVariables.
empty())
836bool ConstraintTy::isValid(
const ConstraintInfo &Info)
const {
837 return Coefficients.
size() > 0 &&
838 all_of(Preconditions, [&Info](
const ConditionTy &
C) {
839 return Info.doesHold(
C.Pred,
C.Op0,
C.Op1);
849 bool IsNegatedOrEqualImplied =
855 if (IsConditionImplied && IsNegatedOrEqualImplied)
862 bool IsStrictLessThanImplied =
869 if (IsNegatedImplied || IsStrictLessThanImplied)
875 if (IsConditionImplied)
880 if (IsNegatedImplied)
889 auto R = getConstraintForSolving(Pred,
A,
B);
890 return R.isValid(*
this) &&
891 getCS(
R.IsSigned).isConditionImplied(
R.Coefficients);
894void ConstraintInfo::transferToOtherSystem(
897 auto IsKnownNonNegative = [
this](
Value *
V) {
903 if (!
A->getType()->isIntegerTy())
914 if (IsKnownNonNegative(
B)) {
924 if (IsKnownNonNegative(
A)) {
932 if (IsKnownNonNegative(
A))
939 if (IsKnownNonNegative(
B))
945 if (IsKnownNonNegative(
B))
961void State::addInfoForInductions(
BasicBlock &BB) {
963 if (!L ||
L->getHeader() != &BB)
977 PN = dyn_cast<PHINode>(
A);
986 InLoopSucc = cast<BranchInst>(BB.
getTerminator())->getSuccessor(0);
988 InLoopSucc = cast<BranchInst>(BB.
getTerminator())->getSuccessor(1);
992 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB) || InLoopSucc == &BB)
995 auto *AR = dyn_cast_or_null<SCEVAddRecExpr>(SE.
getSCEV(PN));
997 if (!AR || AR->getLoop() != L || !LoopPred)
1000 const SCEV *StartSCEV = AR->getStart();
1001 Value *StartValue =
nullptr;
1002 if (
auto *
C = dyn_cast<SCEVConstant>(StartSCEV)) {
1003 StartValue =
C->getValue();
1006 assert(SE.
getSCEV(StartValue) == StartSCEV &&
"inconsistent start value");
1012 bool MonotonicallyIncreasingUnsigned =
1014 bool MonotonicallyIncreasingSigned =
1018 if (MonotonicallyIncreasingUnsigned)
1021 if (MonotonicallyIncreasingSigned)
1026 if (
auto *
C = dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE)))
1027 StepOffset =
C->getAPInt();
1032 if (!
L->isLoopInvariant(
B))
1038 if (!(-StepOffset).isOne())
1044 WorkList.
push_back(FactOrCheck::getConditionFact(
1047 WorkList.
push_back(FactOrCheck::getConditionFact(
1052 WorkList.
push_back(FactOrCheck::getConditionFact(
1055 WorkList.
push_back(FactOrCheck::getConditionFact(
1067 if (!StepOffset.
isOne()) {
1070 if (isa<SCEVCouldNotCompute>(BMinusStart) ||
1078 if (!MonotonicallyIncreasingUnsigned)
1079 WorkList.
push_back(FactOrCheck::getConditionFact(
1082 if (!MonotonicallyIncreasingSigned)
1083 WorkList.
push_back(FactOrCheck::getConditionFact(
1087 WorkList.
push_back(FactOrCheck::getConditionFact(
1090 WorkList.
push_back(FactOrCheck::getConditionFact(
1099 "unsupported predicate");
1102 L->getExitBlocks(ExitBBs);
1113 addInfoForInductions(BB);
1116 bool GuaranteedToExecute =
true;
1119 if (
auto *Cmp = dyn_cast<ICmpInst>(&
I)) {
1120 for (
Use &U :
Cmp->uses()) {
1122 auto *DTN = DT.
getNode(UserI->getParent());
1125 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1130 auto *
II = dyn_cast<IntrinsicInst>(&
I);
1133 case Intrinsic::assume: {
1138 if (GuaranteedToExecute) {
1145 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1150 case Intrinsic::ssub_with_overflow:
1151 case Intrinsic::ucmp:
1152 case Intrinsic::scmp:
1154 FactOrCheck::getCheck(DT.
getNode(&BB), cast<CallInst>(&
I)));
1157 case Intrinsic::umin:
1158 case Intrinsic::umax:
1159 case Intrinsic::smin:
1160 case Intrinsic::smax:
1163 FactOrCheck::getCheck(DT.
getNode(&BB), cast<CallInst>(&
I)));
1165 case Intrinsic::uadd_sat:
1166 case Intrinsic::usub_sat:
1172 case Intrinsic::abs:
1180 if (
auto *Switch = dyn_cast<SwitchInst>(BB.getTerminator())) {
1181 for (
auto &Case :
Switch->cases()) {
1183 Value *
V = Case.getCaseValue();
1184 if (!canAddSuccessor(BB, Succ))
1192 auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
1193 if (!Br || !Br->isConditional())
1214 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1215 if (SeenCond.
insert(V).second)
1220 while (!CondWorkList.
empty()) {
1222 if (
auto *Cmp = dyn_cast<ICmpInst>(Cur)) {
1225 IsOr ?
Cmp->getInverseCmpPredicate() :
Cmp->getCmpPredicate(),
1226 Cmp->getOperand(0),
Cmp->getOperand(1)));
1244 auto *CmpI = dyn_cast<ICmpInst>(Br->getCondition());
1247 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1249 DT.
getNode(Br->getSuccessor(0)), CmpI->getCmpPredicate(),
1250 CmpI->getOperand(0), CmpI->getOperand(1)));
1251 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1253 DT.
getNode(Br->getSuccessor(1)), CmpI->getInverseCmpPredicate(),
1254 CmpI->getOperand(0), CmpI->getOperand(1)));
1260 OS <<
"icmp " << Pred <<
' ';
1272struct ReproducerEntry {
1308 auto &Value2Index =
Info.getValue2Index(IsSigned);
1310 while (!WorkList.
empty()) {
1312 if (!Seen.
insert(V).second)
1314 if (Old2New.
find(V) != Old2New.
end())
1316 if (isa<Constant>(V))
1319 auto *
I = dyn_cast<Instruction>(V);
1320 if (Value2Index.contains(V) || !
I ||
1321 !isa<CmpInst, BinaryOperator, GEPOperator, CastInst>(V)) {
1331 for (
auto &Entry : Stack)
1332 if (Entry.Pred != ICmpInst::BAD_ICMP_PREDICATE)
1333 CollectArguments({Entry.LHS, Entry.RHS}, ICmpInst::isSigned(Entry.Pred));
1334 CollectArguments(
Cond, ICmpInst::isSigned(
Cond->getPredicate()));
1337 for (
auto *
P : Args)
1343 Cond->getModule()->getName() +
1344 Cond->getFunction()->getName() +
"repro",
1347 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1349 Old2New[Args[
I]] =
F->getArg(
I);
1364 auto &Value2Index =
Info.getValue2Index(IsSigned);
1365 while (!WorkList.
empty()) {
1367 if (Old2New.
find(V) != Old2New.
end())
1370 auto *
I = dyn_cast<Instruction>(V);
1371 if (!Value2Index.contains(V) &&
I) {
1372 Old2New[V] =
nullptr;
1382 Old2New[
I] = Cloned;
1383 Old2New[
I]->setName(
I->getName());
1395 for (
auto &Entry : Stack) {
1396 if (Entry.Pred == ICmpInst::BAD_ICMP_PREDICATE)
1404 auto *Cmp = Builder.
CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1411 Entry->getTerminator()->setOperand(0,
Cond);
1419 ConstraintInfo &Info) {
1422 auto R =
Info.getConstraintForSolving(Pred,
A,
B);
1423 if (R.empty() || !R.isValid(
Info)){
1425 return std::nullopt;
1428 auto &CSToUse =
Info.getCS(R.IsSigned);
1433 for (
auto &Row : R.ExtraInfo)
1434 CSToUse.addVariableRow(Row);
1436 for (
unsigned I = 0;
I < R.ExtraInfo.size(); ++
I)
1437 CSToUse.popLastConstraint();
1440 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1442 return std::nullopt;
1445 dbgs() <<
"Condition ";
1449 dbgs() <<
" implied by dominating constraints\n";
1452 return ImpliedCondition;
1455 return std::nullopt;
1459 ICmpInst *Cmp, ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1463 auto ReplaceCmpWithConstant = [&](
CmpInst *Cmp,
bool IsTrue) {
1467 bool Changed =
false;
1468 Cmp->replaceUsesWithIf(ConstantC, [&DT, NumIn, NumOut, ContextInst,
1471 auto *DTN = DT.
getNode(UserI->getParent());
1474 if (UserI->getParent() == ContextInst->
getParent() &&
1475 UserI->comesBefore(ContextInst))
1480 auto *
II = dyn_cast<IntrinsicInst>(U.getUser());
1481 bool ShouldReplace = !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1482 Changed |= ShouldReplace;
1483 return ShouldReplace;
1492 for (
auto *DVR : DVRUsers) {
1493 auto *DTN = DT.
getNode(DVR->getParent());
1497 auto *MarkedI = DVR->getInstruction();
1498 if (MarkedI->getParent() == ContextInst->
getParent() &&
1499 MarkedI->comesBefore(ContextInst))
1502 DVR->replaceVariableLocationOp(Cmp, ConstantC);
1505 if (Cmp->use_empty())
1511 if (
auto ImpliedCondition =
1513 Cmp->getOperand(1), Cmp,
Info))
1514 return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
1518 if (Cmp->hasSameSign() && Cmp->isUnsigned())
1519 if (
auto ImpliedCondition =
1521 Cmp->getOperand(1), Cmp,
Info))
1522 return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
1531 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1537 ICmpInst::getNonStrictPredicate(
MinMax->getPredicate());
1540 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1543 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1552 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1562 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1571 Module *ReproducerModule,
1574 Info.popLastConstraint(E.IsSigned);
1576 auto &Mapping =
Info.getValue2Index(E.IsSigned);
1577 for (
Value *V : E.ValuesToRelease)
1579 Info.popLastNVariables(E.IsSigned, E.ValuesToRelease.size());
1581 if (ReproducerModule)
1588 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
1596 CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify());
1597 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
1602 if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp))
1605 unsigned OldSize = DFSInStack.
size();
1608 while (OldSize < DFSInStack.
size()) {
1609 StackEntry E = DFSInStack.back();
1610 removeEntryFromStack(E, Info, ReproducerModule, ReproducerCondStack,
1617 while (!Worklist.empty()) {
1618 Value *Val = Worklist.pop_back_val();
1626 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
1631 Worklist.push_back(
LHS);
1632 Worklist.push_back(
RHS);
1635 if (OldSize == DFSInStack.
size())
1639 if (
auto ImpliedCondition =
1642 if (IsOr == *ImpliedCondition)
1655 unsigned NumIn,
unsigned NumOut,
1657 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
1660 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
1664 unsigned NumIn,
unsigned NumOut,
1666 bool ForceSignedSystem) {
1670 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
1673 if (!
R.isValid(*
this) ||
R.isNe())
1678 auto &CSToUse = getCS(
R.IsSigned);
1679 if (
R.Coefficients.empty())
1682 bool Added = CSToUse.addVariableRowFill(
R.Coefficients);
1689 auto &Value2Index = getValue2Index(
R.IsSigned);
1690 for (
Value *V : NewVariables) {
1691 Value2Index.insert({
V, Value2Index.size() + 1});
1696 dbgs() <<
" constraint: ";
1702 std::move(ValuesToRelease));
1705 for (
Value *V : NewVariables) {
1707 false,
false,
false);
1708 VarPos.Coefficients[Value2Index[
V]] = -1;
1709 CSToUse.addVariableRow(VarPos.Coefficients);
1717 for (
auto &Coeff :
R.Coefficients)
1719 CSToUse.addVariableRowFill(
R.Coefficients);
1728 bool Changed =
false;
1735 U->replaceAllUsesWith(
Sub);
1738 U->replaceAllUsesWith(Builder.
getFalse());
1743 if (U->use_empty()) {
1744 auto *
I = cast<Instruction>(U);
1751 if (
II->use_empty()) {
1752 II->eraseFromParent();
1762 ConstraintInfo &
Info) {
1763 auto R =
Info.getConstraintForSolving(Pred,
A,
B);
1764 if (R.size() < 2 || !R.isValid(
Info))
1767 auto &CSToUse =
Info.getCS(R.IsSigned);
1768 return CSToUse.isConditionImplied(R.Coefficients);
1771 bool Changed =
false;
1772 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1779 ConstantInt::get(
A->getType(), 0),
Info))
1789 bool Changed =
false;
1792 ConstraintInfo
Info(
F.getDataLayout(), FunctionArgs);
1793 State S(DT, LI, SE);
1794 std::unique_ptr<Module> ReproducerModule(
1813 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
1814 auto HasNoConstOp = [](const FactOrCheck &B) {
1815 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
1816 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
1817 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
1821 if (
A.NumIn ==
B.NumIn) {
1822 if (A.isConditionFact() && B.isConditionFact()) {
1823 bool NoConstOpA = HasNoConstOp(A);
1824 bool NoConstOpB = HasNoConstOp(B);
1825 return NoConstOpA < NoConstOpB;
1827 if (
A.isConditionFact())
1829 if (
B.isConditionFact())
1831 auto *InstA =
A.getContextInst();
1832 auto *InstB =
B.getContextInst();
1833 return InstA->comesBefore(InstB);
1835 return A.NumIn <
B.NumIn;
1843 for (FactOrCheck &CB : S.WorkList) {
1846 while (!DFSInStack.
empty()) {
1847 auto &E = DFSInStack.
back();
1848 LLVM_DEBUG(
dbgs() <<
"Top of stack : " << E.NumIn <<
" " << E.NumOut
1850 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
1851 assert(E.NumIn <= CB.NumIn);
1852 if (CB.NumOut <= E.NumOut)
1855 dbgs() <<
"Removing ";
1857 Info.getValue2Index(E.IsSigned));
1867 Instruction *Inst = CB.getInstructionToSimplify();
1870 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
1872 if (
auto *
II = dyn_cast<WithOverflowInst>(Inst)) {
1874 }
else if (
auto *Cmp = dyn_cast<ICmpInst>(Inst)) {
1876 Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
1877 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
1881 CB, Info, ReproducerModule.get(), ReproducerCondStack, DFSInStack,
1885 }
else if (
auto *
MinMax = dyn_cast<MinMaxIntrinsic>(Inst)) {
1887 }
else if (
auto *CmpIntr = dyn_cast<CmpIntrinsic>(Inst)) {
1899 <<
"Skip adding constraint because system has too many rows.\n");
1903 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
1904 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
1913 CB.NumIn, CB.NumOut, DFSInStack);
1915 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
1919 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
1922 for (
unsigned I = 0,
1923 E = (DFSInStack.
size() - ReproducerCondStack.
size());
1925 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
1932 if (!CB.isConditionFact()) {
1934 if (
match(CB.Inst, m_Intrinsic<Intrinsic::abs>(
m_Value(
X)))) {
1936 if (cast<ConstantInt>(CB.Inst->getOperand(1))->isOne())
1938 ConstantInt::get(CB.Inst->getType(), 0));
1943 if (
auto *
MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst)) {
1944 Pred = ICmpInst::getNonStrictPredicate(
MinMax->getPredicate());
1949 if (
auto *USatI = dyn_cast<SaturatingInst>(CB.Inst)) {
1950 switch (USatI->getIntrinsicID()) {
1953 case Intrinsic::uadd_sat:
1954 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS());
1955 AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS());
1957 case Intrinsic::usub_sat:
1958 AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS());
1965 Value *
A =
nullptr, *
B =
nullptr;
1966 if (CB.isConditionFact()) {
1967 Pred = CB.Cond.Pred;
1971 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
1973 dbgs() <<
"Not adding fact ";
1975 dbgs() <<
" because precondition ";
1978 dbgs() <<
" does not hold.\n";
1983 bool Matched =
match(CB.Inst, m_Intrinsic<Intrinsic::assume>(
1986 assert(Matched &&
"Must have an assume intrinsic with a icmp operand");
1988 AddFact(Pred,
A,
B);
1991 if (ReproducerModule && !ReproducerModule->functions().empty()) {
1994 ReproducerModule->print(StringS,
nullptr);
1996 Rem <<
ore::NV(
"module") << S;
2001 unsigned SignedEntries =
2002 count_if(DFSInStack, [](
const StackEntry &E) {
return E.IsSigned; });
2003 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
2004 DFSInStack.
size() - SignedEntries &&
2005 "updates to CS and DFSInStack are out of sync");
2006 assert(
Info.getCS(
true).size() == SignedEntries &&
2007 "updates to CS and DFSInStack are out of sync");
2011 I->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefAnalysis InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
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 bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE, OptimizationRemarkEmitter &ORE)
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 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 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)
std::optional< std::vector< StOtherPiece > > Other
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
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.
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)
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.
A container for analyses that lazily runs them and caches their results.
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.
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 represents a function call, abstracting a target machine's calling convention.
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 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)
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 &)
DenseMap< Value *, unsigned > & getValue2Index()
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.
bool addVariableRow(ArrayRef< int64_t > R)
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(unsigned CounterName)
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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 Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags none()
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.
LLVM_ABI CallInst * CreateAssumption(Value *Cond, ArrayRef< OperandBundleDef > OpBundles={})
Create an assume intrinsic call that allows the optimizer to assume that the provided condition will ...
ConstantInt * getTrue()
Get the constant value for i1 true.
BasicBlock::iterator GetInsertPoint() const
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
ConstantInt * getFalse()
Get the constant value for i1 false.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
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.
This class represents an analyzed expression in the program.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI APInt getConstantMultiple(const SCEV *S)
Returns the max constant multiple of S.
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 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.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI unsigned getIntegerBitWidth() const
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 void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
LLVM_ABI const Value * stripPointerCastsSameRepresentation() const
Strip off pointer casts, all-zero GEPs and address space casts but ensures the representation of the ...
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
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.
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
This is an optimization pass for GlobalISel generic memory operations.
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.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
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...
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
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.
@ Sub
Subtraction of integers.
LLVM_ABI void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
constexpr unsigned BitWidth
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...
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 ...
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.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A MapVector that performs no allocations if smaller than a certain size.