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");
122 cl::desc(
"The number of memory accesses to scan in a block in reaching "
123 "memory values analysis (default = 100)"));
127 cl::desc(
"Max number of dependences to attempt Load PRE (default = 100)"));
132 cl::desc(
"Max number of blocks we're willing to speculate on (and recurse "
133 "into) when deducing if a value is fully available or not in GVN "
138 cl::desc(
"Max number of visited instructions when trying to find "
139 "dominating value of select dependency (default = 100)"));
143 cl::desc(
"Max number of instructions to scan in each basic block in GVN "
159 if (
Opcode != Other.Opcode)
167 if ((!
Attrs.isEmpty() || !Other.Attrs.isEmpty()) &&
168 !
Attrs.intersectWith(
Ty->getContext(), Other.Attrs).has_value())
304 Res.
AV = std::move(
AV);
325 return AV.MaterializeAdjustedValue(Load,
BB->getTerminator());
336 E.Opcode =
I->getOpcode();
341 E.VarArgs.push_back(
lookupOrAdd(GCR->getOperand(0)));
342 E.VarArgs.push_back(
lookupOrAdd(GCR->getBasePtr()));
343 E.VarArgs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
345 for (
Use &
Op :
I->operands())
348 if (
I->isCommutative()) {
353 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
354 if (
E.VarArgs[0] >
E.VarArgs[1])
356 E.Commutative =
true;
362 if (
E.VarArgs[0] >
E.VarArgs[1]) {
367 E.Commutative =
true;
369 E.VarArgs.append(IVI->idx_begin(), IVI->idx_end());
371 ArrayRef<int> ShuffleMask = SVI->getShuffleMask();
372 E.VarArgs.append(ShuffleMask.
begin(), ShuffleMask.
end());
374 E.Attrs = CB->getAttributes();
380GVNPass::Expression GVNPass::ValueTable::createCmpExpr(
382 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
383 "Not a comparison!");
386 E.VarArgs.push_back(lookupOrAdd(
LHS));
387 E.VarArgs.push_back(lookupOrAdd(
RHS));
390 if (
E.VarArgs[0] >
E.VarArgs[1]) {
394 E.Opcode = (Opcode << 8) | Predicate;
395 E.Commutative =
true;
400GVNPass::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) {
401 assert(EI &&
"Not an ExtractValueInst?");
412 E.VarArgs.push_back(lookupOrAdd(WO->
getLHS()));
413 E.VarArgs.push_back(lookupOrAdd(WO->
getRHS()));
421 E.VarArgs.push_back(lookupOrAdd(
Op));
428GVNPass::Expression GVNPass::ValueTable::createGEPExpr(GetElementPtrInst *
GEP) {
430 Type *PtrTy =
GEP->getType()->getScalarType();
431 const DataLayout &
DL =
GEP->getDataLayout();
432 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
433 SmallMapVector<Value *, APInt, 4> VariableOffsets;
435 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
439 E.Opcode =
GEP->getOpcode();
441 E.VarArgs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
442 for (
const auto &[V, Scale] : VariableOffsets) {
443 E.VarArgs.push_back(lookupOrAdd(V));
444 E.VarArgs.push_back(lookupOrAdd(ConstantInt::get(
Context, Scale)));
446 if (!ConstantOffset.isZero())
448 lookupOrAdd(ConstantInt::get(
Context, ConstantOffset)));
452 E.Opcode =
GEP->getOpcode();
453 E.Ty =
GEP->getSourceElementType();
454 for (Use &
Op :
GEP->operands())
455 E.VarArgs.push_back(lookupOrAdd(
Op));
464GVNPass::ValueTable::ValueTable() =
default;
465GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
466GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
467GVNPass::ValueTable::~ValueTable() =
default;
473 ValueNumbering.
insert(std::make_pair(V, Num));
475 NumberingPhi[Num] = PN;
485 assert(MSSA &&
"addMemoryStateToExp should not be called without MemorySSA");
486 assert(MSSA->getMemoryAccess(
I) &&
"Instruction does not access memory");
487 MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(
I);
488 Exp.VarArgs.push_back(lookupOrAdd(MA));
499 if (
C->getFunction()->isPresplitCoroutine()) {
500 ValueNumbering[
C] = NextValueNumber;
501 return NextValueNumber++;
507 if (
C->isConvergent()) {
508 ValueNumbering[
C] = NextValueNumber;
509 return NextValueNumber++;
512 if (AA->doesNotAccessMemory(
C)) {
514 uint32_t
E = assignExpNewValueNum(Exp).first;
515 ValueNumbering[
C] =
E;
519 if (MD && AA->onlyReadsMemory(
C)) {
521 auto [
E, IsValNumNew] = assignExpNewValueNum(Exp);
523 ValueNumbering[
C] =
E;
527 MemDepResult LocalDep = MD->getDependency(
C);
530 ValueNumbering[
C] = NextValueNumber;
531 return NextValueNumber++;
534 if (LocalDep.
isDef()) {
539 if (!LocalDepCall || LocalDepCall->
arg_size() !=
C->arg_size()) {
540 ValueNumbering[
C] = NextValueNumber;
541 return NextValueNumber++;
544 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
545 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
546 uint32_t LocalDepCallVN = lookupOrAdd(LocalDepCall->
getArgOperand(
I));
547 if (CVN != LocalDepCallVN) {
548 ValueNumbering[
C] = NextValueNumber;
549 return NextValueNumber++;
553 uint32_t
V = lookupOrAdd(LocalDepCall);
554 ValueNumbering[
C] =
V;
560 MD->getNonLocalCallDependency(
C);
562 CallInst *CDep =
nullptr;
566 for (
const NonLocalDepEntry &
I : Deps) {
567 if (
I.getResult().isNonLocal())
572 if (!
I.getResult().isDef() || CDep !=
nullptr) {
579 if (NonLocalDepCall && DT->properlyDominates(
I.getBB(),
C->getParent())) {
580 CDep = NonLocalDepCall;
589 ValueNumbering[
C] = NextValueNumber;
590 return NextValueNumber++;
594 ValueNumbering[
C] = NextValueNumber;
595 return NextValueNumber++;
597 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
598 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
601 ValueNumbering[
C] = NextValueNumber;
602 return NextValueNumber++;
606 uint32_t
V = lookupOrAdd(CDep);
607 ValueNumbering[
C] =
V;
611 if (MSSA && IsMSSAEnabled && AA->onlyReadsMemory(
C)) {
613 addMemoryStateToExp(
C, Exp);
614 auto [
V,
_] = assignExpNewValueNum(Exp);
615 ValueNumbering[
C] =
V;
619 ValueNumbering[
C] = NextValueNumber;
620 return NextValueNumber++;
624uint32_t GVNPass::ValueTable::computeLoadStoreVN(Instruction *
I) {
625 if (!MSSA || !IsMSSAEnabled) {
626 ValueNumbering[
I] = NextValueNumber;
627 return NextValueNumber++;
631 Exp.Ty =
I->getType();
632 Exp.Opcode =
I->getOpcode();
633 for (Use &
Op :
I->operands())
634 Exp.VarArgs.push_back(lookupOrAdd(
Op));
635 addMemoryStateToExp(
I, Exp);
637 auto [
V,
_] = assignExpNewValueNum(Exp);
638 ValueNumbering[
I] =
V;
643bool GVNPass::ValueTable::exists(
Value *V)
const {
644 return ValueNumbering.contains(V);
656 auto VI = ValueNumbering.find(V);
657 if (VI != ValueNumbering.end())
662 ValueNumbering[V] = NextValueNumber;
665 return NextValueNumber++;
669 switch (
I->getOpcode()) {
670 case Instruction::Call:
672 case Instruction::FNeg:
673 case Instruction::Add:
674 case Instruction::FAdd:
675 case Instruction::Sub:
676 case Instruction::FSub:
677 case Instruction::Mul:
678 case Instruction::FMul:
679 case Instruction::UDiv:
680 case Instruction::SDiv:
681 case Instruction::FDiv:
682 case Instruction::URem:
683 case Instruction::SRem:
684 case Instruction::FRem:
685 case Instruction::Shl:
686 case Instruction::LShr:
687 case Instruction::AShr:
688 case Instruction::And:
689 case Instruction::Or:
690 case Instruction::Xor:
691 case Instruction::ICmp:
692 case Instruction::FCmp:
693 case Instruction::Trunc:
694 case Instruction::ZExt:
695 case Instruction::SExt:
696 case Instruction::FPToUI:
697 case Instruction::FPToSI:
698 case Instruction::UIToFP:
699 case Instruction::SIToFP:
700 case Instruction::FPTrunc:
701 case Instruction::FPExt:
702 case Instruction::PtrToInt:
703 case Instruction::PtrToAddr:
704 case Instruction::IntToPtr:
705 case Instruction::AddrSpaceCast:
706 case Instruction::BitCast:
707 case Instruction::Select:
708 case Instruction::Freeze:
709 case Instruction::ExtractElement:
710 case Instruction::InsertElement:
711 case Instruction::ShuffleVector:
712 case Instruction::InsertValue:
715 case Instruction::GetElementPtr:
718 case Instruction::ExtractValue:
721 case Instruction::PHI:
722 ValueNumbering[V] = NextValueNumber;
724 return NextValueNumber++;
725 case Instruction::Load:
726 case Instruction::Store:
727 return computeLoadStoreVN(
I);
729 ValueNumbering[V] = NextValueNumber;
730 return NextValueNumber++;
733 uint32_t E = assignExpNewValueNum(Exp).first;
734 ValueNumbering[V] = E;
741 auto VI = ValueNumbering.find(V);
743 assert(VI != ValueNumbering.end() &&
"Value not numbered?");
746 return (VI != ValueNumbering.end()) ? VI->second : 0;
753uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
756 Expression Exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
757 return assignExpNewValueNum(Exp).first;
762 ValueNumbering.clear();
763 ExpressionNumbering.clear();
764 NumberingPhi.clear();
766 PhiTranslateTable.clear();
775 uint32_t Num = ValueNumbering.lookup(V);
776 ValueNumbering.erase(V);
779 NumberingPhi.erase(Num);
781 NumberingBB.erase(Num);
786void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
787 assert(!ValueNumbering.contains(V) &&
788 "Inst still occurs in value numbering map!");
797 const auto &[It, Inserted] = NumToLeaders.try_emplace(
N, V, BB,
nullptr);
800 auto *NewSlot = TableAllocator.Allocate<LeaderListNode>();
801 new (NewSlot) LeaderListNode(V, BB, It->second.Next);
802 It->second.Next = NewSlot;
810 auto It = NumToLeaders.find(
N);
811 if (It == NumToLeaders.end())
814 LeaderListNode *Prev =
nullptr;
815 LeaderListNode *Curr = &It->second;
817 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
827 Prev->Next = Curr->Next;
828 Curr->~LeaderListNode();
829 TableAllocator.Deallocate<LeaderListNode>(Curr);
834 NumToLeaders.erase(It);
837 LeaderListNode *
Next = Curr->Next;
838 Curr->Entry.Val = std::move(
Next->Entry.Val);
839 Curr->Entry.BB =
Next->Entry.BB;
840 Curr->Next =
Next->Next;
841 Next->~LeaderListNode();
842 TableAllocator.Deallocate<LeaderListNode>(
Next);
864 return Options.AllowLoadPRESplitBackedge.value_or(
891 "On-demand computation of MemSSA implies that MemDep is disabled!");
895 bool Changed = runImpl(
F, AC, DT, TLI, AA, MemDep, LI, &ORE,
896 MSSA ? &MSSA->getMSSA() :
nullptr);
911 OS, MapClassName2PassName);
914 if (Options.AllowScalarPRE != std::nullopt)
915 OS << (*Options.AllowScalarPRE ?
"" :
"no-") <<
"scalar-pre;";
916 if (Options.AllowLoadPRE != std::nullopt)
917 OS << (*Options.AllowLoadPRE ?
"" :
"no-") <<
"load-pre;";
918 if (Options.AllowLoadPRESplitBackedge != std::nullopt)
919 OS << (*Options.AllowLoadPRESplitBackedge ?
"" :
"no-")
920 <<
"split-backedge-load-pre;";
921 if (Options.AllowMemDep != std::nullopt)
922 OS << (*Options.AllowMemDep ?
"" :
"no-") <<
"memdep;";
923 if (Options.AllowMemorySSA != std::nullopt)
924 OS << (*Options.AllowMemorySSA ?
"" :
"no-") <<
"memoryssa";
931 removeInstruction(
I);
934#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
937 for (
const auto &[Num, Exp] : Map) {
938 errs() << Num <<
"\n";
969 std::optional<BasicBlock *> UnavailableBB;
973 unsigned NumNewNewSpeculativelyAvailableBBs = 0;
981 while (!Worklist.
empty()) {
985 std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator,
bool>
IV =
993 UnavailableBB = CurrBB;
1004 ++NumNewNewSpeculativelyAvailableBBs;
1010 MaxBBSpeculationCutoffReachedTimes += (int)OutOfBudget;
1012 UnavailableBB = CurrBB;
1018 NewSpeculativelyAvailableBBs.
insert(CurrBB);
1024#if LLVM_ENABLE_STATS
1025 IsValueFullyAvailableInBlockNumSpeculationsMax.updateMax(
1026 NumNewNewSpeculativelyAvailableBBs);
1031 auto MarkAsFixpointAndEnqueueSuccessors =
1033 auto It = FullyAvailableBlocks.
find(BB);
1034 if (It == FullyAvailableBlocks.
end())
1041 State = FixpointState;
1044 "Found a speculatively available successor leftover?");
1052 if (UnavailableBB) {
1059 while (!Worklist.
empty())
1060 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1068 while (!Worklist.
empty())
1069 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1073 "Must have fixed all the new speculatively available blocks.");
1076 return !UnavailableBB;
1085 if (V.AV.Val == OldValue)
1086 V.AV.Val = NewValue;
1087 if (V.AV.isSelectValue()) {
1088 if (V.AV.V1 == OldValue)
1090 if (V.AV.V2 == OldValue)
1105 if (ValuesPerBlock.
size() == 1 &&
1107 Load->getParent())) {
1108 assert(!ValuesPerBlock[0].AV.isUndefValue() &&
1109 "Dead BB dominate this block");
1110 return ValuesPerBlock[0].MaterializeAdjustedValue(Load);
1116 SSAUpdate.
Initialize(Load->getType(), Load->getName());
1121 if (AV.AV.isUndefValue())
1131 if (BB == Load->getParent() &&
1132 ((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() == Load) ||
1133 (AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() == Load)))
1146 Type *LoadTy = Load->getType();
1150 if (Res->
getType() != LoadTy) {
1165 Load->getFunction());
1175 if (!CoercedLoad->
hasMetadata(LLVMContext::MD_noundef))
1177 {LLVMContext::MD_dereferenceable,
1178 LLVMContext::MD_dereferenceable_or_null,
1179 LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group});
1195 assert(
V1 &&
V2 &&
"both value operands of the select must be present");
1204 assert(Res &&
"failed to materialize?");
1210 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1227 Value *PtrOp = Load->getPointerOperand();
1233 for (
auto *U : PtrOp->
users()) {
1236 if (
I->getFunction() == Load->getFunction() && DT->
dominates(
I, Load)) {
1254 for (
auto *U : PtrOp->
users()) {
1257 if (
I->getFunction() == Load->getFunction() &&
1265 OtherAccess =
nullptr;
1284 using namespace ore;
1287 R <<
"load of type " << NV(
"Type", Load->getType()) <<
" not eliminated"
1292 R <<
" in favor of " << NV(
"OtherAccess", OtherAccess);
1294 R <<
" because it is clobbered by " << NV(
"ClobberedBy", DepInst);
1308 for (
auto *Inst = BB == FromBB ? From : BB->
getTerminator();
1316 if (
SI->isSimple() &&
SI->getPointerOperand() ==
Loc.Ptr &&
1317 SI->getValueOperand()->getType() == LoadTy)
1318 return SI->getValueOperand();
1322 if (LI->getPointerOperand() ==
Loc.Ptr && LI->getType() == LoadTy)
1328std::optional<AvailableValue>
1329GVNPass::AnalyzeLoadAvailability(LoadInst *Load,
const ReachingMemVal &Dep,
1331 assert(
Load->isUnordered() &&
"rules below are incorrect for ordered access");
1332 assert((Dep.Kind == DepKind::Def || Dep.Kind == DepKind::Clobber) &&
1333 "expected a local dependence");
1337 const DataLayout &
DL =
Load->getDataLayout();
1338 if (Dep.Kind == DepKind::Clobber) {
1344 if (
Address &&
Load->isAtomic() <= DepSI->isAtomic()) {
1360 if (DepLoad != Load &&
Address &&
1361 Load->isAtomic() <= DepLoad->isAtomic()) {
1368 DepLoad->getFunction())) {
1369 const auto ClobberOff = MD->getClobberOffset(DepLoad);
1371 Offset = (ClobberOff == std::nullopt || *ClobberOff < 0)
1377 DepLoad->getFunction()) ||
1404 dbgs() <<
" is clobbered by " << *DepInst <<
'\n';);
1408 return std::nullopt;
1410 assert(Dep.Kind == DepKind::Def &&
"follows from above");
1417 if (Constant *InitVal =
1427 return std::nullopt;
1430 if (S->isAtomic() <
Load->isAtomic())
1431 return std::nullopt;
1442 return std::nullopt;
1445 if (
LD->isAtomic() <
Load->isAtomic())
1446 return std::nullopt;
1455 assert(Sel->getType() ==
Load->getPointerOperandType());
1461 return std::nullopt;
1466 return std::nullopt;
1474 dbgs() <<
" has unknown def " << *DepInst <<
'\n';);
1475 return std::nullopt;
1478void GVNPass::AnalyzeLoadAvailability(LoadInst *Load,
1479 SmallVectorImpl<ReachingMemVal> &Deps,
1480 AvailValInBlkVect &ValuesPerBlock,
1481 UnavailBlkVect &UnavailableBlocks) {
1486 for (
const auto &Dep : Deps) {
1489 if (DeadBlocks.count(DepBB)) {
1496 if (Dep.Kind == DepKind::Other) {
1497 UnavailableBlocks.push_back(DepBB);
1505 AnalyzeLoadAvailability(Load, Dep,
const_cast<Value *
>(Dep.Addr))) {
1509 ValuesPerBlock.push_back(
1512 UnavailableBlocks.push_back(DepBB);
1516 assert(Deps.size() == ValuesPerBlock.size() + UnavailableBlocks.size() &&
1517 "post condition violation");
1539LoadInst *GVNPass::findLoadToHoistIntoPred(BasicBlock *Pred, BasicBlock *LoadBB,
1543 if (
Term->getNumSuccessors() != 2 ||
Term->isSpecialTerminator())
1545 auto *SuccBB =
Term->getSuccessor(0);
1546 if (SuccBB == LoadBB)
1547 SuccBB =
Term->getSuccessor(1);
1548 if (!SuccBB->getSinglePredecessor())
1552 for (Instruction &Inst : *SuccBB) {
1553 if (Inst.isDebugOrPseudoInst())
1555 if (--NumInsts == 0)
1558 if (!Inst.isIdenticalTo(Load))
1561 bool HasLocalDep =
true;
1563 MemDepResult Dep = MD->getDependency(&Inst);
1566 auto *MSSA = MSSAU->getMemorySSA();
1568 if (
auto *MA = MSSA->getMemoryAccess(&Inst); MA &&
isa<MemoryUse>(MA)) {
1569 auto *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(MA);
1570 HasLocalDep = Clobber->getBlock() == SuccBB;
1578 if (!HasLocalDep && !ICF->isDominatedByICFIFromSameBlock(&Inst))
1589void GVNPass::eliminatePartiallyRedundantLoad(
1590 LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1591 MapVector<BasicBlock *, Value *> &AvailableLoads,
1592 MapVector<BasicBlock *, LoadInst *> *CriticalEdgePredAndLoad) {
1593 for (
const auto &AvailableLoad : AvailableLoads) {
1594 BasicBlock *UnavailableBlock = AvailableLoad.first;
1595 Value *LoadPtr = AvailableLoad.second;
1597 auto *NewLoad =
new LoadInst(
1598 Load->getType(), LoadPtr,
Load->getName() +
".pre",
Load->isVolatile(),
1599 Load->getAlign(),
Load->getOrdering(),
Load->getSyncScopeID(),
1601 NewLoad->setDebugLoc(
Load->getDebugLoc());
1603 auto *NewAccess = MSSAU->createMemoryAccessInBB(
1606 MSSAU->insertDef(NewDef,
true);
1612 AAMDNodes Tags =
Load->getAAMetadata();
1614 NewLoad->setAAMetadata(Tags);
1616 if (
auto *MD =
Load->getMetadata(LLVMContext::MD_invariant_load))
1617 NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
1618 if (
auto *InvGroupMD =
Load->getMetadata(LLVMContext::MD_invariant_group))
1619 NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
1620 if (
auto *RangeMD =
Load->getMetadata(LLVMContext::MD_range))
1621 NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
1622 if (
auto *NoFPClassMD =
Load->getMetadata(LLVMContext::MD_nofpclass))
1623 NewLoad->setMetadata(LLVMContext::MD_nofpclass, NoFPClassMD);
1625 if (
auto *AccessMD =
Load->getMetadata(LLVMContext::MD_access_group))
1626 if (LI->getLoopFor(
Load->getParent()) == LI->getLoopFor(UnavailableBlock))
1627 NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
1636 ValuesPerBlock.push_back(
1639 MD->invalidateCachedPointerInfo(LoadPtr);
1644 if (CriticalEdgePredAndLoad) {
1645 auto It = CriticalEdgePredAndLoad->
find(UnavailableBlock);
1646 if (It != CriticalEdgePredAndLoad->
end()) {
1647 ++NumPRELoadMoved2CEPred;
1648 ICF->insertInstructionTo(NewLoad, UnavailableBlock);
1649 LoadInst *OldLoad = It->second;
1653 if (uint32_t ValNo = VN.lookup(OldLoad,
false))
1654 LeaderTable.erase(ValNo, OldLoad, OldLoad->
getParent());
1655 removeInstruction(OldLoad);
1663 ICF->removeUsersOf(Load);
1664 Load->replaceAllUsesWith(V);
1668 I->setDebugLoc(
Load->getDebugLoc());
1669 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
1670 MD->invalidateCachedPointerInfo(V);
1672 return OptimizationRemark(
DEBUG_TYPE,
"LoadPRE", Load)
1673 <<
"load eliminated by PRE";
1678bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1679 UnavailBlkVect &UnavailableBlocks) {
1688 SmallPtrSet<BasicBlock *, 4> Blockers(
llvm::from_range, UnavailableBlocks);
1710 bool MustEnsureSafetyOfSpeculativeExecution =
1711 ICF->isDominatedByICFIFromSameBlock(Load);
1715 if (TmpBB == LoadBB)
1717 if (Blockers.count(TmpBB))
1729 MustEnsureSafetyOfSpeculativeExecution =
1730 MustEnsureSafetyOfSpeculativeExecution || ICF->hasICF(TmpBB);
1738 MapVector<BasicBlock *, Value *> PredLoads;
1739 DenseMap<BasicBlock *, AvailabilityState> FullyAvailableBlocks;
1740 for (
const AvailableValueInBlock &AV : ValuesPerBlock)
1742 for (BasicBlock *UnavailableBB : UnavailableBlocks)
1750 MapVector<BasicBlock *, LoadInst *> CriticalEdgePredAndLoad;
1756 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
1757 << Pred->
getName() <<
"': " << *Load <<
'\n');
1768 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
1769 << Pred->
getName() <<
"': " << *Load <<
'\n');
1775 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
1776 << Pred->
getName() <<
"': " << *Load <<
'\n');
1782 if (DT->dominates(LoadBB, Pred)) {
1785 <<
"COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
1786 << Pred->
getName() <<
"': " << *Load <<
'\n');
1790 if (LoadInst *LI = findLoadToHoistIntoPred(Pred, LoadBB, Load))
1791 CriticalEdgePredAndLoad[Pred] = LI;
1796 PredLoads[Pred] =
nullptr;
1801 unsigned NumInsertPreds = PredLoads.
size() + CriticalEdgePredSplit.
size();
1802 unsigned NumUnavailablePreds = NumInsertPreds +
1803 CriticalEdgePredAndLoad.
size();
1804 assert(NumUnavailablePreds != 0 &&
1805 "Fully available value should already be eliminated!");
1806 (void)NumUnavailablePreds;
1812 if (NumInsertPreds > 1)
1817 if (MustEnsureSafetyOfSpeculativeExecution) {
1818 if (CriticalEdgePredSplit.
size())
1822 for (
auto &PL : PredLoads)
1826 for (
auto &CEP : CriticalEdgePredAndLoad)
1833 for (BasicBlock *OrigPred : CriticalEdgePredSplit) {
1834 BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
1835 assert(!PredLoads.count(OrigPred) &&
"Split edges shouldn't be in map!");
1836 PredLoads[NewPred] =
nullptr;
1837 LLVM_DEBUG(
dbgs() <<
"Split critical edge " << OrigPred->getName() <<
"->"
1838 << LoadBB->
getName() <<
'\n');
1841 for (
auto &CEP : CriticalEdgePredAndLoad)
1842 PredLoads[CEP.first] =
nullptr;
1845 bool CanDoPRE =
true;
1846 const DataLayout &
DL =
Load->getDataLayout();
1847 SmallVector<Instruction*, 8> NewInsts;
1848 for (
auto &PredLoad : PredLoads) {
1849 BasicBlock *UnavailablePred = PredLoad.first;
1859 Value *LoadPtr =
Load->getPointerOperand();
1861 while (Cur != LoadBB) {
1874 LoadPtr =
Address.translateWithInsertion(LoadBB, UnavailablePred, *DT,
1881 << *
Load->getPointerOperand() <<
"\n");
1886 PredLoad.second = LoadPtr;
1890 while (!NewInsts.
empty()) {
1900 return !CriticalEdgePredSplit.empty();
1906 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOAD: " << *Load <<
'\n');
1908 <<
" INSTS: " << *NewInsts.
back()
1912 for (Instruction *
I : NewInsts) {
1916 I->updateLocationAfterHoist();
1925 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, PredLoads,
1926 &CriticalEdgePredAndLoad);
1931bool GVNPass::performLoopLoadPRE(LoadInst *Load,
1932 AvailValInBlkVect &ValuesPerBlock,
1933 UnavailBlkVect &UnavailableBlocks) {
1934 const Loop *
L = LI->getLoopFor(
Load->getParent());
1936 if (!L ||
L->getHeader() !=
Load->getParent())
1941 if (!Preheader || !Latch)
1944 Value *LoadPtr =
Load->getPointerOperand();
1946 if (!
L->isLoopInvariant(LoadPtr))
1952 if (ICF->isDominatedByICFIFromSameBlock(Load))
1956 for (
auto *Blocker : UnavailableBlocks) {
1958 if (!
L->contains(Blocker))
1970 if (L != LI->getLoopFor(Blocker))
1978 if (DT->dominates(Blocker, Latch))
1982 if (Blocker->getTerminator()->mayWriteToMemory())
1985 LoopBlock = Blocker;
1997 MapVector<BasicBlock *, Value *> AvailableLoads;
1998 AvailableLoads[LoopBlock] = LoadPtr;
1999 AvailableLoads[Preheader] = LoadPtr;
2001 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOOP LOAD: " << *Load <<
'\n');
2002 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, AvailableLoads,
2010 using namespace ore;
2014 <<
"load of type " << NV(
"Type", Load->getType()) <<
" eliminated"
2015 << setExtraArgs() <<
" in favor of "
2022bool GVNPass::processNonLocalLoad(LoadInst *Load) {
2024 if (
Load->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2025 Load->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2030 MD->getNonLocalPointerDependency(Load, Deps);
2035 unsigned NumDeps = Deps.size();
2042 for (
const NonLocalDepResult &Dep : Deps) {
2043 const auto &
R = Dep.getResult();
2055 return processNonLocalLoad(Load, MemVals);
2058bool GVNPass::processNonLocalLoad(LoadInst *Load,
2059 SmallVectorImpl<ReachingMemVal> &Deps) {
2062 if (Deps.
size() == 1 && Deps[0].Kind == DepKind::Other) {
2064 dbgs() <<
" has unknown dependencies\n";);
2072 if (GetElementPtrInst *
GEP =
2074 for (Use &U :
GEP->indices())
2081 AvailValInBlkVect ValuesPerBlock;
2082 UnavailBlkVect UnavailableBlocks;
2083 AnalyzeLoadAvailability(Load, Deps, ValuesPerBlock, UnavailableBlocks);
2087 if (ValuesPerBlock.empty())
2095 if (UnavailableBlocks.empty()) {
2096 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING NONLOCAL LOAD: " << *Load <<
'\n');
2101 ICF->removeUsersOf(Load);
2102 Load->replaceAllUsesWith(V);
2110 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2111 I->setDebugLoc(
Load->getDebugLoc());
2112 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2113 MD->invalidateCachedPointerInfo(V);
2126 if (performLoopLoadPRE(Load, ValuesPerBlock, UnavailableBlocks) ||
2127 PerformLoadPRE(Load, ValuesPerBlock, UnavailableBlocks))
2133bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2137 if (
Cond->isZero()) {
2147 const MemoryUseOrDef *FirstNonDom =
nullptr;
2149 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2156 for (
const auto &Acc : *AL) {
2158 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2159 FirstNonDom = Current;
2166 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2168 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2169 : MSSAU->createMemoryAccessInBB(
2191 return propagateEquality(V, True, IntrinsicI);
2196 I->replaceAllUsesWith(Repl);
2203 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2214 PointerUsesQueue.
push_back(PointerOperand);
2219 while (!PointerUsesQueue.
empty()) {
2222 "Null or GlobalValue should not be inserted");
2226 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2241 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2243 MostDominatingInstruction =
I;
2247 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2253static std::optional<MemoryLocation>
2260 switch (
II->getIntrinsicID()) {
2261 case Intrinsic::masked_load:
2263 case Intrinsic::masked_store:
2266 return std::nullopt;
2273 return std::nullopt;
2277 return std::nullopt;
2283std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2284 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2285 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2286 BatchAAResults &AA, LoadInst *L) {
2289 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2293 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2295 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2303 Choice->Kind = DepKind::Clobber;
2304 Choice->Offset = AR.getOffset();
2306 Choice->Kind = DepKind::Def;
2307 Choice->Offset = -1;
2310 Choice->Inst = Candidate;
2311 Choice->Block = Candidate->getParent();
2314 std::optional<ReachingMemVal> ReachingVal;
2315 for (MemoryAccess *MA : ClobbersList) {
2317 for (User *U : MA->
users()) {
2319 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2322 if (!UseOrDef || UseOrDef->getBlock() != BB)
2331 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2345 UpdateChoice(ReachingVal, AR, MemI);
2357std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2358 MemoryAccess *ClobberMA,
const MemoryLocation &Loc,
bool IsInvariantLoad,
2359 BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2367 if (
Alloc->getParent() == BB)
2368 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2369 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2373 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2374 return std::nullopt;
2378 return L->getOrdering();
2385 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2387 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2398 return std::nullopt;
2399 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2404 return std::nullopt;
2409 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2414 "Must be the superset/partial overlap case with positive offset");
2415 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2420 return std::nullopt;
2421 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2423 if (AA.isMustAlias(IIObjLoc, Loc))
2424 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2425 return std::nullopt;
2433 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2434 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2440 return std::nullopt;
2444 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2448 return std::nullopt;
2452 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2458bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2459 MemoryAccess *ClobberMA,
2460 DependencyBlockSet &Blocks,
2461 SmallVectorImpl<BasicBlock *> &Worklist) {
2471 if (!DT->isReachableFromEntry(Pred))
2475 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2478 PHITransAddr TransAddr = Addr;
2482 auto It = Blocks.find(Pred);
2483 if (It != Blocks.end()) {
2487 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2494 Pred, DependencyBlockInfo(TransAddr,
2495 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2502 for (
auto &
P : Preds) {
2503 [[maybe_unused]]
auto It =
2504 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2516void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2518 const DependencyBlockInfo &StartInfo,
2519 const DependencyBlockSet &Blocks,
2521 MemoryAccess *MA = StartInfo.InitialClobberMA;
2522 MemoryAccess *LastMA = StartInfo.ClobberMA;
2525 while (MA != LastMA) {
2539 BB = DT->getNode(BB)->getIDom()->getBlock();
2543 auto It = Blocks.find(BB);
2544 if (It == Blocks.end())
2547 MA = It->second.InitialClobberMA;
2548 LastMA = It->second.ClobberMA;
2549 if (MA == Clobbers.
back())
2566bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2567 SmallVectorImpl<ReachingMemVal> &Values,
2569 EarliestEscapeAnalysis EA(*DT, LI);
2570 BatchAAResults AA(AAR, &EA);
2572 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2578 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2591 if (
auto RMV = scanMemoryAccessesUsers(
2592 Loc, IsInvariantLoad, StartBlock,
2604 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2605 StartBlock, MSSA, AA)) {
2613 }
while (ClobberMA->
getBlock() == StartBlock);
2616 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2617 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2626 DependencyBlockSet Blocks;
2627 SmallVector<BasicBlock *, 16> InitialWorklist;
2628 const DataLayout &
DL =
L->getModule()->getDataLayout();
2629 if (!collectPredecessors(StartBlock,
2630 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2631 ClobberMA, Blocks, InitialWorklist))
2635 auto Worklist = InitialWorklist;
2636 while (!Worklist.
empty()) {
2638 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2641 if (!
Info.Addr.getAddr())
2649 if (
auto RMV = accessMayModifyLocation(
2651 IsInvariantLoad, BB, MSSA, AA)) {
2656 "LiveOnEntry aliases everything");
2672 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2673 Info.ForceUnknown =
true;
2676 if (BB != StartBlock &&
2677 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2678 Info.ForceUnknown =
true;
2688 Worklist = InitialWorklist;
2689 for (BasicBlock *BB : Worklist) {
2690 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2691 Info.Visited =
true;
2695 while (!Worklist.empty()) {
2696 auto *BB = Worklist.pop_back_val();
2697 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2701 if (!
Info.Addr.getAddr()) {
2702 Values.
push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2707 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2710 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2722 if (
Info.ForceUnknown) {
2723 Values.
push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2729 auto It = Blocks.find(Pred);
2730 if (It == Blocks.end())
2732 DependencyBlockInfo &PredInfo = It->second;
2733 if (PredInfo.Visited)
2735 PredInfo.Visited =
true;
2736 Worklist.push_back(Pred);
2745bool GVNPass::processLoad(LoadInst *L) {
2750 if (!
L->isUnordered())
2753 if (
L->getType()->isTokenLikeTy())
2756 if (
L->use_empty()) {
2761 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2764 MemDepResult Dep = MD->getDependency(L);
2768 return processNonLocalLoad(L);
2772 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2775 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2778 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2780 assert(MemVals.
size() &&
"Expected at least an unknown value");
2781 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2782 return processNonLocalLoad(L, MemVals);
2784 MemVal = MemVals[0];
2787 if (MemVal.Kind == DepKind::Other) {
2791 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2792 dbgs() <<
" has unknown dependence\n";);
2796 auto AV = AnalyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2800 Value *AvailableValue = AV->MaterializeAdjustedValue(L, L);
2803 ICF->removeUsersOf(L);
2804 L->replaceAllUsesWith(AvailableValue);
2806 MSSAU->removeMemoryAccess(L);
2813 MD->invalidateCachedPointerInfo(AvailableValue);
2819bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2822 MemDepResult Dep = MD->getDependency(
I);
2828 Value *Passthrough =
I->getOperand(2);
2832 StoreVal->
getType() !=
I->getType())
2839 ICF->removeUsersOf(
I);
2840 I->replaceAllUsesWith(OpToForward);
2848std::pair<uint32_t, bool>
2849GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2850 uint32_t &
E = ExpressionNumbering[
Exp];
2851 bool CreateNewValNum = !
E;
2852 if (CreateNewValNum) {
2853 Expressions.push_back(Exp);
2854 if (ExprIdx.size() < NextValueNumber + 1)
2855 ExprIdx.resize(NextValueNumber * 2);
2856 E = NextValueNumber;
2857 ExprIdx[NextValueNumber++] = NextExprNumber++;
2859 return {
E, CreateNewValNum};
2864bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2867 GVN.LeaderTable.getLeaders(Num),
2875 auto FindRes = PhiTranslateTable.find({Num, Pred});
2876 if (FindRes != PhiTranslateTable.end())
2877 return FindRes->second;
2878 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2879 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2890 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2891 for (
const auto &Entry : Leaders) {
2893 if (
Call &&
Call->getParent() == PhiBlock)
2897 if (
AA->doesNotAccessMemory(
Call))
2900 if (!MD || !
AA->onlyReadsMemory(
Call))
2912 if (
D.getResult().isNonFuncLocal())
2920uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2921 const BasicBlock *PhiBlock,
2925 if (PHINode *PN = NumberingPhi[Num]) {
2926 if (PN->getParent() != PhiBlock)
2928 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2929 if (PN->getIncomingBlock(
I) != Pred)
2931 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2937 if (BasicBlock *BB = NumberingBB[Num]) {
2938 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
2950 return lookupOrAdd(PredPhi->getBlock());
2956 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
2962 if (!areAllValsInBB(Num, PhiBlock, GVN))
2965 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
2969 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
2973 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
2974 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
2975 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
2977 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
2980 if (
Exp.Commutative) {
2981 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
2982 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
2984 uint32_t Opcode =
Exp.Opcode >> 8;
2985 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
2986 Exp.Opcode = (Opcode << 8) |
2992 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
2993 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
2994 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3002void GVNPass::ValueTable::eraseTranslateCacheEntry(
3005 PhiTranslateTable.erase({Num, Pred});
3014 auto Leaders = LeaderTable.getLeaders(Num);
3015 if (Leaders.empty())
3018 Value *Val =
nullptr;
3019 for (
const auto &Entry : Leaders) {
3020 if (DT->dominates(Entry.BB, BB)) {
3040 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3041 assert((!Pred || Pred ==
E.getStart()) &&
3042 "No edge between these basic blocks!");
3043 return Pred !=
nullptr;
3046void GVNPass::assignBlockRPONumber(Function &
F) {
3047 BlockRPONumber.clear();
3048 uint32_t NextBlockNumber = 1;
3049 ReversePostOrderTraversal<Function *> RPOT(&
F);
3050 for (BasicBlock *BB : RPOT)
3051 BlockRPONumber[BB] = NextBlockNumber++;
3052 InvalidBlockRPONumbers =
false;
3060bool GVNPass::propagateEquality(
3062 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3067 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3074 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3078 while (!Worklist.
empty()) {
3079 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3080 LHS = Item.first;
RHS = Item.second;
3094 const DataLayout &
DL =
3103 uint32_t LVN = VN.lookupOrAdd(
LHS);
3108 uint32_t RVN = VN.lookupOrAdd(
RHS);
3125 for (
const BasicBlock *BB : DominatedBlocks)
3126 LeaderTable.insert(LVN,
RHS, BB);
3133 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3136 unsigned NumReplacements;
3137 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3139 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3142 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3143 CanReplacePointersCallBack);
3145 if (NumReplacements > 0) {
3147 NumGVNEqProp += NumReplacements;
3150 MD->invalidateCachedPointerInfo(
LHS);
3167 bool IsKnownFalse = !IsKnownTrue;
3183 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3188 if (
Cmp->isEquivalence(IsKnownFalse))
3189 Worklist.
push_back(std::make_pair(Op0, Op1));
3193 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3197 uint32_t NextNum = VN.getNextUnusedValueNumber();
3198 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3201 if (Num < NextNum) {
3202 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3207 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3208 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3209 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3212 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3213 if (!DT->dominates(
Entry.BB, InstBB) &&
3214 !DT->dominates(InstBB,
Entry.BB))
3220 unsigned NumReplacements;
3221 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3226 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3227 Changed |= NumReplacements > 0;
3228 NumGVNEqProp += NumReplacements;
3231 MD->invalidateCachedPointerInfo(NotCmp);
3239 for (
const BasicBlock *BB : DominatedBlocks)
3240 LeaderTable.insert(Num, NotVal, BB);
3249 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3254 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3264bool GVNPass::processInstruction(Instruction *
I) {
3269 const DataLayout &
DL =
I->getDataLayout();
3272 if (!
I->use_empty()) {
3275 ICF->removeUsersOf(
I);
3276 I->replaceAllUsesWith(V);
3284 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3285 MD->invalidateCachedPointerInfo(V);
3292 return processAssumeIntrinsic(Assume);
3295 if (processLoad(Load))
3298 unsigned Num = VN.lookupOrAdd(Load);
3299 LeaderTable.insert(Num, Load,
Load->getParent());
3311 return processFoldableCondBr(BI);
3313 Value *BranchCond = BI->getCondition();
3317 if (TrueSucc == FalseSucc)
3324 BasicBlockEdge TrueE(Parent, TrueSucc);
3325 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3328 BasicBlockEdge FalseE(Parent, FalseSucc);
3329 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3336 Value *SwitchCond =
SI->getCondition();
3341 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3343 ++SwitchEdges[Succ];
3345 for (
const auto &Case :
SI->cases()) {
3348 if (SwitchEdges.
lookup(Dst) == 1) {
3349 BasicBlockEdge
E(Parent, Dst);
3350 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3358 if (
I->getType()->isVoidTy())
3361 uint32_t NextNum = VN.getNextUnusedValueNumber();
3362 unsigned Num = VN.lookupOrAdd(
I);
3367 LeaderTable.insert(Num,
I,
I->getParent());
3374 if (Num >= NextNum) {
3375 LeaderTable.insert(Num,
I,
I->getParent());
3381 Value *Repl = findLeader(
I->getParent(), Num);
3384 LeaderTable.insert(Num,
I,
I->getParent());
3397 MD->invalidateCachedPointerInfo(Repl);
3403bool GVNPass::runImpl(Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3404 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3405 MemoryDependenceResults *RunMD, LoopInfo &LI,
3406 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3412 VN.setAliasAnalysis(&RunAA);
3414 ImplicitControlFlowTracking ImplicitCFT;
3423 InvalidBlockRPONumbers =
true;
3424 MemorySSAUpdater Updater(MSSA);
3425 MSSAU = MSSA ? &Updater :
nullptr;
3428 bool ShouldContinue =
true;
3430 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3442 unsigned Iteration = 0;
3443 while (ShouldContinue) {
3446 ShouldContinue = iterateOnFunction(
F);
3454 assignValNumForDeadCode();
3455 bool PREChanged =
true;
3456 while (PREChanged) {
3457 PREChanged = performPRE(
F);
3467 cleanupGlobalSets();
3478bool GVNPass::processBlock(BasicBlock *BB) {
3479 if (DeadBlocks.count(BB))
3482 bool ChangedFunction =
false;
3488 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3490 for (PHINode *PN : PHINodesToRemove) {
3491 removeInstruction(PN);
3494 ChangedFunction |= processInstruction(&Inst);
3495 return ChangedFunction;
3499bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3500 BasicBlock *Curr,
unsigned int ValNo) {
3506 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3514 if (!VN.exists(
Op)) {
3519 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3520 if (
Value *V = findLeader(Pred, TValNo)) {
3538 ICF->insertInstructionTo(Instr, Pred);
3540 unsigned Num = VN.lookupOrAdd(Instr);
3544 LeaderTable.insert(Num, Instr, Pred);
3548bool GVNPass::performScalarPRE(Instruction *CurInst) {
3574 if (CallB->isInlineAsm())
3578 uint32_t ValNo = VN.lookup(CurInst);
3586 unsigned NumWith = 0;
3587 unsigned NumWithout = 0;
3592 if (InvalidBlockRPONumbers)
3593 assignBlockRPONumber(*CurrentBlock->
getParent());
3599 if (!DT->isReachableFromEntry(
P)) {
3604 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3605 "Invalid BlockRPONumber map.");
3606 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3611 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3612 Value *PredV = findLeader(
P, TValNo);
3617 }
else if (PredV == CurInst) {
3629 if (NumWithout > 1 || NumWith == 0)
3637 if (NumWithout != 0) {
3643 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3656 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3660 PREInstr = CurInst->
clone();
3661 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3664 verifyRemoved(PREInstr);
3673 assert(PREInstr !=
nullptr || NumWithout == 0);
3679 CurInst->
getName() +
".pre-phi");
3680 Phi->insertBefore(CurrentBlock->begin());
3681 for (
auto &[V, BB] : PredMap) {
3686 Phi->addIncoming(V, BB);
3688 Phi->addIncoming(PREInstr, PREPred);
3694 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3695 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3698 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3699 MD->invalidateCachedPointerInfo(Phi);
3700 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3703 removeInstruction(CurInst);
3710bool GVNPass::performPRE(Function &
F) {
3712 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3714 if (CurrentBlock == &
F.getEntryBlock())
3718 if (CurrentBlock->isEHPad())
3722 BE = CurrentBlock->end();
3725 Changed |= performScalarPRE(CurInst);
3729 if (splitCriticalEdges())
3737BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3742 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3745 MD->invalidateCachedPredecessors();
3746 InvalidBlockRPONumbers =
true;
3753bool GVNPass::splitCriticalEdges() {
3754 if (ToSplit.empty())
3759 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3761 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3763 }
while (!ToSplit.empty());
3766 MD->invalidateCachedPredecessors();
3767 InvalidBlockRPONumbers =
true;
3773bool GVNPass::iterateOnFunction(Function &
F) {
3774 cleanupGlobalSets();
3781 ReversePostOrderTraversal<Function *> RPOT(&
F);
3783 for (BasicBlock *BB : RPOT)
3789void GVNPass::cleanupGlobalSets() {
3791 LeaderTable.clear();
3792 BlockRPONumber.clear();
3794 InvalidBlockRPONumbers =
true;
3797void GVNPass::removeInstruction(Instruction *
I) {
3799 if (MD) MD->removeInstruction(
I);
3801 MSSAU->removeMemoryAccess(
I);
3805 ICF->removeInstruction(
I);
3806 I->eraseFromParent();
3812void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3813 VN.verifyRemoved(Inst);
3820void GVNPass::addDeadBlock(BasicBlock *BB) {
3822 SmallSetVector<BasicBlock *, 4>
DF;
3825 while (!NewDead.
empty()) {
3827 if (DeadBlocks.count(
D))
3831 SmallVector<BasicBlock *, 8> Dom;
3832 DT->getDescendants(
D, Dom);
3833 DeadBlocks.insert_range(Dom);
3836 for (BasicBlock *
B : Dom) {
3838 if (DeadBlocks.count(S))
3841 bool AllPredDead =
true;
3843 if (!DeadBlocks.count(
P)) {
3844 AllPredDead =
false;
3864 for (BasicBlock *
B :
DF) {
3865 if (DeadBlocks.count(
B))
3871 for (BasicBlock *
P : Preds) {
3872 if (!DeadBlocks.count(
P))
3877 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3878 DeadBlocks.insert(
P = S);
3884 if (!DeadBlocks.count(
P))
3886 for (PHINode &Phi :
B->phis()) {
3889 MD->invalidateCachedPointerInfo(&Phi);
3908bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
3919 if (DeadBlocks.count(DeadRoot))
3923 DeadRoot = splitCriticalEdges(BI->getParent(), DeadRoot);
3925 addDeadBlock(DeadRoot);
3933void GVNPass::assignValNumForDeadCode() {
3934 for (BasicBlock *BB : DeadBlocks) {
3935 for (Instruction &Inst : *BB) {
3936 unsigned ValNum = VN.lookupOrAdd(&Inst);
3937 LeaderTable.insert(ValNum, &Inst, BB);
3948 bool ScalarPRE =
true)
3950 .setMemDep(MemDepAnalysis)
3951 .setMemorySSA(MemSSAAnalysis)
3952 .setScalarPRE(ScalarPRE)) {
3961 if (Impl.isMemorySSAEnabled() && !MSSAWP)
3964 return Impl.runImpl(
3969 Impl.isMemDepEnabled()
3974 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
3982 if (Impl.isMemDepEnabled())
3991 if (Impl.isMemorySSAEnabled())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#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.
early cse Early CSE w MemorySSA
static void reportMayClobberedLoad(LoadInst *Load, Instruction *DepInst, const DominatorTree *DT, OptimizationRemarkEmitter *ORE)
Try to locate the three instruction involved in a missed load-elimination case that is due to an inte...
static Instruction * findInvariantGroupValue(LoadInst *L, DominatorTree &DT)
If a load has !invariant.group, try to find the most-dominating instruction with the same metadata an...
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 const Instruction * findMayClobberedPtrAccess(LoadInst *Load, const DominatorTree *DT)
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 std::optional< MemoryLocation > maybeLoadStoreLocation(Instruction *I, bool AllowStores, const TargetLibraryInfo *TLI)
Return the memory location accessed by the (masked) load/store instruction I, if the instruction coul...
static cl::opt< bool > GVNEnableMemorySSA("enable-gvn-memoryssa", cl::init(false))
static bool isOnlyReachableViaThisEdge(const BasicBlockEdge &E, DominatorTree *DT)
There is an edge from 'Src' to 'Dst'.
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 cl::opt< bool > GVNEnableScalarPRE("enable-scalar-pre", cl::init(true), cl::Hidden)
static Value * findDominatingValue(const MemoryLocation &Loc, Type *LoadTy, Instruction *From, AAResults *AA)
static bool liesBetween(const Instruction *From, Instruction *Between, const Instruction *To, const DominatorTree *DT)
Assuming To can be reached from both From and Between, does Between lie on every path from From to To...
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 cl::opt< unsigned > ScanUsersLimit("gvn-scan-users-limit", cl::Hidden, cl::init(100), cl::desc("The number of memory accesses to scan in a block in reaching " "memory values analysis (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.
@ 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< 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 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.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static bool lookup(const GsymReader &GR, GsymDataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
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...
uint64_t IntrinsicInst * II
ppc ctr loops PowerPC CTR Loops Verify
#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
static DominatorTree getDomTree(Function &F)
std::pair< BasicBlock *, BasicBlock * > Edge
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.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
constexpr int32_t getOffset() const
constexpr bool hasOffset() const
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.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI 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; assumes that the block is well-formed.
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)
LLVM_ABI Instruction::BinaryOps getBinaryOp() const
Returns the binary operation underlying the intrinsic.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Analysis pass which computes a DominatorTree.
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.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class representing an expression and its matching format.
FunctionPass class - This class is used to implement most global optimizations.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
const BasicBlock & getEntryBlock() const
Represents calls to the gc.relocate intrinsic.
This class holds the mapping between values and value numbers.
LLVM_ABI uint32_t lookupOrAdd(MemoryAccess *MA)
The core GVN pass object.
friend class gvn::GVNLegacyPass
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI void salvageAndRemoveInstruction(Instruction *I)
This removes the specified instruction from our various maps and marks it for deletion.
AAResults * getAliasAnalysis() const
LLVM_ABI bool isLoadPREEnabled() const
GVNPass(GVNOptions Options={})
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI bool isMemorySSAEnabled() const
DominatorTree & getDominatorTree() const
LLVM_ABI bool isLoadInLoopPREEnabled() const
LLVM_ABI bool isScalarPREEnabled() const
LLVM_ABI bool isLoadPRESplitBackedgeEnabled() const
LLVM_ABI bool isMemDepEnabled() const
Legacy wrapper pass to provide the GlobalsAAResult object.
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI 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.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
LLVM_ABI void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})
Drop all unknown metadata except for debug locations.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
The legacy pass manager's analysis pass to compute loop information.
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.
BasicBlock * getBlock() const
An analysis that produces MemoryDependenceResults for a function.
std::vector< NonLocalDepEntry > NonLocalDepInfo
LLVM_ABI MemDepResult getDependency(Instruction *QueryInst)
Returns the instruction on which a memory operation depends.
LLVM_ABI const NonLocalDepInfo & getNonLocalCallDependency(CallBase *QueryCall)
Perform a full dependency query for the specified call, returning the set of blocks that the value is...
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
MemoryLocation getWithNewPtr(const Value *NewPtr) const
const Value * Ptr
The address of the start of the location.
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
BasicBlock * getIncomingBlock(unsigned I) const
Return incoming basic block number i.
MemoryAccess * getIncomingValue(unsigned I) const
Return incoming value number x.
An analysis that produces MemorySSA for a function.
Legacy analysis pass which computes MemorySSA.
LLVM_ABI void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
LLVM_ABI bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in the same basic block, determine whether MemoryAccess A dominates MemoryA...
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
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...
LLVM_ABI Value * translateValue(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree *DT, bool MustDominate)
translateValue - PHI translate the current address up the CFG from CurBB to Pred, updating our state ...
LLVM_ABI bool isPotentiallyPHITranslatable() const
isPotentiallyPHITranslatable - If this needs PHI translation, return true if we have some hope of doi...
bool needsPHITranslationFromBlock(BasicBlock *BB) const
needsPHITranslationFromBlock - Return true if moving from the specified BasicBlock to its predecessor...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
AnalysisType * getAnalysisIfAvailable() const
getAnalysisIfAvailable<AnalysisType>() - Subclasses use this function to get analysis information tha...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Helper class for SSA formation on a set of values defined in multiple blocks.
LLVM_ABI void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
LLVM_ABI Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
LLVM_ABI bool HasValueForBlock(BasicBlock *BB) const
Return true if the SSAUpdater already has a value for the specified block.
LLVM_ABI 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.
const Value * getCondition() const
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
bool erase(PtrType Ptr)
Remove pointer from the set.
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 reserve(size_type N)
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)
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.
LLVM_ABI bool isTokenLikeTy() const
Returns true if this is 'token' or a token-like target type.s.
static LLVM_ABI 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 LLVM_ABI 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.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
bool hasUseList() const
Check if this Value has a use-list.
LLVM_ABI 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...
LLVM_ABI void deleteValue()
Delete a pointer to a generic Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
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 MemDepAnalysis=GVNEnableMemDep, bool MemSSAAnalysis=GVNEnableMemorySSA, bool ScalarPRE=true)
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.
Abstract Attribute helper functions.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
m_Intrinsic_Ty< Opnd0, Opnd1, Opnd2 >::Ty m_MaskedStore(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedStore Intrinsic.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_Value()
Match an arbitrary value and ignore it.
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
NoWrapTrunc_match< OpTy, TruncInst::NoUnsignedWrap > m_NUWTrunc(const OpTy &Op)
Matches trunc nuw.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
LLVM_ABI 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...
LLVM_ABI 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...
LLVM_ABI 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...
LLVM_ABI Value * getValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, Instruction *InsertPt, Function *F)
If analyzeLoadFromClobberingStore/Load returned an offset, this function can be used to actually perf...
LLVM_ABI 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...
LLVM_ABI bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, Function *F)
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.
Add a small namespace to avoid name clashes with the classes used in the streaming interface.
NodeAddr< InstrNode * > Instr
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
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)
LLVM_ABI 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,...
LLVM_ABI 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...
LLVM_ABI 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...
auto pred_end(const MachineBasicBlock *BB)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI FunctionPass * createGVNPass(bool ScalarPRE)
Create a legacy GVN pass.
LLVM_ABI 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)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
constexpr from_range_t from_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
LLVM_ABI bool isAssumeWithEmptyBundle(const AssumeInst &Assume)
Return true iff the operand bundles of the provided llvm.assume doesn't contain any valuable informat...
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI 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.
LLVM_ABI bool canReplacePointersInUseIfEqual(const Use &U, const Value *To, const DataLayout &DL)
LLVM_ABI 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)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void patchReplacementInstruction(Instruction *I, Value *Repl)
Patch the replacement so that it is not more restrictive than the value being replaced.
LLVM_ABI void initializeGVNLegacyPassPass(PassRegistry &)
LLVM_ABI 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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
LLVM_ABI void combineMetadataForCSE(Instruction *K, const Instruction *J, bool DoesKMove)
Combine the metadata of two instructions so that K can replace J.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ Ref
The access may reference the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
LLVM_ABI bool VerifyMemorySSA
Enables verification of MemorySSA.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
LLVM_ABI bool salvageKnowledge(Instruction *I, AssumptionCache *AC=nullptr, DominatorTree *DT=nullptr)
Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert if before I.
LLVM_ABI 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.
LLVM_ABI FunctionPass * createGVNPass()
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
LLVM_ABI 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.
LLVM_ABI bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges=false)
Return true if the specified edge is a critical edge.
constexpr unsigned BitWidth
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool EliminateDuplicatePHINodes(BasicBlock *BB)
Check for and eliminate duplicate PHI nodes in this block.
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static bool isEqual(const GVNPass::Expression &LHS, const GVNPass::Expression &RHS)
static GVNPass::Expression getEmptyKey()
static unsigned getHashValue(const GVNPass::Expression &E)
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.
bool operator==(const Expression &Other) const
friend hash_code hash_value(const Expression &Value)
SmallVector< uint32_t, 4 > VarArgs
Expression(uint32_t Op=~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)
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.
Value * MaterializeAdjustedValue(LoadInst *Load) const
Emit code at the end of this block to adjust the value defined here to the specified type.
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.
static AvailableValue getUndef()
SelectInst * getSelectValue() const
Value * getSimpleValue() const
bool isMemIntrinValue() const
MemIntrinsic * getMemIntrinValue() const
Value * MaterializeAdjustedValue(LoadInst *Load, Instruction *InsertPt) const
Emit code at the specified insertion point to adjust the value defined here to the specified type.