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())
302 Res.
AV = std::move(
AV);
323 return AV.MaterializeAdjustedValue(Load,
BB->getTerminator());
334 E.Opcode =
I->getOpcode();
339 E.VarArgs.push_back(
lookupOrAdd(GCR->getOperand(0)));
340 E.VarArgs.push_back(
lookupOrAdd(GCR->getBasePtr()));
341 E.VarArgs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
343 for (
Use &
Op :
I->operands())
346 if (
I->isCommutative()) {
351 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
352 if (
E.VarArgs[0] >
E.VarArgs[1])
354 E.Commutative =
true;
360 if (
E.VarArgs[0] >
E.VarArgs[1]) {
365 E.Commutative =
true;
367 E.VarArgs.append(IVI->idx_begin(), IVI->idx_end());
369 ArrayRef<int> ShuffleMask = SVI->getShuffleMask();
370 E.VarArgs.append(ShuffleMask.
begin(), ShuffleMask.
end());
372 E.Attrs = CB->getAttributes();
378GVNPass::Expression GVNPass::ValueTable::createCmpExpr(
380 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
381 "Not a comparison!");
384 E.VarArgs.push_back(lookupOrAdd(
LHS));
385 E.VarArgs.push_back(lookupOrAdd(
RHS));
388 if (
E.VarArgs[0] >
E.VarArgs[1]) {
392 E.Opcode = (Opcode << 8) | Predicate;
393 E.Commutative =
true;
398GVNPass::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) {
399 assert(EI &&
"Not an ExtractValueInst?");
410 E.VarArgs.push_back(lookupOrAdd(WO->
getLHS()));
411 E.VarArgs.push_back(lookupOrAdd(WO->
getRHS()));
419 E.VarArgs.push_back(lookupOrAdd(
Op));
426GVNPass::Expression GVNPass::ValueTable::createGEPExpr(GetElementPtrInst *
GEP) {
428 Type *PtrTy =
GEP->getType()->getScalarType();
429 const DataLayout &
DL =
GEP->getDataLayout();
430 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
431 SmallMapVector<Value *, APInt, 4> VariableOffsets;
433 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
437 E.Opcode =
GEP->getOpcode();
439 E.VarArgs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
440 for (
const auto &[V, Scale] : VariableOffsets) {
441 E.VarArgs.push_back(lookupOrAdd(V));
442 E.VarArgs.push_back(lookupOrAdd(ConstantInt::get(
Context, Scale)));
444 if (!ConstantOffset.isZero())
446 lookupOrAdd(ConstantInt::get(
Context, ConstantOffset)));
450 E.Opcode =
GEP->getOpcode();
451 E.Ty =
GEP->getSourceElementType();
452 for (Use &
Op :
GEP->operands())
453 E.VarArgs.push_back(lookupOrAdd(
Op));
462GVNPass::ValueTable::ValueTable() =
default;
463GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
464GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
465GVNPass::ValueTable::~ValueTable() =
default;
471 ValueNumbering.
insert(std::make_pair(V, Num));
473 NumberingPhi[Num] = PN;
483 assert(MSSA &&
"addMemoryStateToExp should not be called without MemorySSA");
484 assert(MSSA->getMemoryAccess(
I) &&
"Instruction does not access memory");
485 MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(
I);
486 Exp.VarArgs.push_back(lookupOrAdd(MA));
497 if (
C->getFunction()->isPresplitCoroutine()) {
498 ValueNumbering[
C] = NextValueNumber;
499 return NextValueNumber++;
505 if (
C->isConvergent()) {
506 ValueNumbering[
C] = NextValueNumber;
507 return NextValueNumber++;
510 if (AA->doesNotAccessMemory(
C)) {
512 uint32_t
E = assignExpNewValueNum(Exp).first;
513 ValueNumbering[
C] =
E;
517 if (MD && AA->onlyReadsMemory(
C)) {
519 auto [
E, IsValNumNew] = assignExpNewValueNum(Exp);
521 ValueNumbering[
C] =
E;
525 MemDepResult LocalDep = MD->getDependency(
C);
528 ValueNumbering[
C] = NextValueNumber;
529 return NextValueNumber++;
532 if (LocalDep.
isDef()) {
537 if (!LocalDepCall || LocalDepCall->
arg_size() !=
C->arg_size()) {
538 ValueNumbering[
C] = NextValueNumber;
539 return NextValueNumber++;
542 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
543 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
544 uint32_t LocalDepCallVN = lookupOrAdd(LocalDepCall->
getArgOperand(
I));
545 if (CVN != LocalDepCallVN) {
546 ValueNumbering[
C] = NextValueNumber;
547 return NextValueNumber++;
551 uint32_t
V = lookupOrAdd(LocalDepCall);
552 ValueNumbering[
C] =
V;
558 MD->getNonLocalCallDependency(
C);
560 CallInst *CDep =
nullptr;
564 for (
const NonLocalDepEntry &
I : Deps) {
565 if (
I.getResult().isNonLocal())
570 if (!
I.getResult().isDef() || CDep !=
nullptr) {
577 if (NonLocalDepCall && DT->properlyDominates(
I.getBB(),
C->getParent())) {
578 CDep = NonLocalDepCall;
587 ValueNumbering[
C] = NextValueNumber;
588 return NextValueNumber++;
592 ValueNumbering[
C] = NextValueNumber;
593 return NextValueNumber++;
595 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
596 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
599 ValueNumbering[
C] = NextValueNumber;
600 return NextValueNumber++;
604 uint32_t
V = lookupOrAdd(CDep);
605 ValueNumbering[
C] =
V;
609 if (MSSA && IsMSSAEnabled && AA->onlyReadsMemory(
C)) {
611 addMemoryStateToExp(
C, Exp);
612 auto [
V,
_] = assignExpNewValueNum(Exp);
613 ValueNumbering[
C] =
V;
617 ValueNumbering[
C] = NextValueNumber;
618 return NextValueNumber++;
622uint32_t GVNPass::ValueTable::computeLoadStoreVN(Instruction *
I) {
623 if (!MSSA || !IsMSSAEnabled) {
624 ValueNumbering[
I] = NextValueNumber;
625 return NextValueNumber++;
629 Exp.Ty =
I->getType();
630 Exp.Opcode =
I->getOpcode();
631 for (Use &
Op :
I->operands())
632 Exp.VarArgs.push_back(lookupOrAdd(
Op));
633 addMemoryStateToExp(
I, Exp);
635 auto [
V,
_] = assignExpNewValueNum(Exp);
636 ValueNumbering[
I] =
V;
641bool GVNPass::ValueTable::exists(
Value *V)
const {
642 return ValueNumbering.contains(V);
654 auto VI = ValueNumbering.find(V);
655 if (VI != ValueNumbering.end())
660 ValueNumbering[V] = NextValueNumber;
663 return NextValueNumber++;
667 switch (
I->getOpcode()) {
668 case Instruction::Call:
670 case Instruction::FNeg:
671 case Instruction::Add:
672 case Instruction::FAdd:
673 case Instruction::Sub:
674 case Instruction::FSub:
675 case Instruction::Mul:
676 case Instruction::FMul:
677 case Instruction::UDiv:
678 case Instruction::SDiv:
679 case Instruction::FDiv:
680 case Instruction::URem:
681 case Instruction::SRem:
682 case Instruction::FRem:
683 case Instruction::Shl:
684 case Instruction::LShr:
685 case Instruction::AShr:
686 case Instruction::And:
687 case Instruction::Or:
688 case Instruction::Xor:
689 case Instruction::ICmp:
690 case Instruction::FCmp:
691 case Instruction::Trunc:
692 case Instruction::ZExt:
693 case Instruction::SExt:
694 case Instruction::FPToUI:
695 case Instruction::FPToSI:
696 case Instruction::UIToFP:
697 case Instruction::SIToFP:
698 case Instruction::FPTrunc:
699 case Instruction::FPExt:
700 case Instruction::PtrToInt:
701 case Instruction::PtrToAddr:
702 case Instruction::IntToPtr:
703 case Instruction::AddrSpaceCast:
704 case Instruction::BitCast:
705 case Instruction::Select:
706 case Instruction::Freeze:
707 case Instruction::ExtractElement:
708 case Instruction::InsertElement:
709 case Instruction::ShuffleVector:
710 case Instruction::InsertValue:
713 case Instruction::GetElementPtr:
716 case Instruction::ExtractValue:
719 case Instruction::PHI:
720 ValueNumbering[V] = NextValueNumber;
722 return NextValueNumber++;
723 case Instruction::Load:
724 case Instruction::Store:
725 return computeLoadStoreVN(
I);
727 ValueNumbering[V] = NextValueNumber;
728 return NextValueNumber++;
731 uint32_t E = assignExpNewValueNum(Exp).first;
732 ValueNumbering[V] = E;
739 auto VI = ValueNumbering.find(V);
741 assert(VI != ValueNumbering.end() &&
"Value not numbered?");
744 return (VI != ValueNumbering.end()) ? VI->second : 0;
751uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
754 Expression Exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
755 return assignExpNewValueNum(Exp).first;
760 ValueNumbering.clear();
761 ExpressionNumbering.clear();
762 NumberingPhi.clear();
764 PhiTranslateTable.clear();
773 uint32_t Num = ValueNumbering.lookup(V);
774 ValueNumbering.erase(V);
777 NumberingPhi.erase(Num);
779 NumberingBB.erase(Num);
784void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
785 assert(!ValueNumbering.contains(V) &&
786 "Inst still occurs in value numbering map!");
795 const auto &[It, Inserted] = NumToLeaders.try_emplace(
N, V, BB,
nullptr);
798 auto *NewSlot = TableAllocator.Allocate<LeaderListNode>();
799 new (NewSlot) LeaderListNode(V, BB, It->second.Next);
800 It->second.Next = NewSlot;
808 auto It = NumToLeaders.find(
N);
809 if (It == NumToLeaders.end())
812 LeaderListNode *Prev =
nullptr;
813 LeaderListNode *Curr = &It->second;
815 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
825 Prev->Next = Curr->Next;
826 Curr->~LeaderListNode();
827 TableAllocator.Deallocate<LeaderListNode>(Curr);
832 NumToLeaders.erase(It);
835 LeaderListNode *
Next = Curr->Next;
836 Curr->Entry.Val = std::move(
Next->Entry.Val);
837 Curr->Entry.BB =
Next->Entry.BB;
838 Curr->Next =
Next->Next;
839 Next->~LeaderListNode();
840 TableAllocator.Deallocate<LeaderListNode>(
Next);
862 return Options.AllowLoadPRESplitBackedge.value_or(
889 "On-demand computation of MemSSA implies that MemDep is disabled!");
893 bool Changed = runImpl(
F, AC, DT, TLI, AA, MemDep, LI, &ORE,
894 MSSA ? &MSSA->getMSSA() :
nullptr);
909 OS, MapClassName2PassName);
912 if (Options.AllowScalarPRE != std::nullopt)
913 OS << (*Options.AllowScalarPRE ?
"" :
"no-") <<
"scalar-pre;";
914 if (Options.AllowLoadPRE != std::nullopt)
915 OS << (*Options.AllowLoadPRE ?
"" :
"no-") <<
"load-pre;";
916 if (Options.AllowLoadPRESplitBackedge != std::nullopt)
917 OS << (*Options.AllowLoadPRESplitBackedge ?
"" :
"no-")
918 <<
"split-backedge-load-pre;";
919 if (Options.AllowMemDep != std::nullopt)
920 OS << (*Options.AllowMemDep ?
"" :
"no-") <<
"memdep;";
921 if (Options.AllowMemorySSA != std::nullopt)
922 OS << (*Options.AllowMemorySSA ?
"" :
"no-") <<
"memoryssa";
929 removeInstruction(
I);
932#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
935 for (
const auto &[Num, Exp] : Map) {
936 errs() << Num <<
"\n";
967 std::optional<BasicBlock *> UnavailableBB;
971 unsigned NumNewNewSpeculativelyAvailableBBs = 0;
979 while (!Worklist.
empty()) {
983 std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator,
bool>
IV =
991 UnavailableBB = CurrBB;
1002 ++NumNewNewSpeculativelyAvailableBBs;
1008 MaxBBSpeculationCutoffReachedTimes += (int)OutOfBudget;
1010 UnavailableBB = CurrBB;
1016 NewSpeculativelyAvailableBBs.
insert(CurrBB);
1022#if LLVM_ENABLE_STATS
1023 IsValueFullyAvailableInBlockNumSpeculationsMax.updateMax(
1024 NumNewNewSpeculativelyAvailableBBs);
1029 auto MarkAsFixpointAndEnqueueSuccessors =
1031 auto It = FullyAvailableBlocks.
find(BB);
1032 if (It == FullyAvailableBlocks.
end())
1039 State = FixpointState;
1042 "Found a speculatively available successor leftover?");
1050 if (UnavailableBB) {
1057 while (!Worklist.
empty())
1058 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1066 while (!Worklist.
empty())
1067 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1071 "Must have fixed all the new speculatively available blocks.");
1074 return !UnavailableBB;
1083 if (V.AV.Val == OldValue)
1084 V.AV.Val = NewValue;
1085 if (V.AV.isSelectValue()) {
1086 if (V.AV.V1 == OldValue)
1088 if (V.AV.V2 == OldValue)
1103 if (ValuesPerBlock.
size() == 1 &&
1105 Load->getParent())) {
1106 assert(!ValuesPerBlock[0].AV.isUndefValue() &&
1107 "Dead BB dominate this block");
1108 return ValuesPerBlock[0].MaterializeAdjustedValue(Load);
1114 SSAUpdate.
Initialize(Load->getType(), Load->getName());
1119 if (AV.AV.isUndefValue())
1129 if (BB == Load->getParent() &&
1130 ((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() == Load) ||
1131 (AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() == Load)))
1144 Type *LoadTy = Load->getType();
1148 if (Res->
getType() != LoadTy) {
1163 Load->getFunction());
1173 if (!CoercedLoad->
hasMetadata(LLVMContext::MD_noundef))
1175 {LLVMContext::MD_dereferenceable,
1176 LLVMContext::MD_dereferenceable_or_null,
1177 LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group});
1193 assert(
V1 &&
V2 &&
"both value operands of the select must be present");
1202 assert(Res &&
"failed to materialize?");
1208 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1225 Value *PtrOp = Load->getPointerOperand();
1231 for (
auto *U : PtrOp->
users()) {
1234 if (
I->getFunction() == Load->getFunction() && DT->
dominates(
I, Load)) {
1252 for (
auto *U : PtrOp->
users()) {
1255 if (
I->getFunction() == Load->getFunction() &&
1263 OtherAccess =
nullptr;
1282 using namespace ore;
1285 R <<
"load of type " << NV(
"Type", Load->getType()) <<
" not eliminated"
1290 R <<
" in favor of " << NV(
"OtherAccess", OtherAccess);
1292 R <<
" because it is clobbered by " << NV(
"ClobberedBy", DepInst);
1306 for (
auto *Inst = BB == FromBB ? From : BB->
getTerminator();
1314 if (
SI->isSimple() &&
SI->getPointerOperand() ==
Loc.Ptr &&
1315 SI->getValueOperand()->getType() == LoadTy)
1316 return SI->getValueOperand();
1320 if (LI->getPointerOperand() ==
Loc.Ptr && LI->getType() == LoadTy)
1326std::optional<AvailableValue>
1327GVNPass::AnalyzeLoadAvailability(LoadInst *Load,
const ReachingMemVal &Dep,
1329 assert(
Load->isUnordered() &&
"rules below are incorrect for ordered access");
1330 assert((Dep.Kind == DepKind::Def || Dep.Kind == DepKind::Clobber) &&
1331 "expected a local dependence");
1335 const DataLayout &
DL =
Load->getDataLayout();
1336 if (Dep.Kind == DepKind::Clobber) {
1342 if (
Address &&
Load->isAtomic() <= DepSI->isAtomic()) {
1358 if (DepLoad != Load &&
Address &&
1359 Load->isAtomic() <= DepLoad->isAtomic()) {
1366 DepLoad->getFunction())) {
1367 const auto ClobberOff = MD->getClobberOffset(DepLoad);
1369 Offset = (ClobberOff == std::nullopt || *ClobberOff < 0)
1375 DepLoad->getFunction()) ||
1402 dbgs() <<
" is clobbered by " << *DepInst <<
'\n';);
1406 return std::nullopt;
1408 assert(Dep.Kind == DepKind::Def &&
"follows from above");
1415 if (Constant *InitVal =
1425 return std::nullopt;
1428 if (S->isAtomic() <
Load->isAtomic())
1429 return std::nullopt;
1440 return std::nullopt;
1443 if (
LD->isAtomic() <
Load->isAtomic())
1444 return std::nullopt;
1453 assert(Sel->getType() ==
Load->getPointerOperandType());
1459 return std::nullopt;
1464 return std::nullopt;
1472 dbgs() <<
" has unknown def " << *DepInst <<
'\n';);
1473 return std::nullopt;
1476void GVNPass::AnalyzeLoadAvailability(LoadInst *Load,
1477 SmallVectorImpl<ReachingMemVal> &Deps,
1478 AvailValInBlkVect &ValuesPerBlock,
1479 UnavailBlkVect &UnavailableBlocks) {
1484 for (
const auto &Dep : Deps) {
1487 if (DeadBlocks.count(DepBB)) {
1494 if (Dep.Kind == DepKind::Other) {
1495 UnavailableBlocks.push_back(DepBB);
1503 AnalyzeLoadAvailability(Load, Dep,
const_cast<Value *
>(Dep.Addr))) {
1507 ValuesPerBlock.push_back(
1510 UnavailableBlocks.push_back(DepBB);
1514 assert(Deps.size() == ValuesPerBlock.size() + UnavailableBlocks.size() &&
1515 "post condition violation");
1537LoadInst *GVNPass::findLoadToHoistIntoPred(BasicBlock *Pred, BasicBlock *LoadBB,
1541 if (
Term->getNumSuccessors() != 2 ||
Term->isSpecialTerminator())
1543 auto *SuccBB =
Term->getSuccessor(0);
1544 if (SuccBB == LoadBB)
1545 SuccBB =
Term->getSuccessor(1);
1546 if (!SuccBB->getSinglePredecessor())
1550 for (Instruction &Inst : *SuccBB) {
1551 if (Inst.isDebugOrPseudoInst())
1553 if (--NumInsts == 0)
1556 if (!Inst.isIdenticalTo(Load))
1559 bool HasLocalDep =
true;
1561 MemDepResult Dep = MD->getDependency(&Inst);
1564 auto *MSSA = MSSAU->getMemorySSA();
1566 if (
auto *MA = MSSA->getMemoryAccess(&Inst); MA &&
isa<MemoryUse>(MA)) {
1567 auto *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(MA);
1568 HasLocalDep = Clobber->getBlock() == SuccBB;
1576 if (!HasLocalDep && !ICF->isDominatedByICFIFromSameBlock(&Inst))
1587void GVNPass::eliminatePartiallyRedundantLoad(
1588 LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1589 MapVector<BasicBlock *, Value *> &AvailableLoads,
1590 MapVector<BasicBlock *, LoadInst *> *CriticalEdgePredAndLoad) {
1591 for (
const auto &AvailableLoad : AvailableLoads) {
1592 BasicBlock *UnavailableBlock = AvailableLoad.first;
1593 Value *LoadPtr = AvailableLoad.second;
1595 auto *NewLoad =
new LoadInst(
1596 Load->getType(), LoadPtr,
Load->getName() +
".pre",
Load->isVolatile(),
1597 Load->getAlign(),
Load->getOrdering(),
Load->getSyncScopeID(),
1599 NewLoad->setDebugLoc(
Load->getDebugLoc());
1601 auto *NewAccess = MSSAU->createMemoryAccessInBB(
1604 MSSAU->insertDef(NewDef,
true);
1610 AAMDNodes Tags =
Load->getAAMetadata();
1612 NewLoad->setAAMetadata(Tags);
1614 if (
auto *MD =
Load->getMetadata(LLVMContext::MD_invariant_load))
1615 NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
1616 if (
auto *InvGroupMD =
Load->getMetadata(LLVMContext::MD_invariant_group))
1617 NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
1618 if (
auto *RangeMD =
Load->getMetadata(LLVMContext::MD_range))
1619 NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
1620 if (
auto *NoFPClassMD =
Load->getMetadata(LLVMContext::MD_nofpclass))
1621 NewLoad->setMetadata(LLVMContext::MD_nofpclass, NoFPClassMD);
1623 if (
auto *AccessMD =
Load->getMetadata(LLVMContext::MD_access_group))
1624 if (LI->getLoopFor(
Load->getParent()) == LI->getLoopFor(UnavailableBlock))
1625 NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
1634 ValuesPerBlock.push_back(
1637 MD->invalidateCachedPointerInfo(LoadPtr);
1642 if (CriticalEdgePredAndLoad) {
1643 auto It = CriticalEdgePredAndLoad->
find(UnavailableBlock);
1644 if (It != CriticalEdgePredAndLoad->
end()) {
1645 ++NumPRELoadMoved2CEPred;
1646 ICF->insertInstructionTo(NewLoad, UnavailableBlock);
1647 LoadInst *OldLoad = It->second;
1651 if (uint32_t ValNo = VN.lookup(OldLoad,
false))
1652 LeaderTable.erase(ValNo, OldLoad, OldLoad->
getParent());
1653 removeInstruction(OldLoad);
1661 ICF->removeUsersOf(Load);
1662 Load->replaceAllUsesWith(V);
1666 I->setDebugLoc(
Load->getDebugLoc());
1667 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
1668 MD->invalidateCachedPointerInfo(V);
1670 return OptimizationRemark(
DEBUG_TYPE,
"LoadPRE", Load)
1671 <<
"load eliminated by PRE";
1676bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1677 UnavailBlkVect &UnavailableBlocks) {
1686 SmallPtrSet<BasicBlock *, 4> Blockers(
llvm::from_range, UnavailableBlocks);
1708 bool MustEnsureSafetyOfSpeculativeExecution =
1709 ICF->isDominatedByICFIFromSameBlock(Load);
1713 if (TmpBB == LoadBB)
1715 if (Blockers.count(TmpBB))
1727 MustEnsureSafetyOfSpeculativeExecution =
1728 MustEnsureSafetyOfSpeculativeExecution || ICF->hasICF(TmpBB);
1736 MapVector<BasicBlock *, Value *> PredLoads;
1737 DenseMap<BasicBlock *, AvailabilityState> FullyAvailableBlocks;
1738 for (
const AvailableValueInBlock &AV : ValuesPerBlock)
1740 for (BasicBlock *UnavailableBB : UnavailableBlocks)
1748 MapVector<BasicBlock *, LoadInst *> CriticalEdgePredAndLoad;
1754 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
1755 << Pred->
getName() <<
"': " << *Load <<
'\n');
1766 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
1767 << Pred->
getName() <<
"': " << *Load <<
'\n');
1773 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
1774 << Pred->
getName() <<
"': " << *Load <<
'\n');
1780 if (DT->dominates(LoadBB, Pred)) {
1783 <<
"COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
1784 << Pred->
getName() <<
"': " << *Load <<
'\n');
1788 if (LoadInst *LI = findLoadToHoistIntoPred(Pred, LoadBB, Load))
1789 CriticalEdgePredAndLoad[Pred] = LI;
1794 PredLoads[Pred] =
nullptr;
1799 unsigned NumInsertPreds = PredLoads.
size() + CriticalEdgePredSplit.
size();
1800 unsigned NumUnavailablePreds = NumInsertPreds +
1801 CriticalEdgePredAndLoad.
size();
1802 assert(NumUnavailablePreds != 0 &&
1803 "Fully available value should already be eliminated!");
1804 (void)NumUnavailablePreds;
1810 if (NumInsertPreds > 1)
1815 if (MustEnsureSafetyOfSpeculativeExecution) {
1816 if (CriticalEdgePredSplit.
size())
1820 for (
auto &PL : PredLoads)
1824 for (
auto &CEP : CriticalEdgePredAndLoad)
1831 for (BasicBlock *OrigPred : CriticalEdgePredSplit) {
1832 BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
1833 assert(!PredLoads.count(OrigPred) &&
"Split edges shouldn't be in map!");
1834 PredLoads[NewPred] =
nullptr;
1835 LLVM_DEBUG(
dbgs() <<
"Split critical edge " << OrigPred->getName() <<
"->"
1836 << LoadBB->
getName() <<
'\n');
1839 for (
auto &CEP : CriticalEdgePredAndLoad)
1840 PredLoads[CEP.first] =
nullptr;
1843 bool CanDoPRE =
true;
1844 const DataLayout &
DL =
Load->getDataLayout();
1845 SmallVector<Instruction*, 8> NewInsts;
1846 for (
auto &PredLoad : PredLoads) {
1847 BasicBlock *UnavailablePred = PredLoad.first;
1857 Value *LoadPtr =
Load->getPointerOperand();
1859 while (Cur != LoadBB) {
1872 LoadPtr =
Address.translateWithInsertion(LoadBB, UnavailablePred, *DT,
1879 << *
Load->getPointerOperand() <<
"\n");
1884 PredLoad.second = LoadPtr;
1888 while (!NewInsts.
empty()) {
1898 return !CriticalEdgePredSplit.empty();
1904 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOAD: " << *Load <<
'\n');
1906 <<
" INSTS: " << *NewInsts.
back()
1910 for (Instruction *
I : NewInsts) {
1914 I->updateLocationAfterHoist();
1923 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, PredLoads,
1924 &CriticalEdgePredAndLoad);
1929bool GVNPass::performLoopLoadPRE(LoadInst *Load,
1930 AvailValInBlkVect &ValuesPerBlock,
1931 UnavailBlkVect &UnavailableBlocks) {
1932 const Loop *
L = LI->getLoopFor(
Load->getParent());
1934 if (!L ||
L->getHeader() !=
Load->getParent())
1939 if (!Preheader || !Latch)
1942 Value *LoadPtr =
Load->getPointerOperand();
1944 if (!
L->isLoopInvariant(LoadPtr))
1950 if (ICF->isDominatedByICFIFromSameBlock(Load))
1954 for (
auto *Blocker : UnavailableBlocks) {
1956 if (!
L->contains(Blocker))
1968 if (L != LI->getLoopFor(Blocker))
1976 if (DT->dominates(Blocker, Latch))
1980 if (Blocker->getTerminator()->mayWriteToMemory())
1983 LoopBlock = Blocker;
1995 MapVector<BasicBlock *, Value *> AvailableLoads;
1996 AvailableLoads[LoopBlock] = LoadPtr;
1997 AvailableLoads[Preheader] = LoadPtr;
1999 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOOP LOAD: " << *Load <<
'\n');
2000 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, AvailableLoads,
2008 using namespace ore;
2012 <<
"load of type " << NV(
"Type", Load->getType()) <<
" eliminated"
2013 << setExtraArgs() <<
" in favor of "
2020bool GVNPass::processNonLocalLoad(LoadInst *Load) {
2022 if (
Load->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2023 Load->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2028 MD->getNonLocalPointerDependency(Load, Deps);
2033 unsigned NumDeps = Deps.size();
2040 for (
const NonLocalDepResult &Dep : Deps) {
2041 const auto &
R = Dep.getResult();
2053 return processNonLocalLoad(Load, MemVals);
2056bool GVNPass::processNonLocalLoad(LoadInst *Load,
2057 SmallVectorImpl<ReachingMemVal> &Deps) {
2060 if (Deps.
size() == 1 && Deps[0].Kind == DepKind::Other) {
2062 dbgs() <<
" has unknown dependencies\n";);
2070 if (GetElementPtrInst *
GEP =
2072 for (Use &U :
GEP->indices())
2079 AvailValInBlkVect ValuesPerBlock;
2080 UnavailBlkVect UnavailableBlocks;
2081 AnalyzeLoadAvailability(Load, Deps, ValuesPerBlock, UnavailableBlocks);
2085 if (ValuesPerBlock.empty())
2093 if (UnavailableBlocks.empty()) {
2094 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING NONLOCAL LOAD: " << *Load <<
'\n');
2099 ICF->removeUsersOf(Load);
2100 Load->replaceAllUsesWith(V);
2108 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2109 I->setDebugLoc(
Load->getDebugLoc());
2110 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2111 MD->invalidateCachedPointerInfo(V);
2124 if (performLoopLoadPRE(Load, ValuesPerBlock, UnavailableBlocks) ||
2125 PerformLoadPRE(Load, ValuesPerBlock, UnavailableBlocks))
2131bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2135 if (
Cond->isZero()) {
2145 const MemoryUseOrDef *FirstNonDom =
nullptr;
2147 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2154 for (
const auto &Acc : *AL) {
2156 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2157 FirstNonDom = Current;
2164 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2166 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2167 : MSSAU->createMemoryAccessInBB(
2189 return propagateEquality(V, True, IntrinsicI);
2194 I->replaceAllUsesWith(Repl);
2201 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2212 PointerUsesQueue.
push_back(PointerOperand);
2217 while (!PointerUsesQueue.
empty()) {
2220 "Null or GlobalValue should not be inserted");
2224 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2239 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2241 MostDominatingInstruction =
I;
2245 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2251static std::optional<MemoryLocation>
2258 switch (
II->getIntrinsicID()) {
2259 case Intrinsic::masked_load:
2261 case Intrinsic::masked_store:
2264 return std::nullopt;
2271 return std::nullopt;
2275 return std::nullopt;
2281std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2282 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2283 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2284 BatchAAResults &AA, LoadInst *L) {
2287 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2291 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2293 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2301 Choice->Kind = DepKind::Clobber;
2302 Choice->Offset = AR.getOffset();
2304 Choice->Kind = DepKind::Def;
2305 Choice->Offset = -1;
2308 Choice->Inst = Candidate;
2309 Choice->Block = Candidate->getParent();
2312 std::optional<ReachingMemVal> ReachingVal;
2313 for (MemoryAccess *MA : ClobbersList) {
2315 for (User *U : MA->
users()) {
2317 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2320 if (!UseOrDef || UseOrDef->getBlock() != BB)
2329 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2343 UpdateChoice(ReachingVal, AR, MemI);
2355std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2356 MemoryAccess *ClobberMA,
const MemoryLocation &Loc,
bool IsInvariantLoad,
2357 BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2365 if (
Alloc->getParent() == BB)
2366 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2367 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2371 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2372 return std::nullopt;
2376 return L->getOrdering();
2383 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2385 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2396 return std::nullopt;
2397 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2402 return std::nullopt;
2407 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2412 "Must be the superset/partial overlap case with positive offset");
2413 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2418 return std::nullopt;
2419 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2421 if (AA.isMustAlias(IIObjLoc, Loc))
2422 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2423 return std::nullopt;
2431 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2432 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2438 return std::nullopt;
2442 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2446 return std::nullopt;
2450 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2456bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2457 MemoryAccess *ClobberMA,
2458 DependencyBlockSet &Blocks,
2459 SmallVectorImpl<BasicBlock *> &Worklist) {
2469 if (!DT->isReachableFromEntry(Pred))
2473 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2476 PHITransAddr TransAddr = Addr;
2480 auto It = Blocks.find(Pred);
2481 if (It != Blocks.end()) {
2485 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2492 Pred, DependencyBlockInfo(TransAddr,
2493 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2500 for (
auto &
P : Preds) {
2501 [[maybe_unused]]
auto It =
2502 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2514void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2516 const DependencyBlockInfo &StartInfo,
2517 const DependencyBlockSet &Blocks,
2519 MemoryAccess *MA = StartInfo.InitialClobberMA;
2520 MemoryAccess *LastMA = StartInfo.ClobberMA;
2523 while (MA != LastMA) {
2537 BB = DT->getNode(BB)->getIDom()->getBlock();
2541 auto It = Blocks.find(BB);
2542 if (It == Blocks.end())
2545 MA = It->second.InitialClobberMA;
2546 LastMA = It->second.ClobberMA;
2547 if (MA == Clobbers.
back())
2564bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2565 SmallVectorImpl<ReachingMemVal> &Values,
2567 EarliestEscapeAnalysis EA(*DT, LI);
2568 BatchAAResults AA(AAR, &EA);
2570 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2576 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2589 if (
auto RMV = scanMemoryAccessesUsers(
2590 Loc, IsInvariantLoad, StartBlock,
2602 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2603 StartBlock, MSSA, AA)) {
2611 }
while (ClobberMA->
getBlock() == StartBlock);
2614 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2615 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2624 DependencyBlockSet Blocks;
2625 SmallVector<BasicBlock *, 16> InitialWorklist;
2626 const DataLayout &
DL =
L->getModule()->getDataLayout();
2627 if (!collectPredecessors(StartBlock,
2628 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2629 ClobberMA, Blocks, InitialWorklist))
2633 auto Worklist = InitialWorklist;
2634 while (!Worklist.
empty()) {
2636 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2639 if (!
Info.Addr.getAddr())
2647 if (
auto RMV = accessMayModifyLocation(
2649 IsInvariantLoad, BB, MSSA, AA)) {
2654 "LiveOnEntry aliases everything");
2670 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2671 Info.ForceUnknown =
true;
2674 if (BB != StartBlock &&
2675 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2676 Info.ForceUnknown =
true;
2686 Worklist = InitialWorklist;
2687 for (BasicBlock *BB : Worklist) {
2688 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2689 Info.Visited =
true;
2693 while (!Worklist.empty()) {
2694 auto *BB = Worklist.pop_back_val();
2695 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2699 if (!
Info.Addr.getAddr()) {
2700 Values.
push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2705 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2708 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2720 if (
Info.ForceUnknown) {
2721 Values.
push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2727 auto It = Blocks.find(Pred);
2728 if (It == Blocks.end())
2730 DependencyBlockInfo &PredInfo = It->second;
2731 if (PredInfo.Visited)
2733 PredInfo.Visited =
true;
2734 Worklist.push_back(Pred);
2743bool GVNPass::processLoad(LoadInst *L) {
2748 if (!
L->isUnordered())
2751 if (
L->getType()->isTokenLikeTy())
2754 if (
L->use_empty()) {
2759 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2762 MemDepResult Dep = MD->getDependency(L);
2766 return processNonLocalLoad(L);
2770 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2773 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2776 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2778 assert(MemVals.
size() &&
"Expected at least an unknown value");
2779 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2780 return processNonLocalLoad(L, MemVals);
2782 MemVal = MemVals[0];
2785 if (MemVal.Kind == DepKind::Other) {
2789 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2790 dbgs() <<
" has unknown dependence\n";);
2794 auto AV = AnalyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2798 Value *AvailableValue = AV->MaterializeAdjustedValue(L, L);
2801 ICF->removeUsersOf(L);
2802 L->replaceAllUsesWith(AvailableValue);
2804 MSSAU->removeMemoryAccess(L);
2811 MD->invalidateCachedPointerInfo(AvailableValue);
2817bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2820 MemDepResult Dep = MD->getDependency(
I);
2826 Value *Passthrough =
I->getOperand(2);
2830 StoreVal->
getType() !=
I->getType())
2837 ICF->removeUsersOf(
I);
2838 I->replaceAllUsesWith(OpToForward);
2846std::pair<uint32_t, bool>
2847GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2848 uint32_t &
E = ExpressionNumbering[
Exp];
2849 bool CreateNewValNum = !
E;
2850 if (CreateNewValNum) {
2851 Expressions.push_back(Exp);
2852 if (ExprIdx.size() < NextValueNumber + 1)
2853 ExprIdx.resize(NextValueNumber * 2);
2854 E = NextValueNumber;
2855 ExprIdx[NextValueNumber++] = NextExprNumber++;
2857 return {
E, CreateNewValNum};
2862bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2865 GVN.LeaderTable.getLeaders(Num),
2873 auto FindRes = PhiTranslateTable.find({Num, Pred});
2874 if (FindRes != PhiTranslateTable.end())
2875 return FindRes->second;
2876 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2877 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2888 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2889 for (
const auto &Entry : Leaders) {
2891 if (
Call &&
Call->getParent() == PhiBlock)
2895 if (
AA->doesNotAccessMemory(
Call))
2898 if (!MD || !
AA->onlyReadsMemory(
Call))
2910 if (
D.getResult().isNonFuncLocal())
2918uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2919 const BasicBlock *PhiBlock,
2923 if (PHINode *PN = NumberingPhi[Num]) {
2924 if (PN->getParent() != PhiBlock)
2926 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2927 if (PN->getIncomingBlock(
I) != Pred)
2929 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2935 if (BasicBlock *BB = NumberingBB[Num]) {
2936 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
2948 return lookupOrAdd(PredPhi->getBlock());
2954 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
2960 if (!areAllValsInBB(Num, PhiBlock, GVN))
2963 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
2967 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
2971 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
2972 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
2973 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
2975 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
2978 if (
Exp.Commutative) {
2979 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
2980 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
2982 uint32_t Opcode =
Exp.Opcode >> 8;
2983 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
2984 Exp.Opcode = (Opcode << 8) |
2990 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
2991 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
2992 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3000void GVNPass::ValueTable::eraseTranslateCacheEntry(
3003 PhiTranslateTable.erase({Num, Pred});
3012 auto Leaders = LeaderTable.getLeaders(Num);
3013 if (Leaders.empty())
3016 Value *Val =
nullptr;
3017 for (
const auto &Entry : Leaders) {
3018 if (DT->dominates(Entry.BB, BB)) {
3038 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3039 assert((!Pred || Pred ==
E.getStart()) &&
3040 "No edge between these basic blocks!");
3041 return Pred !=
nullptr;
3044void GVNPass::assignBlockRPONumber(Function &
F) {
3045 BlockRPONumber.clear();
3046 uint32_t NextBlockNumber = 1;
3047 ReversePostOrderTraversal<Function *> RPOT(&
F);
3048 for (BasicBlock *BB : RPOT)
3049 BlockRPONumber[BB] = NextBlockNumber++;
3050 InvalidBlockRPONumbers =
false;
3058bool GVNPass::propagateEquality(
3060 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3065 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3072 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3076 while (!Worklist.
empty()) {
3077 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3078 LHS = Item.first;
RHS = Item.second;
3092 const DataLayout &
DL =
3101 uint32_t LVN = VN.lookupOrAdd(
LHS);
3106 uint32_t RVN = VN.lookupOrAdd(
RHS);
3123 for (
const BasicBlock *BB : DominatedBlocks)
3124 LeaderTable.insert(LVN,
RHS, BB);
3131 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3134 unsigned NumReplacements;
3135 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3137 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3140 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3141 CanReplacePointersCallBack);
3143 if (NumReplacements > 0) {
3145 NumGVNEqProp += NumReplacements;
3148 MD->invalidateCachedPointerInfo(
LHS);
3165 bool IsKnownFalse = !IsKnownTrue;
3181 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3186 if (
Cmp->isEquivalence(IsKnownFalse))
3187 Worklist.
push_back(std::make_pair(Op0, Op1));
3191 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3195 uint32_t NextNum = VN.getNextUnusedValueNumber();
3196 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3199 if (Num < NextNum) {
3200 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3205 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3206 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3207 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3210 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3211 if (!DT->dominates(
Entry.BB, InstBB) &&
3212 !DT->dominates(InstBB,
Entry.BB))
3218 unsigned NumReplacements;
3219 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3224 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3225 Changed |= NumReplacements > 0;
3226 NumGVNEqProp += NumReplacements;
3229 MD->invalidateCachedPointerInfo(NotCmp);
3237 for (
const BasicBlock *BB : DominatedBlocks)
3238 LeaderTable.insert(Num, NotVal, BB);
3247 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3252 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3262bool GVNPass::processInstruction(Instruction *
I) {
3267 const DataLayout &
DL =
I->getDataLayout();
3270 if (!
I->use_empty()) {
3273 ICF->removeUsersOf(
I);
3274 I->replaceAllUsesWith(V);
3282 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3283 MD->invalidateCachedPointerInfo(V);
3290 return processAssumeIntrinsic(Assume);
3293 if (processLoad(Load))
3296 unsigned Num = VN.lookupOrAdd(Load);
3297 LeaderTable.insert(Num, Load,
Load->getParent());
3309 return processFoldableCondBr(BI);
3311 Value *BranchCond = BI->getCondition();
3315 if (TrueSucc == FalseSucc)
3322 BasicBlockEdge TrueE(Parent, TrueSucc);
3323 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3326 BasicBlockEdge FalseE(Parent, FalseSucc);
3327 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3334 Value *SwitchCond =
SI->getCondition();
3339 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3341 ++SwitchEdges[Succ];
3343 for (
const auto &Case :
SI->cases()) {
3346 if (SwitchEdges.
lookup(Dst) == 1) {
3347 BasicBlockEdge
E(Parent, Dst);
3348 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3356 if (
I->getType()->isVoidTy())
3359 uint32_t NextNum = VN.getNextUnusedValueNumber();
3360 unsigned Num = VN.lookupOrAdd(
I);
3365 LeaderTable.insert(Num,
I,
I->getParent());
3372 if (Num >= NextNum) {
3373 LeaderTable.insert(Num,
I,
I->getParent());
3379 Value *Repl = findLeader(
I->getParent(), Num);
3382 LeaderTable.insert(Num,
I,
I->getParent());
3395 MD->invalidateCachedPointerInfo(Repl);
3401bool GVNPass::runImpl(Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3402 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3403 MemoryDependenceResults *RunMD, LoopInfo &LI,
3404 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3410 VN.setAliasAnalysis(&RunAA);
3412 ImplicitControlFlowTracking ImplicitCFT;
3421 InvalidBlockRPONumbers =
true;
3422 MemorySSAUpdater Updater(MSSA);
3423 MSSAU = MSSA ? &Updater :
nullptr;
3426 bool ShouldContinue =
true;
3428 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3440 unsigned Iteration = 0;
3441 while (ShouldContinue) {
3444 ShouldContinue = iterateOnFunction(
F);
3452 assignValNumForDeadCode();
3453 bool PREChanged =
true;
3454 while (PREChanged) {
3455 PREChanged = performPRE(
F);
3465 cleanupGlobalSets();
3476bool GVNPass::processBlock(BasicBlock *BB) {
3477 if (DeadBlocks.count(BB))
3480 bool ChangedFunction =
false;
3486 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3488 for (PHINode *PN : PHINodesToRemove) {
3489 removeInstruction(PN);
3492 ChangedFunction |= processInstruction(&Inst);
3493 return ChangedFunction;
3497bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3498 BasicBlock *Curr,
unsigned int ValNo) {
3504 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3512 if (!VN.exists(
Op)) {
3517 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3518 if (
Value *V = findLeader(Pred, TValNo)) {
3536 ICF->insertInstructionTo(Instr, Pred);
3538 unsigned Num = VN.lookupOrAdd(Instr);
3542 LeaderTable.insert(Num, Instr, Pred);
3546bool GVNPass::performScalarPRE(Instruction *CurInst) {
3572 if (CallB->isInlineAsm())
3576 uint32_t ValNo = VN.lookup(CurInst);
3584 unsigned NumWith = 0;
3585 unsigned NumWithout = 0;
3590 if (InvalidBlockRPONumbers)
3591 assignBlockRPONumber(*CurrentBlock->
getParent());
3597 if (!DT->isReachableFromEntry(
P)) {
3602 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3603 "Invalid BlockRPONumber map.");
3604 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3609 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3610 Value *PredV = findLeader(
P, TValNo);
3615 }
else if (PredV == CurInst) {
3627 if (NumWithout > 1 || NumWith == 0)
3635 if (NumWithout != 0) {
3641 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3654 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3658 PREInstr = CurInst->
clone();
3659 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3662 verifyRemoved(PREInstr);
3671 assert(PREInstr !=
nullptr || NumWithout == 0);
3677 CurInst->
getName() +
".pre-phi");
3678 Phi->insertBefore(CurrentBlock->begin());
3679 for (
auto &[V, BB] : PredMap) {
3684 Phi->addIncoming(V, BB);
3686 Phi->addIncoming(PREInstr, PREPred);
3692 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3693 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3696 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3697 MD->invalidateCachedPointerInfo(Phi);
3698 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3701 removeInstruction(CurInst);
3708bool GVNPass::performPRE(Function &
F) {
3710 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3712 if (CurrentBlock == &
F.getEntryBlock())
3716 if (CurrentBlock->isEHPad())
3720 BE = CurrentBlock->end();
3723 Changed |= performScalarPRE(CurInst);
3727 if (splitCriticalEdges())
3735BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3740 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3743 MD->invalidateCachedPredecessors();
3744 InvalidBlockRPONumbers =
true;
3751bool GVNPass::splitCriticalEdges() {
3752 if (ToSplit.empty())
3757 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3759 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3761 }
while (!ToSplit.empty());
3764 MD->invalidateCachedPredecessors();
3765 InvalidBlockRPONumbers =
true;
3771bool GVNPass::iterateOnFunction(Function &
F) {
3772 cleanupGlobalSets();
3779 ReversePostOrderTraversal<Function *> RPOT(&
F);
3781 for (BasicBlock *BB : RPOT)
3787void GVNPass::cleanupGlobalSets() {
3789 LeaderTable.clear();
3790 BlockRPONumber.clear();
3792 InvalidBlockRPONumbers =
true;
3795void GVNPass::removeInstruction(Instruction *
I) {
3797 if (MD) MD->removeInstruction(
I);
3799 MSSAU->removeMemoryAccess(
I);
3803 ICF->removeInstruction(
I);
3804 I->eraseFromParent();
3810void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3811 VN.verifyRemoved(Inst);
3818void GVNPass::addDeadBlock(BasicBlock *BB) {
3820 SmallSetVector<BasicBlock *, 4>
DF;
3823 while (!NewDead.
empty()) {
3825 if (DeadBlocks.count(
D))
3829 SmallVector<BasicBlock *, 8> Dom;
3830 DT->getDescendants(
D, Dom);
3831 DeadBlocks.insert_range(Dom);
3834 for (BasicBlock *
B : Dom) {
3836 if (DeadBlocks.count(S))
3839 bool AllPredDead =
true;
3841 if (!DeadBlocks.count(
P)) {
3842 AllPredDead =
false;
3862 for (BasicBlock *
B :
DF) {
3863 if (DeadBlocks.count(
B))
3869 for (BasicBlock *
P : Preds) {
3870 if (!DeadBlocks.count(
P))
3875 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3876 DeadBlocks.insert(
P = S);
3882 if (!DeadBlocks.count(
P))
3884 for (PHINode &Phi :
B->phis()) {
3887 MD->invalidateCachedPointerInfo(&Phi);
3906bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
3917 if (DeadBlocks.count(DeadRoot))
3921 DeadRoot = splitCriticalEdges(BI->getParent(), DeadRoot);
3923 addDeadBlock(DeadRoot);
3931void GVNPass::assignValNumForDeadCode() {
3932 for (BasicBlock *BB : DeadBlocks) {
3933 for (Instruction &Inst : *BB) {
3934 unsigned ValNum = VN.lookupOrAdd(&Inst);
3935 LeaderTable.insert(ValNum, &Inst, BB);
3946 bool ScalarPRE =
true)
3948 .setMemDep(MemDepAnalysis)
3949 .setMemorySSA(MemSSAAnalysis)
3950 .setScalarPRE(ScalarPRE)) {
3959 if (Impl.isMemorySSAEnabled() && !MSSAWP)
3962 return Impl.runImpl(
3967 Impl.isMemDepEnabled()
3972 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
3980 if (Impl.isMemDepEnabled())
3989 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 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.