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."));
82 Instruction *UserI = cast<Instruction>(U.getUser());
83 if (
auto *Phi = dyn_cast<PHINode>(UserI))
84 UserI = Phi->getIncomingBlock(U)->getTerminator();
97 : Pred(Pred), Op0(Op0), Op1(Op1) {}
130 : Inst(Inst), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
134 :
U(
U), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
135 Ty(EntryTy::UseCheck) {}
138 ConditionTy Precond = {})
140 NumOut(DTN->
getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
144 ConditionTy Precond = {}) {
145 return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
149 return FactOrCheck(EntryTy::InstFact, DTN, Inst);
153 return FactOrCheck(DTN, U);
157 return FactOrCheck(EntryTy::InstCheck, DTN, CI);
160 bool isCheck()
const {
161 return Ty == EntryTy::InstCheck || Ty == EntryTy::UseCheck;
165 assert(!isConditionFact());
166 if (Ty == EntryTy::UseCheck)
173 if (Ty == EntryTy::InstCheck)
176 return dyn_cast<Instruction>(*U);
179 bool isConditionFact()
const {
return Ty == EntryTy::ConditionFact; }
190 : DT(DT), LI(LI), SE(SE) {}
211 bool IsSigned =
false;
216 StackEntry(
unsigned NumIn,
unsigned NumOut,
bool IsSigned,
218 : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
219 ValuesToRelease(ValuesToRelease) {}
228 bool IsSigned =
false;
230 ConstraintTy() =
default;
234 : Coefficients(
std::
move(Coefficients)), IsSigned(IsSigned), IsEq(IsEq),
237 unsigned size()
const {
return Coefficients.
size(); }
239 unsigned empty()
const {
return Coefficients.
empty(); }
243 bool isValid(
const ConstraintInfo &Info)
const;
245 bool isEq()
const {
return IsEq; }
247 bool isNe()
const {
return IsNe; }
267class ConstraintInfo {
276 : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs),
DL(
DL) {
277 auto &Value2Index = getValue2Index(
false);
279 for (
Value *Arg : FunctionArgs) {
281 false,
false,
false);
282 VarPos.Coefficients[Value2Index[Arg]] = -1;
295 return Signed ? SignedCS : UnsignedCS;
298 return Signed ? SignedCS : UnsignedCS;
302 void popLastNVariables(
bool Signed,
unsigned N) {
303 getCS(
Signed).popLastNVariables(
N);
331 unsigned NumIn,
unsigned NumOut,
340 bool IsKnownNonNegative;
342 DecompEntry(int64_t Coefficient,
Value *Variable,
343 bool IsKnownNonNegative =
false)
344 : Coefficient(Coefficient), Variable(Variable),
345 IsKnownNonNegative(IsKnownNonNegative) {}
349struct Decomposition {
354 Decomposition(
Value *V,
bool IsKnownNonNegative =
false) {
360 void add(int64_t OtherOffset) {
364 void add(
const Decomposition &
Other) {
369 void sub(
const Decomposition &
Other) {
370 Decomposition Tmp =
Other;
376 void mul(int64_t Factor) {
378 for (
auto &Var : Vars)
386 APInt ConstantOffset;
394 ConstantOffset =
APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
403 OffsetResult Result(
GEP,
DL);
404 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
406 Result.ConstantOffset))
411 if (
auto *InnerGEP = dyn_cast<GetElementPtrInst>(Result.BasePtr)) {
414 bool CanCollectInner = InnerGEP->collectOffset(
415 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
417 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
418 VariableOffsets2.
size() > 1 ||
419 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
423 Result.BasePtr = InnerGEP->getPointerOperand();
424 Result.ConstantOffset += ConstantOffset2;
425 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
426 Result.VariableOffsets = VariableOffsets2;
427 Result.NW &= InnerGEP->getNoWrapFlags();
446 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
449 assert(!IsSigned &&
"The logic below only supports decomposition for "
450 "unsigned predicates at the moment.");
451 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
458 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
459 for (
auto [Index, Scale] : VariableOffsets) {
460 auto IdxResult =
decompose(Index, Preconditions, IsSigned,
DL);
461 IdxResult.mul(Scale.getSExtValue());
462 Result.add(IdxResult);
464 if (!NW.hasNoUnsignedWrap()) {
466 assert(NW.hasNoUnsignedSignedWrap() &&
"Must have nusw flag");
469 ConstantInt::get(Index->getType(), 0));
482 auto MergeResults = [&Preconditions, IsSigned, &
DL](
Value *
A,
Value *
B,
490 Type *Ty = V->getType()->getScalarType();
492 if (
auto *
GEP = dyn_cast<GEPOperator>(V))
494 if (isa<ConstantPointerNull>(V))
506 bool IsKnownNonNegative =
false;
510 if (
auto *CI = dyn_cast<ConstantInt>(V)) {
512 return CI->getSExtValue();
521 IsKnownNonNegative =
true;
528 return MergeResults(Op0, Op1, IsSigned);
531 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
532 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
539 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
548 if (Shift < Ty->getIntegerBitWidth() - 1) {
549 assert(Shift < 64 &&
"Would overflow");
550 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
551 Result.mul(int64_t(1) << Shift);
556 return {V, IsKnownNonNegative};
559 if (
auto *CI = dyn_cast<ConstantInt>(V)) {
562 return int64_t(CI->getZExtValue());
567 IsKnownNonNegative =
true;
572 ConstantInt::get(Op0->
getType(), 0));
573 }
else if (
auto *Trunc = dyn_cast<TruncInst>(V)) {
574 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64) {
575 if (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap()) {
576 V = Trunc->getOperand(0);
577 if (!Trunc->hasNoUnsignedWrap())
579 ConstantInt::get(V->getType(), 0));
587 return MergeResults(Op0, Op1, IsSigned);
592 ConstantInt::get(Op0->
getType(), 0));
595 ConstantInt::get(Op1->
getType(), 0));
597 return MergeResults(Op0, Op1, IsSigned);
605 return MergeResults(Op0, CI,
true);
610 return MergeResults(Op0, CI, IsSigned);
614 return {V, IsKnownNonNegative};
615 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
622 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
628 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
629 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
634 return {V, IsKnownNonNegative};
640 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
681 auto &Value2Index = getValue2Index(IsSigned);
683 Preconditions, IsSigned,
DL);
685 Preconditions, IsSigned,
DL);
686 int64_t Offset1 = ADec.Offset;
687 int64_t Offset2 = BDec.Offset;
690 auto &VariablesA = ADec.Vars;
691 auto &VariablesB = BDec.Vars;
696 auto GetOrAddIndex = [&Value2Index, &NewVariables,
697 &NewIndexMap](
Value *
V) ->
unsigned {
698 auto V2I = Value2Index.
find(V);
699 if (V2I != Value2Index.end())
702 NewIndexMap.
insert({V, Value2Index.size() + NewVariables.size() + 1});
704 NewVariables.push_back(V);
705 return Insert.first->second;
709 for (
const auto &KV : concat<DecompEntry>(VariablesA, VariablesB))
710 GetOrAddIndex(KV.Variable);
716 IsSigned, IsEq, IsNe);
720 auto &
R = Res.Coefficients;
721 for (
const auto &KV : VariablesA) {
722 R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
724 KnownNonNegativeVariables.
insert({KV.Variable, KV.IsKnownNonNegative});
725 I.first->second &= KV.IsKnownNonNegative;
728 for (
const auto &KV : VariablesB) {
729 if (
SubOverflow(R[GetOrAddIndex(KV.Variable)], KV.Coefficient,
730 R[GetOrAddIndex(KV.Variable)]))
733 KnownNonNegativeVariables.
insert({KV.Variable, KV.IsKnownNonNegative});
734 I.first->second &= KV.IsKnownNonNegative;
741 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
744 Res.Preconditions = std::move(Preconditions);
748 while (!NewVariables.empty()) {
749 int64_t
Last =
R.back();
753 Value *RemovedV = NewVariables.pop_back_val();
754 NewIndexMap.
erase(RemovedV);
758 for (
auto &KV : KnownNonNegativeVariables) {
760 (!Value2Index.contains(KV.first) && !NewIndexMap.
contains(KV.first)))
763 C[GetOrAddIndex(KV.first)] = -1;
764 Res.ExtraInfo.push_back(
C);
777 auto &Value2Index = getValue2Index(
false);
792 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
793 if (!NewVariables.
empty())
798bool ConstraintTy::isValid(
const ConstraintInfo &Info)
const {
799 return Coefficients.
size() > 0 &&
800 all_of(Preconditions, [&Info](
const ConditionTy &
C) {
801 return Info.doesHold(
C.Pred,
C.Op0,
C.Op1);
811 bool IsNegatedOrEqualImplied =
817 if (IsConditionImplied && IsNegatedOrEqualImplied)
824 bool IsStrictLessThanImplied =
831 if (IsNegatedImplied || IsStrictLessThanImplied)
837 if (IsConditionImplied)
842 if (IsNegatedImplied)
851 auto R = getConstraintForSolving(Pred,
A,
B);
852 return R.isValid(*
this) &&
853 getCS(
R.IsSigned).isConditionImplied(
R.Coefficients);
856void ConstraintInfo::transferToOtherSystem(
859 auto IsKnownNonNegative = [
this](
Value *
V) {
865 if (!
A->getType()->isIntegerTy())
876 if (IsKnownNonNegative(
B)) {
886 if (IsKnownNonNegative(
A)) {
894 if (IsKnownNonNegative(
A))
901 if (IsKnownNonNegative(
B))
907 if (IsKnownNonNegative(
B))
923void State::addInfoForInductions(
BasicBlock &BB) {
925 if (!L ||
L->getHeader() != &BB)
939 PN = dyn_cast<PHINode>(
A);
948 InLoopSucc = cast<BranchInst>(BB.
getTerminator())->getSuccessor(0);
950 InLoopSucc = cast<BranchInst>(BB.
getTerminator())->getSuccessor(1);
954 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB) || InLoopSucc == &BB)
957 auto *AR = dyn_cast_or_null<SCEVAddRecExpr>(SE.
getSCEV(PN));
959 if (!AR || AR->getLoop() != L || !LoopPred)
962 const SCEV *StartSCEV = AR->getStart();
963 Value *StartValue =
nullptr;
964 if (
auto *
C = dyn_cast<SCEVConstant>(StartSCEV)) {
965 StartValue =
C->getValue();
968 assert(SE.
getSCEV(StartValue) == StartSCEV &&
"inconsistent start value");
974 bool MonotonicallyIncreasingUnsigned =
976 bool MonotonicallyIncreasingSigned =
980 if (MonotonicallyIncreasingUnsigned)
983 if (MonotonicallyIncreasingSigned)
988 if (
auto *
C = dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE)))
989 StepOffset =
C->getAPInt();
994 if (!
L->isLoopInvariant(
B))
1000 if (!(-StepOffset).isOne())
1006 WorkList.
push_back(FactOrCheck::getConditionFact(
1009 WorkList.
push_back(FactOrCheck::getConditionFact(
1014 WorkList.
push_back(FactOrCheck::getConditionFact(
1017 WorkList.
push_back(FactOrCheck::getConditionFact(
1029 if (!StepOffset.
isOne()) {
1032 if (isa<SCEVCouldNotCompute>(BMinusStart) ||
1040 if (!MonotonicallyIncreasingUnsigned)
1041 WorkList.
push_back(FactOrCheck::getConditionFact(
1044 if (!MonotonicallyIncreasingSigned)
1045 WorkList.
push_back(FactOrCheck::getConditionFact(
1049 WorkList.
push_back(FactOrCheck::getConditionFact(
1052 WorkList.
push_back(FactOrCheck::getConditionFact(
1061 "unsupported predicate");
1064 L->getExitBlocks(ExitBBs);
1075 addInfoForInductions(BB);
1078 bool GuaranteedToExecute =
true;
1081 if (
auto Cmp = dyn_cast<ICmpInst>(&
I)) {
1082 for (
Use &U :
Cmp->uses()) {
1084 auto *DTN = DT.
getNode(UserI->getParent());
1087 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1092 auto *
II = dyn_cast<IntrinsicInst>(&
I);
1095 case Intrinsic::assume: {
1100 if (GuaranteedToExecute) {
1107 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1112 case Intrinsic::ssub_with_overflow:
1113 case Intrinsic::ucmp:
1114 case Intrinsic::scmp:
1116 FactOrCheck::getCheck(DT.
getNode(&BB), cast<CallInst>(&
I)));
1119 case Intrinsic::umin:
1120 case Intrinsic::umax:
1121 case Intrinsic::smin:
1122 case Intrinsic::smax:
1125 FactOrCheck::getCheck(DT.
getNode(&BB), cast<CallInst>(&
I)));
1131 case Intrinsic::abs:
1139 if (
auto *Switch = dyn_cast<SwitchInst>(BB.getTerminator())) {
1140 for (
auto &Case :
Switch->cases()) {
1142 Value *
V = Case.getCaseValue();
1143 if (!canAddSuccessor(BB, Succ))
1151 auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
1152 if (!Br || !Br->isConditional())
1173 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1174 if (SeenCond.
insert(V).second)
1179 while (!CondWorkList.
empty()) {
1181 if (
auto *Cmp = dyn_cast<ICmpInst>(Cur)) {
1184 IsOr ?
Cmp->getInverseCmpPredicate() :
Cmp->getCmpPredicate(),
1185 Cmp->getOperand(0),
Cmp->getOperand(1)));
1203 auto *CmpI = dyn_cast<ICmpInst>(Br->getCondition());
1206 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1208 DT.
getNode(Br->getSuccessor(0)), CmpI->getCmpPredicate(),
1209 CmpI->getOperand(0), CmpI->getOperand(1)));
1210 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1212 DT.
getNode(Br->getSuccessor(1)), CmpI->getInverseCmpPredicate(),
1213 CmpI->getOperand(0), CmpI->getOperand(1)));
1219 OS <<
"icmp " << Pred <<
' ';
1231struct ReproducerEntry {
1267 auto &Value2Index =
Info.getValue2Index(IsSigned);
1269 while (!WorkList.
empty()) {
1271 if (!Seen.
insert(V).second)
1273 if (Old2New.
find(V) != Old2New.
end())
1275 if (isa<Constant>(V))
1278 auto *
I = dyn_cast<Instruction>(V);
1279 if (Value2Index.contains(V) || !
I ||
1280 !isa<CmpInst, BinaryOperator, GEPOperator, CastInst>(V)) {
1290 for (
auto &Entry : Stack)
1291 if (Entry.Pred != ICmpInst::BAD_ICMP_PREDICATE)
1292 CollectArguments({Entry.LHS, Entry.RHS}, ICmpInst::isSigned(Entry.Pred));
1293 CollectArguments(
Cond, ICmpInst::isSigned(
Cond->getPredicate()));
1296 for (
auto *
P : Args)
1302 Cond->getModule()->getName() +
1303 Cond->getFunction()->getName() +
"repro",
1306 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1308 Old2New[Args[
I]] =
F->getArg(
I);
1323 auto &Value2Index =
Info.getValue2Index(IsSigned);
1324 while (!WorkList.
empty()) {
1326 if (Old2New.
find(V) != Old2New.
end())
1329 auto *
I = dyn_cast<Instruction>(V);
1330 if (!Value2Index.contains(V) &&
I) {
1331 Old2New[V] =
nullptr;
1341 Old2New[
I] = Cloned;
1342 Old2New[
I]->setName(
I->getName());
1354 for (
auto &Entry : Stack) {
1355 if (Entry.Pred == ICmpInst::BAD_ICMP_PREDICATE)
1363 auto *Cmp = Builder.
CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1370 Entry->getTerminator()->setOperand(0,
Cond);
1378 ConstraintInfo &Info) {
1381 auto R =
Info.getConstraintForSolving(Pred,
A,
B);
1382 if (R.empty() || !R.isValid(
Info)){
1384 return std::nullopt;
1387 auto &CSToUse =
Info.getCS(R.IsSigned);
1392 for (
auto &Row : R.ExtraInfo)
1393 CSToUse.addVariableRow(Row);
1395 for (
unsigned I = 0;
I < R.ExtraInfo.size(); ++
I)
1396 CSToUse.popLastConstraint();
1399 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1401 return std::nullopt;
1404 dbgs() <<
"Condition ";
1408 dbgs() <<
" implied by dominating constraints\n";
1411 return ImpliedCondition;
1414 return std::nullopt;
1418 CmpInst *Cmp, ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1422 auto ReplaceCmpWithConstant = [&](
CmpInst *Cmp,
bool IsTrue) {
1426 Cmp->replaceUsesWithIf(ConstantC, [&DT, NumIn, NumOut,
1427 ContextInst](
Use &U) {
1429 auto *DTN = DT.
getNode(UserI->getParent());
1432 if (UserI->getParent() == ContextInst->
getParent() &&
1433 UserI->comesBefore(ContextInst))
1438 auto *
II = dyn_cast<IntrinsicInst>(U.getUser());
1439 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1442 if (Cmp->use_empty())
1447 if (
auto ImpliedCondition =
1449 Cmp->getOperand(1), Cmp,
Info))
1450 return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
1458 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1464 ICmpInst::getNonStrictPredicate(
MinMax->getPredicate());
1467 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1470 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1479 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1489 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1498 Module *ReproducerModule,
1501 Info.popLastConstraint(E.IsSigned);
1503 auto &Mapping =
Info.getValue2Index(E.IsSigned);
1504 for (
Value *V : E.ValuesToRelease)
1506 Info.popLastNVariables(E.IsSigned, E.ValuesToRelease.size());
1508 if (ReproducerModule)
1515 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
1519 CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify());
1520 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
1525 if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp))
1528 unsigned OldSize = DFSInStack.
size();
1531 while (OldSize < DFSInStack.
size()) {
1532 StackEntry E = DFSInStack.back();
1533 removeEntryFromStack(E, Info, ReproducerModule, ReproducerCondStack,
1540 while (!Worklist.empty()) {
1541 Value *Val = Worklist.pop_back_val();
1549 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
1554 Worklist.push_back(
LHS);
1555 Worklist.push_back(
RHS);
1558 if (OldSize == DFSInStack.
size())
1562 if (
auto ImpliedCondition =
1565 if (IsOr && isa<SelectInst>(JoinOp)) {
1567 OtherOpIdx == 0 ? 2 : 0,
1581 unsigned NumIn,
unsigned NumOut,
1586 auto R = getConstraint(Pred,
A,
B, NewVariables);
1589 if (!
R.isValid(*
this) ||
R.isNe())
1595 auto &CSToUse = getCS(
R.IsSigned);
1596 if (
R.Coefficients.empty())
1599 Added |= CSToUse.addVariableRowFill(
R.Coefficients);
1605 auto &Value2Index = getValue2Index(
R.IsSigned);
1606 for (
Value *V : NewVariables) {
1607 Value2Index.insert({
V, Value2Index.size() + 1});
1612 dbgs() <<
" constraint: ";
1618 std::move(ValuesToRelease));
1621 for (
Value *V : NewVariables) {
1623 false,
false,
false);
1624 VarPos.Coefficients[Value2Index[
V]] = -1;
1625 CSToUse.addVariableRow(VarPos.Coefficients);
1633 for (
auto &Coeff :
R.Coefficients)
1635 CSToUse.addVariableRowFill(
R.Coefficients);
1645 bool Changed =
false;
1647 Value *Sub =
nullptr;
1652 U->replaceAllUsesWith(Sub);
1655 U->replaceAllUsesWith(Builder.
getFalse());
1660 if (U->use_empty()) {
1661 auto *
I = cast<Instruction>(U);
1668 if (
II->use_empty()) {
1669 II->eraseFromParent();
1679 ConstraintInfo &
Info) {
1680 auto R =
Info.getConstraintForSolving(Pred,
A,
B);
1681 if (R.size() < 2 || !R.isValid(
Info))
1684 auto &CSToUse =
Info.getCS(R.IsSigned);
1685 return CSToUse.isConditionImplied(R.Coefficients);
1688 bool Changed =
false;
1689 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1696 ConstantInt::get(
A->getType(), 0),
Info))
1706 bool Changed =
false;
1709 for (
Value &Arg :
F.args())
1711 ConstraintInfo
Info(
F.getDataLayout(), FunctionArgs);
1712 State S(DT, LI, SE);
1713 std::unique_ptr<Module> ReproducerModule(
1732 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
1733 auto HasNoConstOp = [](const FactOrCheck &B) {
1734 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
1735 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
1736 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
1740 if (
A.NumIn ==
B.NumIn) {
1741 if (A.isConditionFact() && B.isConditionFact()) {
1742 bool NoConstOpA = HasNoConstOp(A);
1743 bool NoConstOpB = HasNoConstOp(B);
1744 return NoConstOpA < NoConstOpB;
1746 if (
A.isConditionFact())
1748 if (
B.isConditionFact())
1750 auto *InstA =
A.getContextInst();
1751 auto *InstB =
B.getContextInst();
1752 return InstA->comesBefore(InstB);
1754 return A.NumIn <
B.NumIn;
1762 for (FactOrCheck &CB : S.WorkList) {
1765 while (!DFSInStack.
empty()) {
1766 auto &E = DFSInStack.
back();
1767 LLVM_DEBUG(
dbgs() <<
"Top of stack : " << E.NumIn <<
" " << E.NumOut
1769 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
1770 assert(E.NumIn <= CB.NumIn);
1771 if (CB.NumOut <= E.NumOut)
1774 dbgs() <<
"Removing ";
1776 Info.getValue2Index(E.IsSigned));
1786 Instruction *Inst = CB.getInstructionToSimplify();
1789 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
1791 if (
auto *
II = dyn_cast<WithOverflowInst>(Inst)) {
1793 }
else if (
auto *Cmp = dyn_cast<ICmpInst>(Inst)) {
1795 Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
1796 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
1801 ReproducerCondStack, DFSInStack);
1804 }
else if (
auto *
MinMax = dyn_cast<MinMaxIntrinsic>(Inst)) {
1806 }
else if (
auto *CmpIntr = dyn_cast<CmpIntrinsic>(Inst)) {
1818 <<
"Skip adding constraint because system has too many rows.\n");
1822 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
1823 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
1832 CB.NumIn, CB.NumOut, DFSInStack);
1834 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
1838 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
1841 for (
unsigned I = 0,
1842 E = (DFSInStack.
size() - ReproducerCondStack.
size());
1844 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
1851 if (!CB.isConditionFact()) {
1853 if (
match(CB.Inst, m_Intrinsic<Intrinsic::abs>(
m_Value(
X)))) {
1855 if (cast<ConstantInt>(CB.Inst->getOperand(1))->isOne())
1857 ConstantInt::get(CB.Inst->getType(), 0));
1862 if (
auto *
MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst)) {
1863 Pred = ICmpInst::getNonStrictPredicate(
MinMax->getPredicate());
1870 Value *
A =
nullptr, *
B =
nullptr;
1871 if (CB.isConditionFact()) {
1872 Pred = CB.Cond.Pred;
1876 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
1878 dbgs() <<
"Not adding fact ";
1880 dbgs() <<
" because precondition ";
1883 dbgs() <<
" does not hold.\n";
1888 bool Matched =
match(CB.Inst, m_Intrinsic<Intrinsic::assume>(
1891 assert(Matched &&
"Must have an assume intrinsic with a icmp operand");
1893 AddFact(Pred,
A,
B);
1896 if (ReproducerModule && !ReproducerModule->functions().empty()) {
1899 ReproducerModule->print(StringS,
nullptr);
1901 Rem <<
ore::NV(
"module") << S;
1906 unsigned SignedEntries =
1907 count_if(DFSInStack, [](
const StackEntry &E) {
return E.IsSigned; });
1908 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
1909 DFSInStack.
size() - SignedEntries &&
1910 "updates to CS and DFSInStack are out of sync");
1911 assert(
Info.getCS(
true).size() == SignedEntries &&
1912 "updates to CS and DFSInStack are out of sync");
1916 I->eraseFromParent();
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 int64_t multiplyWithOverflow(int64_t A, int64_t B)
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 int64_t addWithOverflow(int64_t A, int64_t B)
static cl::opt< bool > DumpReproducers("constraint-elimination-dump-reproducers", cl::init(false), cl::Hidden, cl::desc("Dump IR to reproduce successful transformations."))
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 void dumpUnpackedICmp(raw_ostream &OS, ICmpInst::Predicate Pred, Value *LHS, Value *RHS)
static bool checkOrAndOpImpliedByOther(FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule, SmallVectorImpl< ReproducerEntry > &ReproducerCondStack, SmallVectorImpl< StackEntry > &DFSInStack)
Check if either the first condition of an AND or OR is implied by the (negated in case of OR) second ...
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 checkAndReplaceCondition(CmpInst *Cmp, ConstraintInfo &Info, unsigned NumIn, unsigned NumOut, Instruction *ContextInst, Module *ReproducerModule, ArrayRef< ReproducerEntry > ReproducerCondStack, DominatorTree &DT, 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_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
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.
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 ConstantInt * getBool(LLVMContext &Context, bool V)
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
static 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)
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)
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.
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()
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.
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...
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
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 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.
void preserveSet()
Mark an analysis set as preserved.
void 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.
APInt getConstantMultiple(const SCEV *S)
Returns the max constant multiple of S.
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
bool isSCEVable(Type *Ty) const
Test if values of the given type are analyzable within the SCEV framework.
@ MonotonicallyIncreasing
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
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.
unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
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.
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
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.
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.
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.
@ 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)
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
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...
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...
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.
bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
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.