86using namespace PatternMatch;
88#define DEBUG_TYPE "gvn"
90STATISTIC(NumGVNInstr,
"Number of instructions deleted");
92STATISTIC(NumGVNPRE,
"Number of instructions PRE'd");
94STATISTIC(NumGVNSimpl,
"Number of instructions simplified");
95STATISTIC(NumGVNEqProp,
"Number of equalities propagated");
97STATISTIC(NumPRELoopLoad,
"Number of loop loads PRE'd");
99 "Number of loads moved to predecessor of a critical edge in PRE");
101STATISTIC(IsValueFullyAvailableInBlockNumSpeculationsMax,
102 "Number of blocks speculated as available in "
103 "IsValueFullyAvailableInBlock(), max");
105 "Number of times we we reached gvn-max-block-speculations cut-off "
106 "preventing further exploration");
119 cl::desc(
"Max number of dependences to attempt Load PRE (default = 100)"));
124 cl::desc(
"Max number of blocks we're willing to speculate on (and recurse "
125 "into) when deducing if a value is fully available or not in GVN "
130 cl::desc(
"Max number of visited instructions when trying to find "
131 "dominating value of select dependency (default = 100)"));
135 cl::desc(
"Max number of instructions to scan in each basic block in GVN "
267 return cast<LoadInst>(
Val);
272 return cast<MemIntrinsic>(
Val);
277 return cast<SelectInst>(
Val);
298 Res.
AV = std::move(
AV);
329 e.type =
I->getType();
330 e.opcode =
I->getOpcode();
335 e.varargs.push_back(
lookupOrAdd(GCR->getOperand(0)));
336 e.varargs.push_back(
lookupOrAdd(GCR->getBasePtr()));
337 e.varargs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
339 for (
Use &
Op :
I->operands())
342 if (
I->isCommutative()) {
347 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
348 if (
e.varargs[0] >
e.varargs[1])
350 e.commutative =
true;
353 if (
auto *
C = dyn_cast<CmpInst>(
I)) {
356 if (
e.varargs[0] >
e.varargs[1]) {
360 e.opcode = (
C->getOpcode() << 8) | Predicate;
361 e.commutative =
true;
362 }
else if (
auto *E = dyn_cast<InsertValueInst>(
I)) {
363 e.varargs.append(E->idx_begin(), E->idx_end());
364 }
else if (
auto *SVI = dyn_cast<ShuffleVectorInst>(
I)) {
366 e.varargs.append(ShuffleMask.
begin(), ShuffleMask.
end());
374 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
375 "Not a comparison!");
378 e.varargs.push_back(lookupOrAdd(LHS));
379 e.varargs.push_back(lookupOrAdd(RHS));
382 if (
e.varargs[0] >
e.varargs[1]) {
386 e.opcode = (Opcode << 8) | Predicate;
387 e.commutative =
true;
393 assert(EI &&
"Not an ExtractValueInst?");
404 e.varargs.push_back(lookupOrAdd(WO->
getLHS()));
405 e.varargs.push_back(lookupOrAdd(WO->
getRHS()));
413 e.varargs.push_back(lookupOrAdd(
Op));
422 Type *PtrTy =
GEP->getType()->getScalarType();
424 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
427 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
431 E.opcode =
GEP->getOpcode();
433 E.varargs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
434 for (
const auto &Pair : VariableOffsets) {
435 E.varargs.push_back(lookupOrAdd(Pair.first));
436 E.varargs.push_back(lookupOrAdd(ConstantInt::get(Context, Pair.second)));
438 if (!ConstantOffset.isZero())
440 lookupOrAdd(ConstantInt::get(Context, ConstantOffset)));
444 E.opcode =
GEP->getOpcode();
445 E.type =
GEP->getSourceElementType();
447 E.varargs.push_back(lookupOrAdd(
Op));
456GVNPass::ValueTable::ValueTable() =
default;
457GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
458GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
459GVNPass::ValueTable::~ValueTable() =
default;
465 valueNumbering.
insert(std::make_pair(V, num));
466 if (
PHINode *PN = dyn_cast<PHINode>(V))
467 NumberingPhi[num] = PN;
478 if (
C->getFunction()->isPresplitCoroutine()) {
479 valueNumbering[
C] = nextValueNumber;
480 return nextValueNumber++;
486 if (
C->isConvergent()) {
487 valueNumbering[
C] = nextValueNumber;
488 return nextValueNumber++;
491 if (AA->doesNotAccessMemory(
C)) {
493 uint32_t e = assignExpNewValueNum(exp).first;
494 valueNumbering[
C] = e;
498 if (MD && AA->onlyReadsMemory(
C)) {
500 auto ValNum = assignExpNewValueNum(exp);
502 valueNumbering[
C] = ValNum.first;
509 valueNumbering[
C] = nextValueNumber;
510 return nextValueNumber++;
513 if (local_dep.
isDef()) {
518 if (!local_cdep || local_cdep->
arg_size() !=
C->arg_size()) {
519 valueNumbering[
C] = nextValueNumber;
520 return nextValueNumber++;
523 for (
unsigned i = 0, e =
C->arg_size(); i < e; ++i) {
524 uint32_t c_vn = lookupOrAdd(
C->getArgOperand(i));
527 valueNumbering[
C] = nextValueNumber;
528 return nextValueNumber++;
533 valueNumbering[
C] =
v;
546 if (
I.getResult().isNonLocal())
551 if (!
I.getResult().isDef() || cdep !=
nullptr) {
556 CallInst *NonLocalDepCall = dyn_cast<CallInst>(
I.getResult().getInst());
559 cdep = NonLocalDepCall;
568 valueNumbering[
C] = nextValueNumber;
569 return nextValueNumber++;
573 valueNumbering[
C] = nextValueNumber;
574 return nextValueNumber++;
576 for (
unsigned i = 0, e =
C->arg_size(); i < e; ++i) {
577 uint32_t c_vn = lookupOrAdd(
C->getArgOperand(i));
580 valueNumbering[
C] = nextValueNumber;
581 return nextValueNumber++;
586 valueNumbering[
C] =
v;
590 valueNumbering[
C] = nextValueNumber;
591 return nextValueNumber++;
595bool GVNPass::ValueTable::exists(
Value *V)
const {
596 return valueNumbering.contains(V);
603 if (VI != valueNumbering.end())
606 auto *
I = dyn_cast<Instruction>(V);
608 valueNumbering[V] = nextValueNumber;
609 return nextValueNumber++;
613 switch (
I->getOpcode()) {
614 case Instruction::Call:
615 return lookupOrAddCall(cast<CallInst>(
I));
616 case Instruction::FNeg:
617 case Instruction::Add:
618 case Instruction::FAdd:
619 case Instruction::Sub:
620 case Instruction::FSub:
621 case Instruction::Mul:
622 case Instruction::FMul:
623 case Instruction::UDiv:
624 case Instruction::SDiv:
625 case Instruction::FDiv:
626 case Instruction::URem:
627 case Instruction::SRem:
628 case Instruction::FRem:
629 case Instruction::Shl:
630 case Instruction::LShr:
631 case Instruction::AShr:
632 case Instruction::And:
633 case Instruction::Or:
634 case Instruction::Xor:
635 case Instruction::ICmp:
636 case Instruction::FCmp:
637 case Instruction::Trunc:
638 case Instruction::ZExt:
639 case Instruction::SExt:
640 case Instruction::FPToUI:
641 case Instruction::FPToSI:
642 case Instruction::UIToFP:
643 case Instruction::SIToFP:
644 case Instruction::FPTrunc:
645 case Instruction::FPExt:
646 case Instruction::PtrToInt:
647 case Instruction::IntToPtr:
648 case Instruction::AddrSpaceCast:
649 case Instruction::BitCast:
650 case Instruction::Select:
651 case Instruction::Freeze:
652 case Instruction::ExtractElement:
653 case Instruction::InsertElement:
654 case Instruction::ShuffleVector:
655 case Instruction::InsertValue:
658 case Instruction::GetElementPtr:
659 exp = createGEPExpr(cast<GetElementPtrInst>(
I));
661 case Instruction::ExtractValue:
662 exp = createExtractvalueExpr(cast<ExtractValueInst>(
I));
664 case Instruction::PHI:
665 valueNumbering[V] = nextValueNumber;
666 NumberingPhi[nextValueNumber] = cast<PHINode>(V);
667 return nextValueNumber++;
669 valueNumbering[V] = nextValueNumber;
670 return nextValueNumber++;
673 uint32_t e = assignExpNewValueNum(exp).first;
674 valueNumbering[V] = e;
683 assert(VI != valueNumbering.end() &&
"Value not numbered?");
686 return (VI != valueNumbering.end()) ? VI->second : 0;
693uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
697 return assignExpNewValueNum(exp).first;
702 valueNumbering.clear();
703 expressionNumbering.clear();
704 NumberingPhi.clear();
705 PhiTranslateTable.clear();
714 uint32_t Num = valueNumbering.lookup(V);
715 valueNumbering.erase(V);
718 NumberingPhi.erase(Num);
723void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
724 assert(!valueNumbering.contains(V) &&
725 "Inst still occurs in value numbering map!");
734 LeaderListNode &Curr = NumToLeaders[
N];
735 if (!Curr.Entry.Val) {
741 LeaderListNode *Node = TableAllocator.Allocate<LeaderListNode>();
744 Node->Next = Curr.Next;
752 LeaderListNode *Prev =
nullptr;
753 LeaderListNode *Curr = &NumToLeaders[
N];
755 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
764 Prev->Next = Curr->Next;
767 Curr->Entry.Val =
nullptr;
768 Curr->Entry.BB =
nullptr;
770 LeaderListNode *Next = Curr->Next;
771 Curr->Entry.Val = Next->Entry.Val;
772 Curr->Entry.BB = Next->Entry.BB;
773 Curr->Next = Next->Next;
778void GVNPass::LeaderMap::verifyRemoved(
const Value *V)
const {
781 for (
const auto &
I : NumToLeaders) {
783 assert(
I.second.Entry.Val != V &&
"Inst still in value numbering scope!");
785 std::none_of(leader_iterator(&
I.second), leader_iterator(
nullptr),
786 [=](
const LeaderTableEntry &E) {
return E.Val ==
V; }) &&
787 "Inst still in value numbering scope!");
830 bool Changed = runImpl(
F, AC, DT, TLI, AA, MemDep, LI, &ORE,
831 MSSA ? &MSSA->getMSSA() :
nullptr);
846 OS, MapClassName2PassName);
849 if (Options.
AllowPRE != std::nullopt)
850 OS << (*Options.
AllowPRE ?
"" :
"no-") <<
"pre;";
855 <<
"split-backedge-load-pre;";
861#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
865 errs() <<
I.first <<
"\n";
896 std::optional<BasicBlock *> UnavailableBB;
900 unsigned NumNewNewSpeculativelyAvailableBBs = 0;
908 while (!Worklist.
empty()) {
912 std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator,
bool>
IV =
914 CurrBB, AvailabilityState::SpeculativelyAvailable);
919 if (State == AvailabilityState::Unavailable) {
920 UnavailableBB = CurrBB;
931 ++NumNewNewSpeculativelyAvailableBBs;
937 MaxBBSpeculationCutoffReachedTimes += (int)OutOfBudget;
938 State = AvailabilityState::Unavailable;
939 UnavailableBB = CurrBB;
945 NewSpeculativelyAvailableBBs.
insert(CurrBB);
952 IsValueFullyAvailableInBlockNumSpeculationsMax.updateMax(
953 NumNewNewSpeculativelyAvailableBBs);
958 auto MarkAsFixpointAndEnqueueSuccessors =
960 auto It = FullyAvailableBlocks.
find(BB);
961 if (It == FullyAvailableBlocks.
end())
964 case AvailabilityState::Unavailable:
965 case AvailabilityState::Available:
967 case AvailabilityState::SpeculativelyAvailable:
968 State = FixpointState;
971 "Found a speculatively available successor leftover?");
986 while (!Worklist.
empty())
987 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
988 AvailabilityState::Unavailable);
995 while (!Worklist.
empty())
996 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
997 AvailabilityState::Available);
1000 "Must have fixed all the new speculatively available blocks.");
1003 return !UnavailableBB;
1012 if (V.AV.Val == OldValue)
1013 V.AV.Val = NewValue;
1014 if (V.AV.isSelectValue()) {
1015 if (V.AV.V1 == OldValue)
1017 if (V.AV.V2 == OldValue)
1032 if (ValuesPerBlock.
size() == 1 &&
1034 Load->getParent())) {
1035 assert(!ValuesPerBlock[0].AV.isUndefValue() &&
1036 "Dead BB dominate this block");
1037 return ValuesPerBlock[0].MaterializeAdjustedValue(Load, gvn);
1043 SSAUpdate.
Initialize(Load->getType(), Load->getName());
1048 if (AV.AV.isUndefValue())
1058 if (BB == Load->getParent() &&
1059 ((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() == Load) ||
1060 (AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() == Load)))
1074 Type *LoadTy = Load->getType();
1076 if (isSimpleValue()) {
1077 Res = getSimpleValue();
1078 if (Res->
getType() != LoadTy) {
1082 <<
" " << *getSimpleValue() <<
'\n'
1086 }
else if (isCoercedLoadValue()) {
1087 LoadInst *CoercedLoad = getCoercedLoadValue();
1102 if (!CoercedLoad->
hasMetadata(LLVMContext::MD_noundef))
1104 {LLVMContext::MD_dereferenceable,
1105 LLVMContext::MD_dereferenceable_or_null,
1106 LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group});
1108 <<
" " << *getCoercedLoadValue() <<
'\n'
1112 }
else if (isMemIntrinValue()) {
1116 <<
" " << *getMemIntrinValue() <<
'\n'
1119 }
else if (isSelectValue()) {
1122 assert(V1 && V2 &&
"both value operands of the select must be present");
1128 assert(Res &&
"failed to materialize?");
1134 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1154 using namespace ore;
1159 R <<
"load of type " << NV(
"Type", Load->getType()) <<
" not eliminated"
1162 for (
auto *U : Load->getPointerOperand()->users()) {
1163 if (U != Load && (isa<LoadInst>(U) || isa<StoreInst>(U))) {
1164 auto *
I = cast<Instruction>(U);
1165 if (
I->getFunction() == Load->getFunction() && DT->
dominates(
I, Load)) {
1181 for (
auto *U : Load->getPointerOperand()->users()) {
1182 if (U != Load && (isa<LoadInst>(U) || isa<StoreInst>(U))) {
1183 auto *
I = cast<Instruction>(U);
1184 if (
I->getFunction() == Load->getFunction() &&
1192 OtherAccess =
nullptr;
1204 R <<
" in favor of " << NV(
"OtherAccess", OtherAccess);
1206 R <<
" because it is clobbered by " << NV(
"ClobberedBy", DepInfo.
getInst());
1226 if (
auto *LI = dyn_cast<LoadInst>(Inst))
1227 if (LI->getPointerOperand() == Loc.
Ptr && LI->getType() == LoadTy)
1233std::optional<AvailableValue>
1236 assert(
Load->isUnordered() &&
"rules below are incorrect for ordered access");
1246 if (
StoreInst *DepSI = dyn_cast<StoreInst>(DepInst)) {
1248 if (
Address &&
Load->isAtomic() <= DepSI->isAtomic()) {
1260 if (
LoadInst *DepLoad = dyn_cast<LoadInst>(DepInst)) {
1264 if (DepLoad != Load &&
Address &&
1265 Load->isAtomic() <= DepLoad->isAtomic()) {
1274 Offset = (ClobberOff == std::nullopt || *ClobberOff < 0)
1288 if (
MemIntrinsic *DepMI = dyn_cast<MemIntrinsic>(DepInst)) {
1301 dbgs() <<
" is clobbered by " << *DepInst <<
'\n';);
1305 return std::nullopt;
1318 if (
StoreInst *S = dyn_cast<StoreInst>(DepInst)) {
1324 return std::nullopt;
1327 if (S->isAtomic() <
Load->isAtomic())
1328 return std::nullopt;
1333 if (
LoadInst *LD = dyn_cast<LoadInst>(DepInst)) {
1338 return std::nullopt;
1341 if (
LD->isAtomic() <
Load->isAtomic())
1342 return std::nullopt;
1350 if (
auto *Sel = dyn_cast<SelectInst>(DepInst)) {
1351 assert(Sel->getType() ==
Load->getPointerOperandType());
1357 return std::nullopt;
1362 return std::nullopt;
1370 dbgs() <<
" has unknown def " << *DepInst <<
'\n';);
1371 return std::nullopt;
1374void GVNPass::AnalyzeLoadAvailability(
LoadInst *Load, LoadDepVect &Deps,
1375 AvailValInBlkVect &ValuesPerBlock,
1376 UnavailBlkVect &UnavailableBlocks) {
1381 for (
const auto &Dep : Deps) {
1385 if (DeadBlocks.count(DepBB)) {
1393 UnavailableBlocks.push_back(DepBB);
1400 if (
auto AV = AnalyzeLoadAvailability(Load, DepInfo, Dep.getAddress())) {
1404 ValuesPerBlock.push_back(
1407 UnavailableBlocks.push_back(DepBB);
1411 assert(Deps.size() == ValuesPerBlock.size() + UnavailableBlocks.size() &&
1412 "post condition violation");
1438 if (
Term->getNumSuccessors() != 2 ||
Term->isSpecialTerminator())
1440 auto *SuccBB =
Term->getSuccessor(0);
1441 if (SuccBB == LoadBB)
1442 SuccBB =
Term->getSuccessor(1);
1443 if (!SuccBB->getSinglePredecessor())
1448 if (Inst.isDebugOrPseudoInst())
1450 if (--NumInsts == 0)
1453 if (!Inst.isIdenticalTo(Load))
1462 return cast<LoadInst>(&Inst);
1472void GVNPass::eliminatePartiallyRedundantLoad(
1473 LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1476 for (
const auto &AvailableLoad : AvailableLoads) {
1477 BasicBlock *UnavailableBlock = AvailableLoad.first;
1478 Value *LoadPtr = AvailableLoad.second;
1481 Load->getType(), LoadPtr,
Load->getName() +
".pre",
Load->isVolatile(),
1482 Load->getAlign(),
Load->getOrdering(),
Load->getSyncScopeID(),
1484 NewLoad->setDebugLoc(
Load->getDebugLoc());
1488 if (
auto *NewDef = dyn_cast<MemoryDef>(NewAccess))
1491 MSSAU->
insertUse(cast<MemoryUse>(NewAccess),
true);
1497 NewLoad->setAAMetadata(Tags);
1499 if (
auto *MD =
Load->getMetadata(LLVMContext::MD_invariant_load))
1500 NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
1501 if (
auto *InvGroupMD =
Load->getMetadata(LLVMContext::MD_invariant_group))
1502 NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
1503 if (
auto *RangeMD =
Load->getMetadata(LLVMContext::MD_range))
1504 NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
1505 if (
auto *AccessMD =
Load->getMetadata(LLVMContext::MD_access_group))
1507 NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
1516 ValuesPerBlock.push_back(
1523 if (CriticalEdgePredAndLoad) {
1524 auto I = CriticalEdgePredAndLoad->
find(UnavailableBlock);
1525 if (
I != CriticalEdgePredAndLoad->
end()) {
1526 ++NumPRELoadMoved2CEPred;
1533 LeaderTable.erase(ValNo, OldLoad, OldLoad->
getParent());
1535 removeInstruction(OldLoad);
1544 Load->replaceAllUsesWith(V);
1545 if (isa<PHINode>(V))
1548 I->setDebugLoc(
Load->getDebugLoc());
1549 if (
V->getType()->isPtrOrPtrVectorTy())
1554 <<
"load eliminated by PRE";
1558bool GVNPass::PerformLoadPRE(
LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1559 UnavailBlkVect &UnavailableBlocks) {
1569 UnavailableBlocks.end());
1591 bool MustEnsureSafetyOfSpeculativeExecution =
1596 if (TmpBB == LoadBB)
1598 if (Blockers.count(TmpBB))
1610 MustEnsureSafetyOfSpeculativeExecution =
1611 MustEnsureSafetyOfSpeculativeExecution || ICF->
hasICF(TmpBB);
1622 FullyAvailableBlocks[AV.BB] = AvailabilityState::Available;
1623 for (
BasicBlock *UnavailableBB : UnavailableBlocks)
1624 FullyAvailableBlocks[UnavailableBB] = AvailabilityState::Unavailable;
1637 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
1638 << Pred->
getName() <<
"': " << *Load <<
'\n');
1649 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
1650 << Pred->
getName() <<
"': " << *Load <<
'\n');
1656 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
1657 << Pred->
getName() <<
"': " << *Load <<
'\n');
1666 <<
"COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
1667 << Pred->
getName() <<
"': " << *Load <<
'\n');
1671 if (
LoadInst *LI = findLoadToHoistIntoPred(Pred, LoadBB, Load))
1672 CriticalEdgePredAndLoad[Pred] = LI;
1677 PredLoads[Pred] =
nullptr;
1682 unsigned NumInsertPreds = PredLoads.
size() + CriticalEdgePredSplit.
size();
1683 unsigned NumUnavailablePreds = NumInsertPreds +
1684 CriticalEdgePredAndLoad.
size();
1685 assert(NumUnavailablePreds != 0 &&
1686 "Fully available value should already be eliminated!");
1687 (void)NumUnavailablePreds;
1693 if (NumInsertPreds > 1)
1698 if (MustEnsureSafetyOfSpeculativeExecution) {
1699 if (CriticalEdgePredSplit.
size())
1702 for (
auto &PL : PredLoads)
1706 for (
auto &CEP : CriticalEdgePredAndLoad)
1713 for (
BasicBlock *OrigPred : CriticalEdgePredSplit) {
1714 BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
1715 assert(!PredLoads.count(OrigPred) &&
"Split edges shouldn't be in map!");
1716 PredLoads[NewPred] =
nullptr;
1717 LLVM_DEBUG(
dbgs() <<
"Split critical edge " << OrigPred->getName() <<
"->"
1718 << LoadBB->
getName() <<
'\n');
1721 for (
auto &CEP : CriticalEdgePredAndLoad)
1722 PredLoads[CEP.first] =
nullptr;
1725 bool CanDoPRE =
true;
1728 for (
auto &PredLoad : PredLoads) {
1729 BasicBlock *UnavailablePred = PredLoad.first;
1739 Value *LoadPtr =
Load->getPointerOperand();
1741 while (Cur != LoadBB) {
1754 LoadPtr =
Address.translateWithInsertion(LoadBB, UnavailablePred, *DT,
1761 << *
Load->getPointerOperand() <<
"\n");
1766 PredLoad.second = LoadPtr;
1770 while (!NewInsts.
empty()) {
1780 return !CriticalEdgePredSplit.empty();
1786 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOAD: " << *Load <<
'\n');
1788 <<
" INSTS: " << *NewInsts.
back()
1796 I->updateLocationAfterHoist();
1805 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, PredLoads,
1806 &CriticalEdgePredAndLoad);
1811bool GVNPass::performLoopLoadPRE(
LoadInst *Load,
1812 AvailValInBlkVect &ValuesPerBlock,
1813 UnavailBlkVect &UnavailableBlocks) {
1816 if (!L ||
L->getHeader() !=
Load->getParent())
1821 if (!Preheader || !Latch)
1824 Value *LoadPtr =
Load->getPointerOperand();
1826 if (!
L->isLoopInvariant(LoadPtr))
1836 for (
auto *Blocker : UnavailableBlocks) {
1838 if (!
L->contains(Blocker))
1862 if (Blocker->getTerminator()->mayWriteToMemory())
1865 LoopBlock = Blocker;
1878 AvailableLoads[LoopBlock] = LoadPtr;
1879 AvailableLoads[Preheader] = LoadPtr;
1881 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOOP LOAD: " << *Load <<
'\n');
1882 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, AvailableLoads,
1890 using namespace ore;
1894 <<
"load of type " << NV(
"Type", Load->getType()) <<
" eliminated"
1895 << setExtraArgs() <<
" in favor of "
1902bool GVNPass::processNonLocalLoad(
LoadInst *Load) {
1904 if (
Load->getParent()->getParent()->hasFnAttribute(
1905 Attribute::SanitizeAddress) ||
1906 Load->getParent()->getParent()->hasFnAttribute(
1907 Attribute::SanitizeHWAddress))
1917 unsigned NumDeps = Deps.size();
1924 !Deps[0].getResult().isDef() && !Deps[0].getResult().isClobber()) {
1926 dbgs() <<
" has unknown dependencies\n";);
1930 bool Changed =
false;
1933 dyn_cast<GetElementPtrInst>(
Load->getOperand(0))) {
1934 for (
Use &U :
GEP->indices())
1936 Changed |= performScalarPRE(
I);
1940 AvailValInBlkVect ValuesPerBlock;
1941 UnavailBlkVect UnavailableBlocks;
1942 AnalyzeLoadAvailability(Load, Deps, ValuesPerBlock, UnavailableBlocks);
1946 if (ValuesPerBlock.empty())
1954 if (UnavailableBlocks.empty()) {
1955 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING NONLOCAL LOAD: " << *Load <<
'\n');
1961 Load->replaceAllUsesWith(V);
1963 if (isa<PHINode>(V))
1969 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
1970 I->setDebugLoc(
Load->getDebugLoc());
1971 if (
V->getType()->isPtrOrPtrVectorTy())
1985 if (performLoopLoadPRE(Load, ValuesPerBlock, UnavailableBlocks) ||
1986 PerformLoadPRE(Load, ValuesPerBlock, UnavailableBlocks))
2001 Cmp->getFastMathFlags().noNaNs())) {
2009 if (isa<ConstantFP>(
LHS) && !cast<ConstantFP>(
LHS)->
isZero())
2011 if (isa<ConstantFP>(
RHS) && !cast<ConstantFP>(
RHS)->
isZero())
2026 Cmp->getFastMathFlags().noNaNs()) ||
2035 if (isa<ConstantFP>(
LHS) && !cast<ConstantFP>(
LHS)->
isZero())
2037 if (isa<ConstantFP>(
RHS) && !cast<ConstantFP>(
RHS)->
isZero())
2047 auto *I = dyn_cast<Instruction>(U);
2048 return I && I->getParent() == BB;
2052bool GVNPass::processAssumeIntrinsic(
AssumeInst *IntrinsicI) {
2056 if (
Cond->isZero()) {
2075 for (
const auto &Acc : *AL) {
2076 if (
auto *Current = dyn_cast<MemoryUseOrDef>(&Acc))
2077 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2078 FirstNonDom = Current;
2092 MSSAU->
insertDef(cast<MemoryDef>(NewDef),
false);
2102 if (isa<Constant>(V)) {
2110 bool Changed =
false;
2117 Changed |= propagateEquality(V, True, Edge,
false);
2123 ReplaceOperandsWithMap[
V] = True;
2145 if (
auto *CmpI = dyn_cast<CmpInst>(V)) {
2147 Value *CmpLHS = CmpI->getOperand(0);
2148 Value *CmpRHS = CmpI->getOperand(1);
2154 if (isa<Constant>(CmpLHS) && !isa<Constant>(CmpRHS))
2156 if (!isa<Instruction>(CmpLHS) && isa<Instruction>(CmpRHS))
2158 if ((isa<Argument>(CmpLHS) && isa<Argument>(CmpRHS)) ||
2159 (isa<Instruction>(CmpLHS) && isa<Instruction>(CmpRHS))) {
2170 if (isa<Constant>(CmpLHS) && isa<Constant>(CmpRHS))
2174 << *CmpLHS <<
" with "
2175 << *CmpRHS <<
" in block "
2176 << IntrinsicI->
getParent()->getName() <<
"\n");
2181 ReplaceOperandsWithMap[CmpLHS] = CmpRHS;
2194 I->replaceAllUsesWith(Repl);
2199bool GVNPass::processLoad(
LoadInst *L) {
2204 if (!
L->isUnordered())
2207 if (
L->use_empty()) {
2217 return processNonLocalLoad(L);
2224 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2225 dbgs() <<
" has unknown dependence\n";);
2229 auto AV = AnalyzeLoadAvailability(L, Dep,
L->getPointerOperand());
2252std::pair<uint32_t, bool>
2253GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2255 bool CreateNewValNum = !
e;
2256 if (CreateNewValNum) {
2257 Expressions.push_back(Exp);
2258 if (ExprIdx.size() < nextValueNumber + 1)
2259 ExprIdx.resize(nextValueNumber * 2);
2260 e = nextValueNumber;
2261 ExprIdx[nextValueNumber++] = nextExprNumber++;
2263 return {
e, CreateNewValNum};
2271 Gvn.LeaderTable.getLeaders(Num),
2272 [=](
const LeaderMap::LeaderTableEntry &L) { return L.BB == BB; });
2279 auto FindRes = PhiTranslateTable.find({Num, Pred});
2280 if (FindRes != PhiTranslateTable.end())
2281 return FindRes->second;
2282 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, Gvn);
2283 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2294 auto Leaders = Gvn.LeaderTable.getLeaders(Num);
2295 for (
const auto &Entry : Leaders) {
2296 Call = dyn_cast<CallInst>(Entry.Val);
2297 if (Call && Call->getParent() == PhiBlock)
2301 if (AA->doesNotAccessMemory(Call))
2304 if (!MD || !AA->onlyReadsMemory(Call))
2316 if (
D.getResult().isNonFuncLocal())
2327 if (
PHINode *PN = NumberingPhi[Num]) {
2328 for (
unsigned i = 0; i != PN->getNumIncomingValues(); ++i) {
2329 if (PN->getParent() == PhiBlock && PN->getIncomingBlock(i) == Pred)
2339 if (!areAllValsInBB(Num, PhiBlock, Gvn))
2342 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
2346 for (
unsigned i = 0; i <
Exp.varargs.size(); i++) {
2350 if ((i > 1 &&
Exp.opcode == Instruction::InsertValue) ||
2351 (i > 0 &&
Exp.opcode == Instruction::ExtractValue) ||
2352 (i > 1 &&
Exp.opcode == Instruction::ShuffleVector))
2354 Exp.varargs[i] = phiTranslate(Pred, PhiBlock,
Exp.varargs[i], Gvn);
2357 if (
Exp.commutative) {
2358 assert(
Exp.varargs.size() >= 2 &&
"Unsupported commutative instruction!");
2359 if (
Exp.varargs[0] >
Exp.varargs[1]) {
2362 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
2363 Exp.opcode = (Opcode << 8) |
2369 if (
uint32_t NewNum = expressionNumbering[Exp]) {
2370 if (
Exp.opcode == Instruction::Call && NewNum != Num)
2371 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, Gvn) ? NewNum : Num;
2379void GVNPass::ValueTable::eraseTranslateCacheEntry(
2382 PhiTranslateTable.erase({Num, Pred});
2391 auto Leaders = LeaderTable.getLeaders(num);
2392 if (Leaders.empty())
2395 Value *Val =
nullptr;
2396 for (
const auto &Entry : Leaders) {
2399 if (isa<Constant>(Val))
2419 "No edge between these basic blocks!");
2420 return Pred !=
nullptr;
2423void GVNPass::assignBlockRPONumber(
Function &
F) {
2424 BlockRPONumber.clear();
2428 BlockRPONumber[BB] = NextBlockNumber++;
2429 InvalidBlockRPONumbers =
false;
2432bool GVNPass::replaceOperandsForInBlockEquality(
Instruction *Instr)
const {
2433 bool Changed =
false;
2434 for (
unsigned OpNum = 0; OpNum <
Instr->getNumOperands(); ++OpNum) {
2436 auto it = ReplaceOperandsWithMap.find(Operand);
2437 if (it != ReplaceOperandsWithMap.end()) {
2439 << *it->second <<
" in instruction " << *Instr <<
'\n');
2440 Instr->setOperand(OpNum, it->second);
2452bool GVNPass::propagateEquality(
Value *LHS,
Value *RHS,
2454 bool DominatesByEdge) {
2456 Worklist.
push_back(std::make_pair(LHS, RHS));
2457 bool Changed =
false;
2462 while (!Worklist.
empty()) {
2463 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
2464 LHS = Item.first;
RHS = Item.second;
2471 if (isa<Constant>(LHS) && isa<Constant>(RHS))
2475 if (isa<Constant>(LHS) || (isa<Argument>(LHS) && !isa<Constant>(RHS)))
2477 assert((isa<Argument>(LHS) || isa<Instruction>(LHS)) &&
"Unexpected value!");
2481 : cast<Instruction>(LHS)->getDataLayout();
2488 if ((isa<Argument>(LHS) && isa<Argument>(RHS)) ||
2489 (isa<Instruction>(LHS) && isa<Instruction>(RHS))) {
2508 if (RootDominatesEnd && !isa<Instruction>(RHS) &&
2510 LeaderTable.insert(LVN, RHS, Root.
getEnd());
2517 auto canReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
2520 unsigned NumReplacements =
2523 canReplacePointersCallBack)
2525 canReplacePointersCallBack);
2527 if (NumReplacements > 0) {
2529 NumGVNEqProp += NumReplacements;
2549 bool isKnownFalse = !isKnownTrue;
2564 if (
CmpInst *Cmp = dyn_cast<CmpInst>(LHS)) {
2565 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
2572 Worklist.
push_back(std::make_pair(Op0, Op1));
2576 Constant *NotVal = ConstantInt::get(
Cmp->getType(), isKnownFalse);
2584 if (Num < NextNum) {
2586 if (NotCmp && isa<Instruction>(NotCmp)) {
2587 unsigned NumReplacements =
2592 Changed |= NumReplacements > 0;
2593 NumGVNEqProp += NumReplacements;
2603 if (RootDominatesEnd)
2604 LeaderTable.insert(Num, NotVal, Root.
getEnd());
2617 if (isa<DbgInfoIntrinsic>(
I))
2626 bool Changed =
false;
2627 if (!
I->use_empty()) {
2631 I->replaceAllUsesWith(V);
2639 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2646 if (
auto *Assume = dyn_cast<AssumeInst>(
I))
2647 return processAssumeIntrinsic(Assume);
2649 if (
LoadInst *Load = dyn_cast<LoadInst>(
I)) {
2650 if (processLoad(Load))
2654 LeaderTable.insert(Num, Load,
Load->getParent());
2661 if (!BI->isConditional())
2664 if (isa<Constant>(BI->getCondition()))
2665 return processFoldableCondBr(BI);
2667 Value *BranchCond = BI->getCondition();
2671 if (TrueSucc == FalseSucc)
2675 bool Changed =
false;
2679 Changed |= propagateEquality(BranchCond, TrueVal, TrueE,
true);
2683 Changed |= propagateEquality(BranchCond, FalseVal, FalseE,
true);
2690 Value *SwitchCond =
SI->getCondition();
2692 bool Changed =
false;
2697 ++SwitchEdges[Succ];
2703 if (SwitchEdges.
lookup(Dst) == 1) {
2705 Changed |= propagateEquality(SwitchCond, i->getCaseValue(), E,
true);
2713 if (
I->getType()->isVoidTy())
2721 if (isa<AllocaInst>(
I) ||
I->isTerminator() || isa<PHINode>(
I)) {
2722 LeaderTable.insert(Num,
I,
I->getParent());
2729 if (Num >= NextNum) {
2730 LeaderTable.insert(Num,
I,
I->getParent());
2736 Value *Repl = findLeader(
I->getParent(), Num);
2739 LeaderTable.insert(Num,
I,
I->getParent());
2773 InvalidBlockRPONumbers =
true;
2775 MSSAU = MSSA ? &Updater :
nullptr;
2777 bool Changed =
false;
2778 bool ShouldContinue =
true;
2788 Changed |= removedBlock;
2792 unsigned Iteration = 0;
2793 while (ShouldContinue) {
2796 ShouldContinue = iterateOnFunction(
F);
2797 Changed |= ShouldContinue;
2804 assignValNumForDeadCode();
2805 bool PREChanged =
true;
2806 while (PREChanged) {
2807 PREChanged = performPRE(
F);
2808 Changed |= PREChanged;
2817 cleanupGlobalSets();
2832 "We expect InstrsToErase to be empty across iterations");
2833 if (DeadBlocks.count(BB))
2837 ReplaceOperandsWithMap.clear();
2838 bool ChangedFunction =
false;
2846 for (
PHINode *PN : PHINodesToRemove) {
2848 removeInstruction(PN);
2853 if (!ReplaceOperandsWithMap.empty())
2854 ChangedFunction |= replaceOperandsForInBlockEquality(&*BI);
2855 ChangedFunction |= processInstruction(&*BI);
2857 if (InstrsToErase.
empty()) {
2863 NumGVNInstr += InstrsToErase.
size();
2866 bool AtStart = BI == BB->
begin();
2870 for (
auto *
I : InstrsToErase) {
2871 assert(
I->getParent() == BB &&
"Removing instruction from wrong block?");
2875 removeInstruction(
I);
2877 InstrsToErase.clear();
2885 return ChangedFunction;
2896 for (
unsigned i = 0, e =
Instr->getNumOperands(); i != e; ++i) {
2898 if (isa<Argument>(
Op) || isa<Constant>(
Op) || isa<GlobalValue>(
Op))
2910 if (
Value *V = findLeader(Pred, TValNo)) {
2911 Instr->setOperand(i, V);
2934 LeaderTable.insert(Num, Instr, Pred);
2938bool GVNPass::performScalarPRE(
Instruction *CurInst) {
2939 if (isa<AllocaInst>(CurInst) || CurInst->
isTerminator() ||
2942 isa<DbgInfoIntrinsic>(CurInst))
2949 if (isa<CmpInst>(CurInst))
2959 if (isa<GetElementPtrInst>(CurInst))
2962 if (
auto *CallB = dyn_cast<CallBase>(CurInst)) {
2964 if (CallB->isInlineAsm())
2976 unsigned NumWith = 0;
2977 unsigned NumWithout = 0;
2982 if (InvalidBlockRPONumbers)
2983 assignBlockRPONumber(*CurrentBlock->
getParent());
2994 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
2995 "Invalid BlockRPONumber map.");
2996 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3002 Value *predV = findLeader(
P, TValNo);
3007 }
else if (predV == CurInst) {
3019 if (NumWithout > 1 || NumWith == 0)
3027 if (NumWithout != 0) {
3046 toSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3050 PREInstr = CurInst->
clone();
3051 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3054 verifyRemoved(PREInstr);
3063 assert(PREInstr !=
nullptr || NumWithout == 0);
3069 CurInst->
getName() +
".pre-phi");
3070 Phi->insertBefore(CurrentBlock->begin());
3071 for (
unsigned i = 0, e = predMap.
size(); i != e; ++i) {
3072 if (
Value *V = predMap[i].first) {
3076 Phi->addIncoming(V, predMap[i].second);
3078 Phi->addIncoming(PREInstr, PREPred);
3085 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3088 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3091 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3094 removeInstruction(CurInst);
3103 bool Changed =
false;
3106 if (CurrentBlock == &
F.getEntryBlock())
3110 if (CurrentBlock->isEHPad())
3114 BE = CurrentBlock->end();
3117 Changed |= performScalarPRE(CurInst);
3121 if (splitCriticalEdges())
3138 InvalidBlockRPONumbers =
true;
3145bool GVNPass::splitCriticalEdges() {
3146 if (toSplit.empty())
3149 bool Changed =
false;
3151 std::pair<Instruction *, unsigned> Edge = toSplit.pop_back_val();
3155 }
while (!toSplit.empty());
3159 InvalidBlockRPONumbers =
true;
3165bool GVNPass::iterateOnFunction(
Function &
F) {
3166 cleanupGlobalSets();
3169 bool Changed =
false;
3176 Changed |= processBlock(BB);
3181void GVNPass::cleanupGlobalSets() {
3183 LeaderTable.clear();
3184 BlockRPONumber.clear();
3186 InvalidBlockRPONumbers =
true;
3197 I->eraseFromParent();
3202void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3204 LeaderTable.verifyRemoved(Inst);
3216 while (!NewDead.
empty()) {
3218 if (DeadBlocks.count(
D))
3224 DeadBlocks.insert(Dom.
begin(), Dom.
end());
3229 if (DeadBlocks.count(S))
3232 bool AllPredDead =
true;
3234 if (!DeadBlocks.count(
P)) {
3235 AllPredDead =
false;
3256 if (DeadBlocks.count(
B))
3263 if (!DeadBlocks.count(
P))
3269 DeadBlocks.insert(
P = S);
3275 if (!DeadBlocks.count(
P))
3299bool GVNPass::processFoldableCondBr(
BranchInst *BI) {
3313 if (DeadBlocks.count(DeadRoot))
3317 DeadRoot = splitCriticalEdges(BI->
getParent(), DeadRoot);
3319 addDeadBlock(DeadRoot);
3327void GVNPass::assignValNumForDeadCode() {
3331 LeaderTable.insert(ValNum, &Inst, BB);
3346 if (skipFunction(
F))
3349 auto *MSSAWP = getAnalysisIfAvailable<MemorySSAWrapperPass>();
3350 return Impl.runImpl(
3351 F, getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F),
3352 getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
3353 getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F),
3354 getAnalysis<AAResultsWrapperPass>().getAAResults(),
3355 Impl.isMemDepEnabled()
3356 ? &getAnalysis<MemoryDependenceWrapperPass>().getMemDep()
3358 getAnalysis<LoopInfoWrapperPass>().getLoopInfo(),
3359 &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(),
3360 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
3368 if (Impl.isMemDepEnabled())
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool hasUsersIn(Value *V, BasicBlock *BB)
static void reportMayClobberedLoad(LoadInst *Load, MemDepResult DepInfo, DominatorTree *DT, OptimizationRemarkEmitter *ORE)
Try to locate the three instruction involved in a missed load-elimination case that is due to an inte...
static void reportLoadElim(LoadInst *Load, Value *AvailableValue, OptimizationRemarkEmitter *ORE)
static cl::opt< uint32_t > MaxNumInsnsPerBlock("gvn-max-num-insns", cl::Hidden, cl::init(100), cl::desc("Max number of instructions to scan in each basic block in GVN " "(default = 100)"))
static cl::opt< bool > GVNEnableMemDep("enable-gvn-memdep", cl::init(true))
static cl::opt< bool > GVNEnableLoadInLoopPRE("enable-load-in-loop-pre", cl::init(true))
static cl::opt< uint32_t > MaxNumDeps("gvn-max-num-deps", cl::Hidden, cl::init(100), cl::desc("Max number of dependences to attempt Load PRE (default = 100)"))
static Value * ConstructSSAForLoadSet(LoadInst *Load, SmallVectorImpl< AvailableValueInBlock > &ValuesPerBlock, GVNPass &gvn)
Given a set of loads specified by ValuesPerBlock, construct SSA form, allowing us to eliminate Load.
static bool isOnlyReachableViaThisEdge(const BasicBlockEdge &E, DominatorTree *DT)
There is an edge from 'Src' to 'Dst'.
static bool impliesEquivalanceIfFalse(CmpInst *Cmp)
static bool IsValueFullyAvailableInBlock(BasicBlock *BB, DenseMap< BasicBlock *, AvailabilityState > &FullyAvailableBlocks)
Return true if we can prove that the value we're analyzing is fully available in the specified block.
static Value * findDominatingValue(const MemoryLocation &Loc, Type *LoadTy, Instruction *From, AAResults *AA)
static bool isLifetimeStart(const Instruction *Inst)
static cl::opt< bool > GVNEnableSplitBackedgeInLoadPRE("enable-split-backedge-in-load-pre", cl::init(false))
static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl)
static void replaceValuesPerBlockEntry(SmallVectorImpl< AvailableValueInBlock > &ValuesPerBlock, Value *OldValue, Value *NewValue)
If the specified OldValue exists in ValuesPerBlock, replace its value with NewValue.
static bool impliesEquivalanceIfTrue(CmpInst *Cmp)
@ Unavailable
We know the block is not fully available. This is a fixpoint.
@ Available
We know the block is fully available. This is a fixpoint.
@ SpeculativelyAvailable
We do not know whether the block is fully available or not, but we are currently speculating that it ...
static cl::opt< bool > GVNEnablePRE("enable-pre", cl::init(true), cl::Hidden)
static cl::opt< uint32_t > MaxNumVisitedInsts("gvn-max-num-visited-insts", cl::Hidden, cl::init(100), cl::desc("Max number of visited instructions when trying to find " "dominating value of select dependency (default = 100)"))
static cl::opt< uint32_t > MaxBBSpeculations("gvn-max-block-speculations", cl::Hidden, cl::init(600), cl::desc("Max number of blocks we're willing to speculate on (and recurse " "into) when deducing if a value is fully available or not in GVN " "(default = 600)"))
static bool liesBetween(const Instruction *From, Instruction *Between, const Instruction *To, DominatorTree *DT)
Assuming To can be reached from both From and Between, does Between lie on every path from From to To...
static cl::opt< bool > GVNEnableLoadPRE("enable-load-pre", cl::init(true))
This file provides the interface for LLVM's Global Value Numbering pass which eliminates fully redund...
This is the interface for a simple mod/ref and alias analysis over globals.
This defines the Use class.
static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
This file implements a map that provides insertion order iteration.
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
ppc ctr loops PowerPC CTR Loops Verify
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static const uint32_t IV[8]
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This represents the llvm.assume intrinsic.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
const BasicBlock * getEnd() const
const BasicBlock * getStart() const
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
LLVMContext & getContext() const
Get the context in which this basic block lives.
bool isEHPad() const
Return true if this basic block is an exception handling block.
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...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Instruction::BinaryOps getBinaryOp() const
Returns the binary operation underlying the intrinsic.
Conditional or Unconditional Branch instruction.
BasicBlock * getSuccessor(unsigned i) const
bool isUnconditional() const
Value * getCondition() const
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
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.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
static ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getFalse(LLVMContext &Context)
This is an important base class in LLVM.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
Analysis pass which computes a DominatorTree.
void getDescendants(NodeT *R, SmallVectorImpl< NodeT * > &Result) const
Get all nodes dominated by R, including R itself.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class representing an expression and its matching format.
FunctionPass class - This class is used to implement most global optimizations.
Represents calls to the gc.relocate intrinsic.
This class holds the mapping between values and value numbers.
uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred, Value *LHS, Value *RHS)
Returns the value number of the given comparison, assigning it a new number if it did not have one be...
uint32_t getNextUnusedValueNumber()
uint32_t lookupOrAdd(Value *V)
lookup_or_add - Returns the value number for the specified value, assigning it a new number if it did...
uint32_t lookup(Value *V, bool Verify=true) const
Returns the value number of the specified value.
void setAliasAnalysis(AAResults *A)
void clear()
Remove all entries from the ValueTable.
bool exists(Value *V) const
Returns true if a value number exists for the specified value.
uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock, uint32_t Num, GVNPass &Gvn)
Wrap phiTranslateImpl to provide caching functionality.
void setMemDep(MemoryDependenceResults *M)
void erase(Value *v)
Remove a value from the value numbering.
void add(Value *V, uint32_t num)
add - Insert a value into the table with a specified value number.
void setDomTree(DominatorTree *D)
void eraseTranslateCacheEntry(uint32_t Num, const BasicBlock &CurrBlock)
Erase stale entry from phiTranslate cache so phiTranslate can be computed again.
void verifyRemoved(const Value *) const
verifyRemoved - Verify that the value is removed from all internal data structures.
The core GVN pass object.
friend class gvn::GVNLegacyPass
bool isPREEnabled() const
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
AAResults * getAliasAnalysis() const
bool isLoadPREEnabled() const
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
DominatorTree & getDominatorTree() const
bool isLoadInLoopPREEnabled() const
bool isLoadPRESplitBackedgeEnabled() const
void markInstructionForDeletion(Instruction *I)
This removes the specified instruction from our various maps and marks it for deletion.
bool isMemDepEnabled() const
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Legacy wrapper pass to provide the GlobalsAAResult object.
This class allows to keep track on instructions with implicit control flow.
bool isDominatedByICFIFromSameBlock(const Instruction *Insn)
Returns true if the first ICFI of Insn's block exists and dominates Insn.
bool hasICF(const BasicBlock *BB)
Returns true if at least one instruction from the given basic block has implicit control flow.
void clear()
Invalidates all information from this tracking.
void removeUsersOf(const Instruction *Inst)
Notifies this tracking that we are going to replace all uses of Inst.
void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB)
Notifies this tracking that we are going to insert a new instruction Inst to the basic block BB.
void removeInstruction(const Instruction *Inst)
Notifies this tracking that we are going to remove the instruction Inst It makes all necessary update...
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Instruction * getPrevNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the previous non-debug instruction in the same basic block as 'this',...
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs=std::nullopt)
Drop all unknown metadata except for debug locations.
bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
This class implements a map that also provides access to all stored values in a deterministic order.
iterator find(const KeyT &Key)
A memory dependence query can return one of three different answers.
bool isClobber() const
Tests if this MemDepResult represents a query that is an instruction clobber dependency.
bool isNonLocal() const
Tests if this MemDepResult represents a query that is transparent to the start of the block,...
bool isDef() const
Tests if this MemDepResult represents a query that is an instruction definition dependency.
bool isLocal() const
Tests if this MemDepResult represents a valid local query (Clobber/Def).
Instruction * getInst() const
If this is a normal dependency, returns the instruction that is depended on.
This is the common base class for memset/memcpy/memmove.
An analysis that produces MemoryDependenceResults for a function.
Provides a lazy, caching interface for making common memory aliasing information queries,...
std::vector< NonLocalDepEntry > NonLocalDepInfo
void invalidateCachedPredecessors()
Clears the PredIteratorCache info.
void invalidateCachedPointerInfo(Value *Ptr)
Invalidates cached information about the specified pointer, because it may be too conservative in mem...
std::optional< int32_t > getClobberOffset(LoadInst *DepInst) const
Return the clobber offset to dependent instruction.
void removeInstruction(Instruction *InstToRemove)
Removes an instruction from the dependence analysis, updating the dependence of instructions that pre...
MemDepResult getDependency(Instruction *QueryInst)
Returns the instruction on which a memory operation depends.
const NonLocalDepInfo & getNonLocalCallDependency(CallBase *QueryCall)
Perform a full dependency query for the specified call, returning the set of blocks that the value is...
void getNonLocalPointerDependency(Instruction *QueryInst, SmallVectorImpl< NonLocalDepResult > &Result)
Perform a full dependency query for an access to the QueryInst's specified memory location,...
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance.
Representation for a specific memory location.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
const Value * Ptr
The address of the start of the location.
An analysis that produces MemorySSA for a function.
MemorySSA * getMemorySSA() const
Get handle on MemorySSA.
MemoryUseOrDef * createMemoryAccessBefore(Instruction *I, MemoryAccess *Definition, MemoryUseOrDef *InsertPt)
Create a MemoryAccess in MemorySSA before an existing MemoryAccess.
void insertDef(MemoryDef *Def, bool RenameUses=false)
Insert a definition into the MemorySSA IR.
MemoryAccess * createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition, const BasicBlock *BB, MemorySSA::InsertionPlace Point)
Create a MemoryAccess in MemorySSA at a specified point in a block.
void insertUse(MemoryUse *Use, bool RenameUses=false)
void removeMemoryAccess(MemoryAccess *, bool OptimizePhis=false)
Remove a MemoryAccess from MemorySSA, including updating all definitions and uses.
Legacy analysis pass which computes MemorySSA.
Encapsulates MemorySSA, including all data associated with memory accesses.
const AccessList * getBlockAccesses(const BasicBlock *BB) const
Return the list of MemoryAccess's for a given basic block.
void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
Class that has the common methods + fields of memory uses/defs.
This is an entry in the NonLocalDepInfo cache.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
PHITransAddr - An address value which tracks and handles phi translation.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
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 preserve()
Mark an analysis as preserved.
Helper class for SSA formation on a set of values defined in multiple blocks.
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
bool HasValueForBlock(BasicBlock *BB) const
Return true if the SSAUpdater already has a value for the specified block.
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
This class represents the LLVM 'select' instruction.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)
const Value * getCondition() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
SmallVector & operator=(const SmallVector &RHS)
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt8Ty(LLVMContext &C)
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
bool canBeFreed() const
Return true if the memory object referred to by V can by freed in the scope for which the SSA value d...
void deleteValue()
Delete a pointer to a generic Value.
StringRef getName() const
Return a constant reference to the value's name.
Represents an op.with.overflow intrinsic.
An efficient, type-erasing, non-owning reference to a callable.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
GVNLegacyPass(bool NoMemDepAnalysis=!GVNEnableMemDep)
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
An opaque object representing a hash code.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
bool match(Val *V, const Pattern &P)
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
BinaryOp_match< cst_pred_ty< is_all_ones >, ValTy, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
Value * getValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, Instruction *InsertPt, const DataLayout &DL)
If analyzeLoadFromClobberingStore/Load returned an offset, this function can be used to actually perf...
int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, StoreInst *DepSI, const DataLayout &DL)
This function determines whether a value for the pointer LoadPtr can be extracted from the store at D...
Value * getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, Type *LoadTy, Instruction *InsertPt, const DataLayout &DL)
If analyzeLoadFromClobberingMemInst returned an offset, this function can be used to actually perform...
int analyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr, LoadInst *DepLI, const DataLayout &DL)
This function determines whether a value for the pointer LoadPtr can be extracted from the load at De...
int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, MemIntrinsic *DepMI, const DataLayout &DL)
This function determines whether a value for the pointer LoadPtr can be extracted from the memory int...
bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, const DataLayout &DL)
Return true if CoerceAvailableValueToLoadType would succeed if it was called.
initializer< Ty > init(const Ty &Val)
A private "module" namespace for types and utilities used by GVN.
NodeAddr< InstrNode * > Instr
NodeAddr< PhiNode * > Phi
This is an optimization pass for GlobalISel generic memory operations.
pred_iterator pred_end(BasicBlock *BB)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
unsigned replaceDominatedUsesWithIf(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge, function_ref< bool(const Use &U, const Value *To)> ShouldReplace)
Replace each use of 'From' with 'To' if that use is dominated by the given edge and the callback Shou...
unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ)
Search for the specified successor of basic block BB and return its position in the terminator instru...
void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
auto successors(const MachineBasicBlock *BB)
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...
bool isAssumeWithEmptyBundle(const AssumeInst &Assume)
Return true iff the operand bundles of the provided llvm.assume doesn't contain any valuable informat...
Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
void initializeGVNLegacyPassPass(PassRegistry &)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
pred_iterator pred_begin(BasicBlock *BB)
bool canReplacePointersInUseIfEqual(const Use &U, const Value *To, const DataLayout &DL)
bool canReplacePointersIfEqual(const Value *From, const Value *To, const DataLayout &DL)
Returns true if a pointer value From can be replaced with another pointer value \To if they are deeme...
bool isModSet(const ModRefInfo MRI)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void patchReplacementInstruction(Instruction *I, Value *Repl)
Patch the replacement so that it is not more restrictive than the value being replaced.
bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge)
Replace each use of 'From' with 'To' if that use is dominated by the given edge.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
@ Global
Append to llvm.global_dtors.
void combineMetadataForCSE(Instruction *K, const Instruction *J, bool DoesKMove)
Combine the metadata of two instructions so that K can replace J.
bool VerifyMemorySSA
Enables verification of MemorySSA.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
bool salvageKnowledge(Instruction *I, AssumptionCache *AC=nullptr, DominatorTree *DT=nullptr)
Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert if before I.
bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, MemoryDependenceResults *MemDep=nullptr, bool PredecessorWithTwoSuccessors=false, DominatorTree *DT=nullptr)
Attempts to merge a block into its predecessor, if possible.
BasicBlock * SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")
If this edge is a critical edge, insert a new node to split the critical edge.
FunctionPass * createGVNPass(bool NoMemDepAnalysis=false)
Create a legacy GVN pass.
bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges=false)
Return true if the specified edge is a critical edge.
constexpr unsigned BitWidth
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
bool pred_empty(const BasicBlock *BB)
iterator_range< df_iterator< T > > depth_first(const T &G)
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
bool EliminateDuplicatePHINodes(BasicBlock *BB)
Check for and eliminate duplicate PHI nodes in this block.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
Option class for critical edge splitting.
static GVNPass::Expression getTombstoneKey()
static bool isEqual(const GVNPass::Expression &LHS, const GVNPass::Expression &RHS)
static unsigned getHashValue(const GVNPass::Expression &e)
static GVNPass::Expression getEmptyKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
A set of parameters to control various transforms performed by GVN pass.
std::optional< bool > AllowLoadPRESplitBackedge
std::optional< bool > AllowPRE
std::optional< bool > AllowLoadInLoopPRE
std::optional< bool > AllowMemDep
std::optional< bool > AllowLoadPRE
SmallVector< uint32_t, 4 > varargs
bool operator==(const Expression &other) const
friend hash_code hash_value(const Expression &Value)
Expression(uint32_t o=~2U)
A CRTP mix-in to automatically provide informational APIs needed for passes.
Represents an AvailableValue which can be rematerialized at the end of the associated BasicBlock.
static AvailableValueInBlock get(BasicBlock *BB, Value *V, unsigned Offset=0)
static AvailableValueInBlock getUndef(BasicBlock *BB)
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV)
Value * MaterializeAdjustedValue(LoadInst *Load, GVNPass &gvn) const
Emit code at the end of this block to adjust the value defined here to the specified type.
AvailableValue AV
AV - The actual available value.
static AvailableValueInBlock getSelect(BasicBlock *BB, SelectInst *Sel, Value *V1, Value *V2)
BasicBlock * BB
BB - The basic block in question.
Represents a particular available value that we know how to materialize.
unsigned Offset
Offset - The byte offset in Val that is interesting for the load query.
bool isSimpleValue() const
static AvailableValue getSelect(SelectInst *Sel, Value *V1, Value *V2)
bool isCoercedLoadValue() const
static AvailableValue get(Value *V, unsigned Offset=0)
ValType Kind
Kind of the live-out value.
LoadInst * getCoercedLoadValue() const
static AvailableValue getLoad(LoadInst *Load, unsigned Offset=0)
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset=0)
bool isUndefValue() const
bool isSelectValue() const
Value * Val
Val - The value that is live out of the block.
Value * V1
V1, V2 - The dominating non-clobbered values of SelectVal.
Value * MaterializeAdjustedValue(LoadInst *Load, Instruction *InsertPt, GVNPass &gvn) const
Emit code at the specified insertion point to adjust the value defined here to the specified type.
static AvailableValue getUndef()
SelectInst * getSelectValue() const
Value * getSimpleValue() const
bool isMemIntrinValue() const
MemIntrinsic * getMemIntrinValue() const