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(
std::
move(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);
317 bool ForceSignedSystem =
false)
const;
332 unsigned NumIn,
unsigned NumOut,
341 bool ForceSignedSystem);
349 bool IsKnownNonNegative;
351 DecompEntry(int64_t Coefficient,
Value *Variable,
352 bool IsKnownNonNegative =
false)
353 : Coefficient(Coefficient), Variable(Variable),
354 IsKnownNonNegative(IsKnownNonNegative) {}
358struct Decomposition {
363 Decomposition(
Value *V,
bool IsKnownNonNegative =
false) {
369 void add(int64_t OtherOffset) {
373 void add(
const Decomposition &
Other) {
378 void sub(
const Decomposition &
Other) {
379 Decomposition Tmp =
Other;
385 void mul(int64_t Factor) {
387 for (
auto &Var : Vars)
395 APInt ConstantOffset;
403 ConstantOffset =
APInt(
DL.getIndexTypeSizeInBits(
BasePtr->getType()), 0);
412 OffsetResult Result(
GEP,
DL);
413 unsigned BitWidth = Result.ConstantOffset.getBitWidth();
415 Result.ConstantOffset))
420 if (
auto *InnerGEP = dyn_cast<GetElementPtrInst>(Result.BasePtr)) {
423 bool CanCollectInner = InnerGEP->collectOffset(
424 DL,
BitWidth, VariableOffsets2, ConstantOffset2);
426 if (!CanCollectInner || Result.VariableOffsets.size() > 1 ||
427 VariableOffsets2.
size() > 1 ||
428 (Result.VariableOffsets.size() >= 1 && VariableOffsets2.
size() >= 1)) {
432 Result.BasePtr = InnerGEP->getPointerOperand();
433 Result.ConstantOffset += ConstantOffset2;
434 if (Result.VariableOffsets.size() == 0 && VariableOffsets2.
size() == 1)
435 Result.VariableOffsets = VariableOffsets2;
436 Result.NW &= InnerGEP->getNoWrapFlags();
455 if (
DL.getIndexTypeSizeInBits(
GEP.getPointerOperand()->getType()) > 64)
458 assert(!IsSigned &&
"The logic below only supports decomposition for "
459 "unsigned predicates at the moment.");
460 const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
467 Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));
468 for (
auto [Index, Scale] : VariableOffsets) {
469 auto IdxResult =
decompose(Index, Preconditions, IsSigned,
DL);
470 IdxResult.mul(Scale.getSExtValue());
471 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, &
DL](
Value *
A,
Value *
B,
499 Type *Ty = V->getType()->getScalarType();
501 if (
auto *
GEP = dyn_cast<GEPOperator>(V))
503 if (isa<ConstantPointerNull>(V))
515 bool IsKnownNonNegative =
false;
519 if (
auto *CI = dyn_cast<ConstantInt>(V)) {
521 return CI->getSExtValue();
530 IsKnownNonNegative =
true;
537 return MergeResults(Op0, Op1, IsSigned);
540 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
541 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
548 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
557 if (Shift < Ty->getIntegerBitWidth() - 1) {
558 assert(Shift < 64 &&
"Would overflow");
559 auto Result =
decompose(Op0, Preconditions, IsSigned,
DL);
560 Result.mul(int64_t(1) << Shift);
565 return {V, IsKnownNonNegative};
568 if (
auto *CI = dyn_cast<ConstantInt>(V)) {
571 return int64_t(CI->getZExtValue());
576 IsKnownNonNegative =
true;
581 ConstantInt::get(Op0->
getType(), 0));
582 }
else if (
auto *Trunc = dyn_cast<TruncInst>(V)) {
583 if (Trunc->getSrcTy()->getScalarSizeInBits() <= 64) {
584 if (Trunc->hasNoUnsignedWrap() || Trunc->hasNoSignedWrap()) {
585 V = Trunc->getOperand(0);
586 if (!Trunc->hasNoUnsignedWrap())
588 ConstantInt::get(V->getType(), 0));
596 return MergeResults(Op0, Op1, IsSigned);
601 ConstantInt::get(Op0->
getType(), 0));
604 ConstantInt::get(Op1->
getType(), 0));
606 return MergeResults(Op0, Op1, IsSigned);
614 return MergeResults(Op0, CI,
true);
619 return MergeResults(Op0, CI, IsSigned);
623 return {V, IsKnownNonNegative};
624 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
631 auto Result =
decompose(Op1, Preconditions, IsSigned,
DL);
637 auto ResA =
decompose(Op0, Preconditions, IsSigned,
DL);
638 auto ResB =
decompose(Op1, Preconditions, IsSigned,
DL);
643 return {V, IsKnownNonNegative};
649 bool ForceSignedSystem)
const {
650 assert(NewVariables.
empty() &&
"NewVariables must be empty when passed in");
652 "signed system can only be forced on eq/ne");
694 auto &Value2Index = getValue2Index(IsSigned);
696 Preconditions, IsSigned,
DL);
698 Preconditions, IsSigned,
DL);
699 int64_t Offset1 = ADec.Offset;
700 int64_t Offset2 = BDec.Offset;
703 auto &VariablesA = ADec.Vars;
704 auto &VariablesB = BDec.Vars;
709 auto GetOrAddIndex = [&Value2Index, &NewVariables,
710 &NewIndexMap](
Value *
V) ->
unsigned {
711 auto V2I = Value2Index.
find(V);
712 if (V2I != Value2Index.end())
715 NewIndexMap.
insert({V, Value2Index.size() + NewVariables.size() + 1});
717 NewVariables.push_back(V);
718 return Insert.first->second;
722 for (
const auto &KV : concat<DecompEntry>(VariablesA, VariablesB))
723 GetOrAddIndex(KV.Variable);
729 IsSigned, IsEq, IsNe);
733 auto &
R = Res.Coefficients;
734 for (
const auto &KV : VariablesA) {
735 R[GetOrAddIndex(KV.Variable)] += KV.Coefficient;
737 KnownNonNegativeVariables.
insert({KV.Variable, KV.IsKnownNonNegative});
738 I.first->second &= KV.IsKnownNonNegative;
741 for (
const auto &KV : VariablesB) {
742 auto &Coeff =
R[GetOrAddIndex(KV.Variable)];
746 KnownNonNegativeVariables.
insert({KV.Variable, KV.IsKnownNonNegative});
747 I.first->second &= KV.IsKnownNonNegative;
754 if (
AddOverflow(OffsetSum, int64_t(-1), OffsetSum))
757 Res.Preconditions = std::move(Preconditions);
761 while (!NewVariables.empty()) {
762 int64_t
Last =
R.back();
766 Value *RemovedV = NewVariables.pop_back_val();
767 NewIndexMap.
erase(RemovedV);
771 for (
auto &KV : KnownNonNegativeVariables) {
773 (!Value2Index.contains(KV.first) && !NewIndexMap.
contains(KV.first)))
775 auto &
C = Res.ExtraInfo.emplace_back(
776 Value2Index.size() + NewVariables.size() + 1, 0);
777 C[GetOrAddIndex(KV.first)] = -1;
790 auto &Value2Index = getValue2Index(
false);
805 ConstraintTy
R = getConstraint(Pred, Op0, Op1, NewVariables);
806 if (!NewVariables.
empty())
811bool ConstraintTy::isValid(
const ConstraintInfo &Info)
const {
812 return Coefficients.
size() > 0 &&
813 all_of(Preconditions, [&Info](
const ConditionTy &
C) {
814 return Info.doesHold(
C.Pred,
C.Op0,
C.Op1);
824 bool IsNegatedOrEqualImplied =
830 if (IsConditionImplied && IsNegatedOrEqualImplied)
837 bool IsStrictLessThanImplied =
844 if (IsNegatedImplied || IsStrictLessThanImplied)
850 if (IsConditionImplied)
855 if (IsNegatedImplied)
864 auto R = getConstraintForSolving(Pred,
A,
B);
865 return R.isValid(*
this) &&
866 getCS(
R.IsSigned).isConditionImplied(
R.Coefficients);
869void ConstraintInfo::transferToOtherSystem(
872 auto IsKnownNonNegative = [
this](
Value *
V) {
878 if (!
A->getType()->isIntegerTy())
889 if (IsKnownNonNegative(
B)) {
899 if (IsKnownNonNegative(
A)) {
907 if (IsKnownNonNegative(
A))
914 if (IsKnownNonNegative(
B))
920 if (IsKnownNonNegative(
B))
936void State::addInfoForInductions(
BasicBlock &BB) {
938 if (!L ||
L->getHeader() != &BB)
952 PN = dyn_cast<PHINode>(
A);
961 InLoopSucc = cast<BranchInst>(BB.
getTerminator())->getSuccessor(0);
963 InLoopSucc = cast<BranchInst>(BB.
getTerminator())->getSuccessor(1);
967 if (!
L->contains(InLoopSucc) || !
L->isLoopExiting(&BB) || InLoopSucc == &BB)
970 auto *AR = dyn_cast_or_null<SCEVAddRecExpr>(SE.
getSCEV(PN));
972 if (!AR || AR->getLoop() != L || !LoopPred)
975 const SCEV *StartSCEV = AR->getStart();
976 Value *StartValue =
nullptr;
977 if (
auto *
C = dyn_cast<SCEVConstant>(StartSCEV)) {
978 StartValue =
C->getValue();
981 assert(SE.
getSCEV(StartValue) == StartSCEV &&
"inconsistent start value");
987 bool MonotonicallyIncreasingUnsigned =
989 bool MonotonicallyIncreasingSigned =
993 if (MonotonicallyIncreasingUnsigned)
996 if (MonotonicallyIncreasingSigned)
1001 if (
auto *
C = dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE)))
1002 StepOffset =
C->getAPInt();
1007 if (!
L->isLoopInvariant(
B))
1013 if (!(-StepOffset).isOne())
1019 WorkList.
push_back(FactOrCheck::getConditionFact(
1022 WorkList.
push_back(FactOrCheck::getConditionFact(
1027 WorkList.
push_back(FactOrCheck::getConditionFact(
1030 WorkList.
push_back(FactOrCheck::getConditionFact(
1042 if (!StepOffset.
isOne()) {
1045 if (isa<SCEVCouldNotCompute>(BMinusStart) ||
1053 if (!MonotonicallyIncreasingUnsigned)
1054 WorkList.
push_back(FactOrCheck::getConditionFact(
1057 if (!MonotonicallyIncreasingSigned)
1058 WorkList.
push_back(FactOrCheck::getConditionFact(
1062 WorkList.
push_back(FactOrCheck::getConditionFact(
1065 WorkList.
push_back(FactOrCheck::getConditionFact(
1074 "unsupported predicate");
1077 L->getExitBlocks(ExitBBs);
1088 addInfoForInductions(BB);
1091 bool GuaranteedToExecute =
true;
1094 if (
auto Cmp = dyn_cast<ICmpInst>(&
I)) {
1095 for (
Use &U :
Cmp->uses()) {
1097 auto *DTN = DT.
getNode(UserI->getParent());
1100 WorkList.
push_back(FactOrCheck::getCheck(DTN, &U));
1105 auto *
II = dyn_cast<IntrinsicInst>(&
I);
1108 case Intrinsic::assume: {
1113 if (GuaranteedToExecute) {
1120 FactOrCheck::getInstFact(DT.
getNode(
I.getParent()), &
I));
1125 case Intrinsic::ssub_with_overflow:
1126 case Intrinsic::ucmp:
1127 case Intrinsic::scmp:
1129 FactOrCheck::getCheck(DT.
getNode(&BB), cast<CallInst>(&
I)));
1132 case Intrinsic::umin:
1133 case Intrinsic::umax:
1134 case Intrinsic::smin:
1135 case Intrinsic::smax:
1138 FactOrCheck::getCheck(DT.
getNode(&BB), cast<CallInst>(&
I)));
1144 case Intrinsic::abs:
1152 if (
auto *Switch = dyn_cast<SwitchInst>(BB.getTerminator())) {
1153 for (
auto &Case :
Switch->cases()) {
1155 Value *
V = Case.getCaseValue();
1156 if (!canAddSuccessor(BB, Succ))
1164 auto *Br = dyn_cast<BranchInst>(BB.getTerminator());
1165 if (!Br || !Br->isConditional())
1186 auto QueueValue = [&CondWorkList, &SeenCond](
Value *
V) {
1187 if (SeenCond.
insert(V).second)
1192 while (!CondWorkList.
empty()) {
1194 if (
auto *Cmp = dyn_cast<ICmpInst>(Cur)) {
1197 IsOr ?
Cmp->getInverseCmpPredicate() :
Cmp->getCmpPredicate(),
1198 Cmp->getOperand(0),
Cmp->getOperand(1)));
1216 auto *CmpI = dyn_cast<ICmpInst>(Br->getCondition());
1219 if (canAddSuccessor(BB, Br->getSuccessor(0)))
1221 DT.
getNode(Br->getSuccessor(0)), CmpI->getCmpPredicate(),
1222 CmpI->getOperand(0), CmpI->getOperand(1)));
1223 if (canAddSuccessor(BB, Br->getSuccessor(1)))
1225 DT.
getNode(Br->getSuccessor(1)), CmpI->getInverseCmpPredicate(),
1226 CmpI->getOperand(0), CmpI->getOperand(1)));
1232 OS <<
"icmp " << Pred <<
' ';
1244struct ReproducerEntry {
1280 auto &Value2Index =
Info.getValue2Index(IsSigned);
1282 while (!WorkList.
empty()) {
1284 if (!Seen.
insert(V).second)
1286 if (Old2New.
find(V) != Old2New.
end())
1288 if (isa<Constant>(V))
1291 auto *
I = dyn_cast<Instruction>(V);
1292 if (Value2Index.contains(V) || !
I ||
1293 !isa<CmpInst, BinaryOperator, GEPOperator, CastInst>(V)) {
1303 for (
auto &Entry : Stack)
1304 if (Entry.Pred != ICmpInst::BAD_ICMP_PREDICATE)
1305 CollectArguments({Entry.LHS, Entry.RHS}, ICmpInst::isSigned(Entry.Pred));
1306 CollectArguments(
Cond, ICmpInst::isSigned(
Cond->getPredicate()));
1309 for (
auto *
P : Args)
1315 Cond->getModule()->getName() +
1316 Cond->getFunction()->getName() +
"repro",
1319 for (
unsigned I = 0;
I < Args.size(); ++
I) {
1321 Old2New[Args[
I]] =
F->getArg(
I);
1336 auto &Value2Index =
Info.getValue2Index(IsSigned);
1337 while (!WorkList.
empty()) {
1339 if (Old2New.
find(V) != Old2New.
end())
1342 auto *
I = dyn_cast<Instruction>(V);
1343 if (!Value2Index.contains(V) &&
I) {
1344 Old2New[V] =
nullptr;
1354 Old2New[
I] = Cloned;
1355 Old2New[
I]->setName(
I->getName());
1367 for (
auto &Entry : Stack) {
1368 if (Entry.Pred == ICmpInst::BAD_ICMP_PREDICATE)
1376 auto *Cmp = Builder.
CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS);
1383 Entry->getTerminator()->setOperand(0,
Cond);
1391 ConstraintInfo &Info) {
1394 auto R =
Info.getConstraintForSolving(Pred,
A,
B);
1395 if (R.empty() || !R.isValid(
Info)){
1397 return std::nullopt;
1400 auto &CSToUse =
Info.getCS(R.IsSigned);
1405 for (
auto &Row : R.ExtraInfo)
1406 CSToUse.addVariableRow(Row);
1408 for (
unsigned I = 0;
I < R.ExtraInfo.size(); ++
I)
1409 CSToUse.popLastConstraint();
1412 if (
auto ImpliedCondition = R.isImpliedBy(CSToUse)) {
1414 return std::nullopt;
1417 dbgs() <<
"Condition ";
1421 dbgs() <<
" implied by dominating constraints\n";
1424 return ImpliedCondition;
1427 return std::nullopt;
1431 CmpInst *Cmp, ConstraintInfo &Info,
unsigned NumIn,
unsigned NumOut,
1435 auto ReplaceCmpWithConstant = [&](
CmpInst *Cmp,
bool IsTrue) {
1439 Cmp->replaceUsesWithIf(ConstantC, [&DT, NumIn, NumOut,
1440 ContextInst](
Use &U) {
1442 auto *DTN = DT.
getNode(UserI->getParent());
1445 if (UserI->getParent() == ContextInst->
getParent() &&
1446 UserI->comesBefore(ContextInst))
1451 auto *
II = dyn_cast<IntrinsicInst>(U.getUser());
1452 return !
II ||
II->getIntrinsicID() != Intrinsic::assume;
1455 if (Cmp->use_empty())
1460 if (
auto ImpliedCondition =
1462 Cmp->getOperand(1), Cmp,
Info))
1463 return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
1471 MinMax->replaceAllUsesWith(
MinMax->getOperand(UseLHS ? 0 : 1));
1477 ICmpInst::getNonStrictPredicate(
MinMax->getPredicate());
1480 return ReplaceMinMaxWithOperand(
MinMax, *ImpliedCondition);
1483 return ReplaceMinMaxWithOperand(
MinMax, !*ImpliedCondition);
1492 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 1));
1502 I->replaceAllUsesWith(ConstantInt::get(
I->getType(), 0));
1511 Module *ReproducerModule,
1514 Info.popLastConstraint(E.IsSigned);
1516 auto &Mapping =
Info.getValue2Index(E.IsSigned);
1517 for (
Value *V : E.ValuesToRelease)
1519 Info.popLastNVariables(E.IsSigned, E.ValuesToRelease.size());
1521 if (ReproducerModule)
1528 FactOrCheck &CB, ConstraintInfo &Info,
Module *ReproducerModule,
1532 CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify());
1533 unsigned OtherOpIdx = JoinOp->
getOperand(0) == CmpToCheck ? 1 : 0;
1538 if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp))
1541 unsigned OldSize = DFSInStack.
size();
1544 while (OldSize < DFSInStack.
size()) {
1545 StackEntry E = DFSInStack.back();
1546 removeEntryFromStack(E, Info, ReproducerModule, ReproducerCondStack,
1553 while (!Worklist.empty()) {
1554 Value *Val = Worklist.pop_back_val();
1562 Info.addFact(Pred,
LHS,
RHS, CB.NumIn, CB.NumOut, DFSInStack);
1567 Worklist.push_back(
LHS);
1568 Worklist.push_back(
RHS);
1571 if (OldSize == DFSInStack.
size())
1575 if (
auto ImpliedCondition =
1578 if (IsOr && isa<SelectInst>(JoinOp)) {
1580 OtherOpIdx == 0 ? 2 : 0,
1594 unsigned NumIn,
unsigned NumOut,
1596 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
false);
1599 addFactImpl(Pred,
A,
B, NumIn, NumOut, DFSInStack,
true);
1603 unsigned NumIn,
unsigned NumOut,
1605 bool ForceSignedSystem) {
1609 auto R = getConstraint(Pred,
A,
B, NewVariables, ForceSignedSystem);
1612 if (!
R.isValid(*
this) ||
R.isNe())
1617 auto &CSToUse = getCS(
R.IsSigned);
1618 if (
R.Coefficients.empty())
1621 bool Added = CSToUse.addVariableRowFill(
R.Coefficients);
1628 auto &Value2Index = getValue2Index(
R.IsSigned);
1629 for (
Value *V : NewVariables) {
1630 Value2Index.insert({
V, Value2Index.size() + 1});
1635 dbgs() <<
" constraint: ";
1641 std::move(ValuesToRelease));
1644 for (
Value *V : NewVariables) {
1646 false,
false,
false);
1647 VarPos.Coefficients[Value2Index[
V]] = -1;
1648 CSToUse.addVariableRow(VarPos.Coefficients);
1656 for (
auto &Coeff :
R.Coefficients)
1658 CSToUse.addVariableRowFill(
R.Coefficients);
1667 bool Changed =
false;
1669 Value *Sub =
nullptr;
1674 U->replaceAllUsesWith(Sub);
1677 U->replaceAllUsesWith(Builder.
getFalse());
1682 if (U->use_empty()) {
1683 auto *
I = cast<Instruction>(U);
1690 if (
II->use_empty()) {
1691 II->eraseFromParent();
1701 ConstraintInfo &
Info) {
1702 auto R =
Info.getConstraintForSolving(Pred,
A,
B);
1703 if (R.size() < 2 || !R.isValid(
Info))
1706 auto &CSToUse =
Info.getCS(R.IsSigned);
1707 return CSToUse.isConditionImplied(R.Coefficients);
1710 bool Changed =
false;
1711 if (
II->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
1718 ConstantInt::get(
A->getType(), 0),
Info))
1728 bool Changed =
false;
1731 for (
Value &Arg :
F.args())
1733 ConstraintInfo
Info(
F.getDataLayout(), FunctionArgs);
1734 State S(DT, LI, SE);
1735 std::unique_ptr<Module> ReproducerModule(
1754 stable_sort(S.WorkList, [](
const FactOrCheck &
A,
const FactOrCheck &
B) {
1755 auto HasNoConstOp = [](const FactOrCheck &B) {
1756 Value *V0 = B.isConditionFact() ? B.Cond.Op0 : B.Inst->getOperand(0);
1757 Value *V1 = B.isConditionFact() ? B.Cond.Op1 : B.Inst->getOperand(1);
1758 return !isa<ConstantInt>(V0) && !isa<ConstantInt>(V1);
1762 if (
A.NumIn ==
B.NumIn) {
1763 if (A.isConditionFact() && B.isConditionFact()) {
1764 bool NoConstOpA = HasNoConstOp(A);
1765 bool NoConstOpB = HasNoConstOp(B);
1766 return NoConstOpA < NoConstOpB;
1768 if (
A.isConditionFact())
1770 if (
B.isConditionFact())
1772 auto *InstA =
A.getContextInst();
1773 auto *InstB =
B.getContextInst();
1774 return InstA->comesBefore(InstB);
1776 return A.NumIn <
B.NumIn;
1784 for (FactOrCheck &CB : S.WorkList) {
1787 while (!DFSInStack.
empty()) {
1788 auto &E = DFSInStack.
back();
1789 LLVM_DEBUG(
dbgs() <<
"Top of stack : " << E.NumIn <<
" " << E.NumOut
1791 LLVM_DEBUG(
dbgs() <<
"CB: " << CB.NumIn <<
" " << CB.NumOut <<
"\n");
1792 assert(E.NumIn <= CB.NumIn);
1793 if (CB.NumOut <= E.NumOut)
1796 dbgs() <<
"Removing ";
1798 Info.getValue2Index(E.IsSigned));
1808 Instruction *Inst = CB.getInstructionToSimplify();
1811 LLVM_DEBUG(
dbgs() <<
"Processing condition to simplify: " << *Inst
1813 if (
auto *
II = dyn_cast<WithOverflowInst>(Inst)) {
1815 }
else if (
auto *Cmp = dyn_cast<ICmpInst>(Inst)) {
1817 Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
1818 ReproducerModule.get(), ReproducerCondStack, S.DT,
ToRemove);
1823 ReproducerCondStack, DFSInStack);
1826 }
else if (
auto *
MinMax = dyn_cast<MinMaxIntrinsic>(Inst)) {
1828 }
else if (
auto *CmpIntr = dyn_cast<CmpIntrinsic>(Inst)) {
1840 <<
"Skip adding constraint because system has too many rows.\n");
1844 Info.addFact(Pred,
A,
B, CB.NumIn, CB.NumOut, DFSInStack);
1845 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size())
1854 CB.NumIn, CB.NumOut, DFSInStack);
1856 Info.transferToOtherSystem(Pred,
A,
B, CB.NumIn, CB.NumOut,
1860 if (ReproducerModule && DFSInStack.
size() > ReproducerCondStack.
size()) {
1863 for (
unsigned I = 0,
1864 E = (DFSInStack.
size() - ReproducerCondStack.
size());
1866 ReproducerCondStack.
emplace_back(ICmpInst::BAD_ICMP_PREDICATE,
1873 if (!CB.isConditionFact()) {
1875 if (
match(CB.Inst, m_Intrinsic<Intrinsic::abs>(
m_Value(
X)))) {
1877 if (cast<ConstantInt>(CB.Inst->getOperand(1))->isOne())
1879 ConstantInt::get(CB.Inst->getType(), 0));
1884 if (
auto *
MinMax = dyn_cast<MinMaxIntrinsic>(CB.Inst)) {
1885 Pred = ICmpInst::getNonStrictPredicate(
MinMax->getPredicate());
1892 Value *
A =
nullptr, *
B =
nullptr;
1893 if (CB.isConditionFact()) {
1894 Pred = CB.Cond.Pred;
1898 !
Info.doesHold(CB.DoesHold.Pred, CB.DoesHold.Op0, CB.DoesHold.Op1)) {
1900 dbgs() <<
"Not adding fact ";
1902 dbgs() <<
" because precondition ";
1905 dbgs() <<
" does not hold.\n";
1910 bool Matched =
match(CB.Inst, m_Intrinsic<Intrinsic::assume>(
1913 assert(Matched &&
"Must have an assume intrinsic with a icmp operand");
1915 AddFact(Pred,
A,
B);
1918 if (ReproducerModule && !ReproducerModule->functions().empty()) {
1921 ReproducerModule->print(StringS,
nullptr);
1923 Rem <<
ore::NV(
"module") << S;
1928 unsigned SignedEntries =
1929 count_if(DFSInStack, [](
const StackEntry &E) {
return E.IsSigned; });
1930 assert(
Info.getCS(
false).size() - FunctionArgs.size() ==
1931 DFSInStack.
size() - SignedEntries &&
1932 "updates to CS and DFSInStack are out of sync");
1933 assert(
Info.getCS(
true).size() == SignedEntries &&
1934 "updates to CS and DFSInStack are out of sync");
1938 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.
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 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.