91#define DEBUG_TYPE "gvn"
93STATISTIC(NumGVNInstr,
"Number of instructions deleted");
95STATISTIC(NumGVNPRE,
"Number of instructions PRE'd");
97STATISTIC(NumGVNSimpl,
"Number of instructions simplified");
98STATISTIC(NumGVNEqProp,
"Number of equalities propagated");
102 "Number of loads moved to predecessor of a critical edge in PRE");
104STATISTIC(IsValueFullyAvailableInBlockNumSpeculationsMax,
105 "Number of blocks speculated as available in "
106 "IsValueFullyAvailableInBlock(), max");
108 "Number of times we we reached gvn-max-block-speculations cut-off "
109 "preventing further exploration");
125 cl::desc(
"The number of memory accesses to scan in a block in reaching "
126 "memory values analysis (default = 100)"));
130 cl::desc(
"Max number of dependences to attempt Load PRE (default = 100)"));
134 cl::desc(
"Max number of blocks scanned per load in the MemorySSA "
135 "reaching-value analysis (default = 200)"));
140 cl::desc(
"Max number of blocks we're willing to speculate on (and recurse "
141 "into) when deducing if a value is fully available or not in GVN "
146 cl::desc(
"Max number of visited instructions when trying to find "
147 "dominating value of select dependency (default = 100)"));
151 cl::desc(
"Max number of instructions to scan in each basic block in GVN "
167 if (
Opcode != Other.Opcode)
175 if ((!
Attrs.isEmpty() || !Other.Attrs.isEmpty()) &&
176 !
Attrs.intersectWith(
Ty->getContext(), Other.Attrs).has_value())
310 Res.
AV = std::move(
AV);
326 return AV.MaterializeAdjustedValue(
Load,
BB->getTerminator());
337 E.Opcode =
I->getOpcode();
342 E.VarArgs.push_back(
lookupOrAdd(GCR->getOperand(0)));
343 E.VarArgs.push_back(
lookupOrAdd(GCR->getBasePtr()));
344 E.VarArgs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
346 for (
Use &
Op :
I->operands())
349 if (
I->isCommutative()) {
354 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
355 if (
E.VarArgs[0] >
E.VarArgs[1])
357 E.Commutative =
true;
361 E.VarArgs.append(IVI->idx_begin(), IVI->idx_end());
363 ArrayRef<int> ShuffleMask = SVI->getShuffleMask();
364 E.VarArgs.append(ShuffleMask.
begin(), ShuffleMask.
end());
366 E.Attrs = CB->getAttributes();
372GVNPass::Expression GVNPass::ValueTable::createCmpExpr(
374 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
375 "Not a comparison!");
378 E.VarArgs.push_back(lookupOrAdd(
LHS));
379 E.VarArgs.push_back(lookupOrAdd(
RHS));
382 if (
E.VarArgs[0] >
E.VarArgs[1]) {
386 E.Opcode = (Opcode << 8) | Predicate;
387 E.Commutative =
true;
392GVNPass::ValueTable::createExtractValueExpr(ExtractValueInst *EI) {
393 assert(EI &&
"Not an ExtractValueInst?");
404 E.VarArgs.push_back(lookupOrAdd(WO->
getLHS()));
405 E.VarArgs.push_back(lookupOrAdd(WO->
getRHS()));
413 E.VarArgs.push_back(lookupOrAdd(
Op));
420GVNPass::Expression GVNPass::ValueTable::createGEPExpr(GetElementPtrInst *
GEP) {
422 Type *PtrTy =
GEP->getType()->getScalarType();
423 const DataLayout &
DL =
GEP->getDataLayout();
424 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
425 SmallMapVector<Value *, APInt, 4> VariableOffsets;
427 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
431 E.Opcode =
GEP->getOpcode();
433 E.VarArgs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
434 for (
const auto &[V, Scale] : VariableOffsets) {
435 E.VarArgs.push_back(lookupOrAdd(V));
436 E.VarArgs.push_back(lookupOrAdd(ConstantInt::get(
Context, Scale)));
438 if (!ConstantOffset.isZero())
440 lookupOrAdd(ConstantInt::get(
Context, ConstantOffset)));
444 E.Opcode =
GEP->getOpcode();
445 E.Ty =
GEP->getSourceElementType();
446 for (Use &
Op :
GEP->operands())
447 E.VarArgs.push_back(lookupOrAdd(
Op));
456GVNPass::ValueTable::ValueTable() =
default;
457GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
458GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
459GVNPass::ValueTable::~ValueTable() =
default;
465 ValueNumbering.
insert(std::make_pair(V, Num));
467 NumberingPhi[Num] = PN;
477 assert(MSSA &&
"addMemoryStateToExp should not be called without MemorySSA");
478 assert(MSSA->getMemoryAccess(
I) &&
"Instruction does not access memory");
479 MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(
I);
480 Exp.VarArgs.push_back(lookupOrAdd(MA));
491 if (
C->getFunction()->isPresplitCoroutine()) {
492 ValueNumbering[
C] = NextValueNumber;
493 return NextValueNumber++;
499 if (
C->isConvergent()) {
500 ValueNumbering[
C] = NextValueNumber;
501 return NextValueNumber++;
507 if (
C->hasOperandBundles()) {
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::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::ICmp:
714 case Instruction::FCmp:
716 I->getOperand(0),
I->getOperand(1));
718 case Instruction::GetElementPtr:
721 case Instruction::ExtractValue:
724 case Instruction::PHI:
725 ValueNumbering[V] = NextValueNumber;
727 return NextValueNumber++;
728 case Instruction::Load:
729 case Instruction::Store:
730 return computeLoadStoreVN(
I);
732 ValueNumbering[V] = NextValueNumber;
733 return NextValueNumber++;
736 uint32_t E = assignExpNewValueNum(Exp).first;
737 ValueNumbering[V] = E;
744 auto VI = ValueNumbering.find(V);
746 assert(VI != ValueNumbering.end() &&
"Value not numbered?");
749 return (VI != ValueNumbering.end()) ? VI->second : 0;
756uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
759 Expression Exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
760 return assignExpNewValueNum(Exp).first;
768 return ExpressionNumbering.lookup(Exp);
773 ValueNumbering.clear();
774 ExpressionNumbering.clear();
775 NumberingPhi.clear();
777 PhiTranslateTable.clear();
786 uint32_t Num = ValueNumbering.lookup(V);
787 ValueNumbering.erase(V);
790 NumberingPhi.erase(Num);
792 NumberingBB.erase(Num);
797void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
798 assert(!ValueNumbering.contains(V) &&
799 "Inst still occurs in value numbering map!");
808 const auto &[It, Inserted] = NumToLeaders.try_emplace(
N, V, BB,
nullptr);
811 auto *NewSlot = TableAllocator.Allocate<LeaderListNode>();
812 new (NewSlot) LeaderListNode(V, BB, It->second.Next);
813 It->second.Next = NewSlot;
821 auto It = NumToLeaders.find(
N);
822 if (It == NumToLeaders.end())
825 LeaderListNode *Prev =
nullptr;
826 LeaderListNode *Curr = &It->second;
828 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
838 Prev->Next = Curr->Next;
839 Curr->~LeaderListNode();
840 TableAllocator.Deallocate<LeaderListNode>(Curr);
845 NumToLeaders.erase(It);
848 LeaderListNode *
Next = Curr->Next;
849 Curr->Entry.Val = std::move(
Next->Entry.Val);
850 Curr->Entry.BB =
Next->Entry.BB;
851 Curr->Next =
Next->Next;
852 Next->~LeaderListNode();
853 TableAllocator.Deallocate<LeaderListNode>(
Next);
875 return Options.AllowLoadPRESplitBackedge.value_or(
884 return Options.AllowMemDep.value_or(
false);
907 "On-demand computation of MemSSA implies that MemDep is disabled!");
911 bool Changed = runImpl(
F, AC, DT, TLI, AA, MemDep, LI, &ORE,
912 MSSA ? &MSSA->getMSSA() :
nullptr);
927 OS, MapClassName2PassName);
930 if (Options.AllowScalarPRE != std::nullopt)
931 OS << (*Options.AllowScalarPRE ?
"" :
"no-") <<
"scalar-pre;";
932 if (Options.AllowLoadPRE != std::nullopt)
933 OS << (*Options.AllowLoadPRE ?
"" :
"no-") <<
"load-pre;";
934 if (Options.AllowLoadPRESplitBackedge != std::nullopt)
935 OS << (*Options.AllowLoadPRESplitBackedge ?
"" :
"no-")
936 <<
"split-backedge-load-pre;";
937 if (Options.AllowMemDep != std::nullopt)
938 OS << (*Options.AllowMemDep ?
"" :
"no-") <<
"memdep;";
939 if (Options.AllowMemorySSA != std::nullopt)
940 OS << (*Options.AllowMemorySSA ?
"" :
"no-") <<
"memoryssa";
947 removeInstruction(
I);
974 std::optional<BasicBlock *> UnavailableBB;
978 unsigned NumNewNewSpeculativelyAvailableBBs = 0;
986 while (!Worklist.
empty()) {
990 std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator,
bool>
IV =
998 UnavailableBB = CurrBB;
1009 ++NumNewNewSpeculativelyAvailableBBs;
1015 MaxBBSpeculationCutoffReachedTimes += (int)OutOfBudget;
1017 UnavailableBB = CurrBB;
1023 NewSpeculativelyAvailableBBs.
insert(CurrBB);
1029#if LLVM_ENABLE_STATS
1030 IsValueFullyAvailableInBlockNumSpeculationsMax.updateMax(
1031 NumNewNewSpeculativelyAvailableBBs);
1036 auto MarkAsFixpointAndEnqueueSuccessors =
1038 auto It = FullyAvailableBlocks.
find(BB);
1039 if (It == FullyAvailableBlocks.
end())
1046 State = FixpointState;
1049 "Found a speculatively available successor leftover?");
1057 if (UnavailableBB) {
1064 while (!Worklist.
empty())
1065 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1073 while (!Worklist.
empty())
1074 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1078 "Must have fixed all the new speculatively available blocks.");
1081 return !UnavailableBB;
1090 if (V.AV.Val == OldValue)
1091 V.AV.Val = NewValue;
1092 if (V.AV.isSelectValue()) {
1093 if (V.AV.V1 == OldValue)
1095 if (V.AV.V2 == OldValue)
1110 if (ValuesPerBlock.
size() == 1 &&
1112 Load->getParent())) {
1113 assert(!ValuesPerBlock[0].AV.isUndefValue() &&
1114 "Dead BB dominate this block");
1115 return ValuesPerBlock[0].MaterializeAdjustedValue(
Load);
1126 if (AV.AV.isUndefValue())
1136 if (BB ==
Load->getParent() &&
1137 ((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() ==
Load) ||
1138 (AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() ==
Load)))
1155 if (Res->
getType() != LoadTy) {
1170 Load->getFunction());
1181 if (!CoercedLoad->
hasMetadata(LLVMContext::MD_noundef))
1183 {LLVMContext::MD_dereferenceable,
1184 LLVMContext::MD_dereferenceable_or_null,
1185 LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group,
1186 LLVMContext::MD_alias_scope, LLVMContext::MD_noalias});
1202 assert(
V1 &&
V2 &&
"both value operands of the select must be present");
1210 assert(Res &&
"failed to materialize?");
1216 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1233 Value *PtrOp =
Load->getPointerOperand();
1239 for (
auto *U : PtrOp->
users()) {
1260 for (
auto *U : PtrOp->
users()) {
1263 if (
I->getFunction() ==
Load->getFunction() &&
1271 OtherAccess =
nullptr;
1290 using namespace ore;
1293 R <<
"load of type " << NV(
"Type",
Load->getType()) <<
" not eliminated"
1298 R <<
" in favor of " << NV(
"OtherAccess", OtherAccess);
1300 R <<
" because it is clobbered by " << NV(
"ClobberedBy", DepInst);
1314 for (
auto *Inst = BB == FromBB ? From : BB->
getTerminator();
1322 if (
SI->isSimple() &&
SI->getPointerOperand() ==
Loc.Ptr &&
1323 SI->getValueOperand()->getType() == LoadTy)
1324 return SI->getValueOperand();
1328 if (LI->getPointerOperand() ==
Loc.Ptr && LI->getType() == LoadTy)
1334std::optional<AvailableValue>
1336 Value *FalseAddr, Instruction *From) {
1338 "Invalid address type of true side of select dependency");
1340 "Invalid address type of false side of select dependency");
1348 return std::nullopt;
1352 return std::nullopt;
1356std::optional<AvailableValue>
1357GVNPass::analyzeLoadAvailability(LoadInst *
Load,
const ReachingMemVal &Dep,
1359 assert(
Load->isUnordered() &&
"rules below are incorrect for ordered access");
1360 assert((Dep.Kind == DepKind::Def || Dep.Kind == DepKind::Clobber) &&
1361 "expected a local dependence");
1365 const DataLayout &
DL =
Load->getDataLayout();
1366 if (Dep.Kind == DepKind::Clobber) {
1372 if (
Address &&
Load->isAtomic() <= DepSI->isAtomic()) {
1389 Load->isAtomic() <= DepLoad->isAtomic()) {
1396 DepLoad->getFunction())) {
1397 const auto ClobberOff = MD->getClobberOffset(DepLoad);
1399 Offset = (ClobberOff == std::nullopt || *ClobberOff < 0)
1405 DepLoad->getFunction()) ||
1432 dbgs() <<
" is clobbered by " << *DepInst <<
'\n';);
1436 return std::nullopt;
1438 assert(Dep.Kind == DepKind::Def &&
"follows from above");
1445 if (Constant *InitVal =
1455 return std::nullopt;
1458 if (S->isAtomic() <
Load->isAtomic())
1459 return std::nullopt;
1470 return std::nullopt;
1473 if (
LD->isAtomic() <
Load->isAtomic())
1474 return std::nullopt;
1483 assert(Sel->getType() ==
Load->getPointerOperandType());
1484 if (
auto AV = analyzeSelectAvailability(
Load, Sel->getCondition(),
1485 Sel->getTrueValue(),
1486 Sel->getFalseValue(), DepInst))
1488 return std::nullopt;
1495 dbgs() <<
" has unknown def " << *DepInst <<
'\n';);
1496 return std::nullopt;
1499void GVNPass::analyzeLoadAvailability(LoadInst *
Load,
1500 SmallVectorImpl<ReachingMemVal> &Deps,
1501 AvailValInBlkVect &ValuesPerBlock,
1502 UnavailBlkVect &UnavailableBlocks) {
1507 for (
const auto &Dep : Deps) {
1510 if (DeadBlocks.count(DepBB)) {
1517 if (Dep.Kind == DepKind::Other) {
1518 UnavailableBlocks.push_back(DepBB);
1525 if (Dep.Kind == DepKind::Select) {
1526 if (
auto AV = analyzeSelectAvailability(
1528 const_cast<Value *
>(Dep.SelTrueAddr),
1530 ValuesPerBlock.push_back(
1533 UnavailableBlocks.push_back(DepBB);
1542 analyzeLoadAvailability(
Load, Dep,
const_cast<Value *
>(Dep.Addr))) {
1546 ValuesPerBlock.push_back(
1549 UnavailableBlocks.push_back(DepBB);
1553 assert(Deps.size() == ValuesPerBlock.size() + UnavailableBlocks.size() &&
1554 "post condition violation");
1576LoadInst *GVNPass::findLoadToHoistIntoPred(BasicBlock *Pred, BasicBlock *LoadBB,
1580 if (
Term->getNumSuccessors() != 2 ||
Term->isSpecialTerminator())
1582 auto *SuccBB =
Term->getSuccessor(0);
1583 if (SuccBB == LoadBB)
1584 SuccBB =
Term->getSuccessor(1);
1585 if (!SuccBB->getSinglePredecessor())
1589 for (Instruction &Inst : *SuccBB) {
1590 if (Inst.isDebugOrPseudoInst())
1592 if (--NumInsts == 0)
1595 if (!Inst.isIdenticalTo(
Load))
1598 bool HasLocalDep =
true;
1600 MemDepResult Dep = MD->getDependency(&Inst);
1603 auto *MSSA = MSSAU->getMemorySSA();
1605 if (
auto *MA = MSSA->getMemoryAccess(&Inst); MA &&
isa<MemoryUse>(MA)) {
1606 auto *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(MA);
1607 HasLocalDep = Clobber->getBlock() == SuccBB;
1615 if (!HasLocalDep && !ICF->isDominatedByICFIFromSameBlock(&Inst))
1626void GVNPass::eliminatePartiallyRedundantLoad(
1627 LoadInst *
Load, AvailValInBlkVect &ValuesPerBlock,
1628 MapVector<BasicBlock *, Value *> &AvailableLoads,
1629 MapVector<BasicBlock *, LoadInst *> *CriticalEdgePredAndLoad) {
1630 for (
const auto &AvailableLoad : AvailableLoads) {
1631 BasicBlock *UnavailableBlock = AvailableLoad.first;
1632 Value *LoadPtr = AvailableLoad.second;
1635 new LoadInst(
Load->getType(), LoadPtr,
Load->getName() +
".pre",
1636 Load->getProperties(),
1638 NewLoad->setDebugLoc(
Load->getDebugLoc());
1640 auto *NewAccess = MSSAU->createMemoryAccessInBB(
1643 MSSAU->insertDef(NewDef,
true);
1649 AAMDNodes Tags =
Load->getAAMetadata();
1651 NewLoad->setAAMetadata(Tags);
1653 if (
auto *MD =
Load->getMetadata(LLVMContext::MD_invariant_load))
1654 NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
1655 if (
auto *InvGroupMD =
Load->getMetadata(LLVMContext::MD_invariant_group))
1656 NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
1657 if (
auto *RangeMD =
Load->getMetadata(LLVMContext::MD_range))
1658 NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
1659 if (
auto *NoFPClassMD =
Load->getMetadata(LLVMContext::MD_nofpclass))
1660 NewLoad->setMetadata(LLVMContext::MD_nofpclass, NoFPClassMD);
1662 if (
auto *AccessMD =
Load->getMetadata(LLVMContext::MD_access_group))
1663 if (LI->getLoopFor(
Load->getParent()) == LI->getLoopFor(UnavailableBlock))
1664 NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
1673 ValuesPerBlock.push_back(
1676 MD->invalidateCachedPointerInfo(LoadPtr);
1681 if (CriticalEdgePredAndLoad) {
1682 auto It = CriticalEdgePredAndLoad->
find(UnavailableBlock);
1683 if (It != CriticalEdgePredAndLoad->
end()) {
1684 ++NumPRELoadMoved2CEPred;
1685 ICF->insertInstructionTo(NewLoad, UnavailableBlock);
1686 LoadInst *OldLoad = It->second;
1690 if (uint32_t ValNo = VN.lookup(OldLoad,
false))
1691 LeaderTable.erase(ValNo, OldLoad, OldLoad->
getParent());
1692 removeInstruction(OldLoad);
1700 ICF->removeUsersOf(
Load);
1701 Load->replaceAllUsesWith(V);
1705 I->setDebugLoc(
Load->getDebugLoc());
1706 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
1707 MD->invalidateCachedPointerInfo(V);
1710 <<
"load eliminated by PRE";
1715bool GVNPass::performLoadPRE(LoadInst *
Load, AvailValInBlkVect &ValuesPerBlock,
1716 UnavailBlkVect &UnavailableBlocks) {
1725 SmallPtrSet<BasicBlock *, 4> Blockers(
llvm::from_range, UnavailableBlocks);
1747 bool MustEnsureSafetyOfSpeculativeExecution =
1748 ICF->isDominatedByICFIFromSameBlock(
Load);
1752 if (TmpBB == LoadBB)
1754 if (Blockers.count(TmpBB))
1766 MustEnsureSafetyOfSpeculativeExecution =
1767 MustEnsureSafetyOfSpeculativeExecution || ICF->hasICF(TmpBB);
1775 MapVector<BasicBlock *, Value *> PredLoads;
1776 DenseMap<BasicBlock *, AvailabilityState> FullyAvailableBlocks;
1779 for (BasicBlock *UnavailableBB : UnavailableBlocks)
1787 MapVector<BasicBlock *, LoadInst *> CriticalEdgePredAndLoad;
1793 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
1805 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
1812 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
1819 if (DT->dominates(LoadBB, Pred)) {
1822 <<
"COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
1827 if (LoadInst *LI = findLoadToHoistIntoPred(Pred, LoadBB,
Load))
1828 CriticalEdgePredAndLoad[Pred] = LI;
1833 PredLoads[Pred] =
nullptr;
1838 unsigned NumInsertPreds = PredLoads.
size() + CriticalEdgePredSplit.
size();
1839 unsigned NumUnavailablePreds = NumInsertPreds +
1840 CriticalEdgePredAndLoad.
size();
1841 assert(NumUnavailablePreds != 0 &&
1842 "Fully available value should already be eliminated!");
1843 (void)NumUnavailablePreds;
1849 if (NumInsertPreds > 1)
1854 if (MustEnsureSafetyOfSpeculativeExecution) {
1855 if (CriticalEdgePredSplit.
size())
1859 for (
auto &PL : PredLoads)
1863 for (
auto &CEP : CriticalEdgePredAndLoad)
1870 for (BasicBlock *OrigPred : CriticalEdgePredSplit) {
1871 BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
1872 assert(!PredLoads.count(OrigPred) &&
"Split edges shouldn't be in map!");
1873 PredLoads[NewPred] =
nullptr;
1874 LLVM_DEBUG(
dbgs() <<
"Split critical edge " << OrigPred->getName() <<
"->"
1875 << LoadBB->
getName() <<
'\n');
1878 for (
auto &CEP : CriticalEdgePredAndLoad)
1879 PredLoads[CEP.first] =
nullptr;
1882 bool CanDoPRE =
true;
1883 const DataLayout &
DL =
Load->getDataLayout();
1884 SmallVector<Instruction*, 8> NewInsts;
1885 for (
auto &PredLoad : PredLoads) {
1886 BasicBlock *UnavailablePred = PredLoad.first;
1896 Value *LoadPtr =
Load->getPointerOperand();
1898 while (Cur != LoadBB) {
1911 LoadPtr =
Address.translateWithInsertion(LoadBB, UnavailablePred, *DT,
1918 << *
Load->getPointerOperand() <<
"\n");
1923 PredLoad.second = LoadPtr;
1927 while (!NewInsts.
empty()) {
1937 return !CriticalEdgePredSplit.empty();
1945 <<
" INSTS: " << *NewInsts.
back()
1949 for (Instruction *
I : NewInsts) {
1953 I->updateLocationAfterHoist();
1962 eliminatePartiallyRedundantLoad(
Load, ValuesPerBlock, PredLoads,
1963 &CriticalEdgePredAndLoad);
1968bool GVNPass::performLoopLoadPRE(LoadInst *
Load,
1969 AvailValInBlkVect &ValuesPerBlock,
1970 UnavailBlkVect &UnavailableBlocks) {
1971 const Loop *
L = LI->getLoopFor(
Load->getParent());
1973 if (!L ||
L->getHeader() !=
Load->getParent())
1978 if (!Preheader || !Latch)
1981 Value *LoadPtr =
Load->getPointerOperand();
1983 if (!
L->isLoopInvariant(LoadPtr))
1989 if (ICF->isDominatedByICFIFromSameBlock(
Load))
1993 for (
auto *Blocker : UnavailableBlocks) {
1995 if (!
L->contains(Blocker))
2007 if (L != LI->getLoopFor(Blocker))
2015 if (DT->dominates(Blocker, Latch))
2019 if (Blocker->getTerminator()->mayWriteToMemory())
2022 LoopBlock = Blocker;
2034 MapVector<BasicBlock *, Value *> AvailableLoads;
2035 AvailableLoads[LoopBlock] = LoadPtr;
2036 AvailableLoads[Preheader] = LoadPtr;
2039 eliminatePartiallyRedundantLoad(
Load, ValuesPerBlock, AvailableLoads,
2047 using namespace ore;
2051 <<
"load of type " << NV(
"Type",
Load->getType()) <<
" eliminated"
2052 << setExtraArgs() <<
" in favor of "
2059bool GVNPass::processNonLocalLoad(LoadInst *
Load) {
2061 if (
Load->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2062 Load->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2067 MD->getNonLocalPointerDependency(
Load, Deps);
2072 unsigned NumDeps = Deps.size();
2079 for (
const NonLocalDepResult &Dep : Deps) {
2080 const auto &
R = Dep.getResult();
2081 SelectAddr SelAddr = Dep.getAddress();
2087 ReachingMemVal::getSelect(BB,
Cond, Addrs.first, Addrs.second));
2099 return processNonLocalLoad(
Load, MemVals);
2102bool GVNPass::processNonLocalLoad(LoadInst *
Load,
2103 SmallVectorImpl<ReachingMemVal> &Deps) {
2106 if (Deps.
size() == 1 && Deps[0].Kind == DepKind::Other) {
2108 dbgs() <<
" has unknown dependencies\n";);
2116 if (GetElementPtrInst *
GEP =
2118 for (Use &U :
GEP->indices())
2128 AvailValInBlkVect ValuesPerBlock;
2129 UnavailBlkVect UnavailableBlocks;
2130 analyzeLoadAvailability(
Load, Deps, ValuesPerBlock, UnavailableBlocks);
2134 if (ValuesPerBlock.empty())
2142 if (UnavailableBlocks.empty()) {
2148 ICF->removeUsersOf(
Load);
2149 Load->replaceAllUsesWith(V);
2157 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2158 I->setDebugLoc(
Load->getDebugLoc());
2159 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2160 MD->invalidateCachedPointerInfo(V);
2173 if (performLoopLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks) ||
2174 performLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks))
2180bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2184 if (
Cond->isZero()) {
2194 const MemoryUseOrDef *FirstNonDom =
nullptr;
2196 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2203 for (
const auto &Acc : *AL) {
2205 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2206 FirstNonDom = Current;
2213 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2215 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2216 : MSSAU->createMemoryAccessInBB(
2238 return propagateEquality(V, True, IntrinsicI);
2243 I->replaceAllUsesWith(Repl);
2250 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2261 PointerUsesQueue.
push_back(PointerOperand);
2266 while (!PointerUsesQueue.
empty()) {
2269 "Null or GlobalValue should not be inserted");
2273 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2288 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2290 MostDominatingInstruction =
I;
2294 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2300static std::optional<MemoryLocation>
2307 switch (
II->getIntrinsicID()) {
2308 case Intrinsic::masked_load:
2310 case Intrinsic::masked_store:
2313 return std::nullopt;
2320 return std::nullopt;
2324 return std::nullopt;
2330std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2331 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2332 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2333 BatchAAResults &AA, LoadInst *L) {
2336 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2340 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2342 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2350 Choice->Kind = DepKind::Clobber;
2351 Choice->Offset = AR.getOffset();
2353 Choice->Kind = DepKind::Def;
2354 Choice->Offset = -1;
2357 Choice->Inst = Candidate;
2358 Choice->Block = Candidate->getParent();
2361 std::optional<ReachingMemVal> ReachingVal;
2362 for (MemoryAccess *MA : ClobbersList) {
2364 for (User *U : MA->
users()) {
2366 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2369 if (!UseOrDef || UseOrDef->getBlock() != BB)
2378 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2392 UpdateChoice(ReachingVal, AR, MemI);
2404std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2405 MemoryAccess *ClobberMA,
const MemoryLocation &Loc, Align LoadAlign,
2406 bool IsInvariantLoad, BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2414 if (
Alloc->getParent() == BB)
2415 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2416 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2420 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2421 return std::nullopt;
2425 return L->getOrdering();
2432 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2434 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2445 return std::nullopt;
2446 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2451 return std::nullopt;
2458 return std::nullopt;
2463 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2468 "Must be the superset/partial overlap case with positive offset");
2469 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2474 return std::nullopt;
2475 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2477 if (AA.isMustAlias(IIObjLoc, Loc))
2478 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2479 return std::nullopt;
2487 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2488 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2494 return std::nullopt;
2498 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2502 return std::nullopt;
2506 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2512bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2513 MemoryAccess *ClobberMA,
2514 DependencyBlockSet &Blocks,
2515 SmallVectorImpl<BasicBlock *> &Worklist) {
2525 if (!DT->isReachableFromEntry(Pred))
2529 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2532 PHITransAddr TransAddr = Addr;
2536 auto It = Blocks.find(Pred);
2537 if (It != Blocks.end()) {
2541 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2548 Pred, DependencyBlockInfo(TransAddr,
2549 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2556 for (
auto &
P : Preds) {
2557 [[maybe_unused]]
auto It =
2558 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2570void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2572 const DependencyBlockInfo &StartInfo,
2573 const DependencyBlockSet &Blocks,
2575 MemoryAccess *MA = StartInfo.InitialClobberMA;
2576 MemoryAccess *LastMA = StartInfo.ClobberMA;
2579 while (MA != LastMA) {
2593 BB = DT->getNode(BB)->getIDom()->getBlock();
2597 auto It = Blocks.find(BB);
2598 if (It == Blocks.end())
2601 MA = It->second.InitialClobberMA;
2602 LastMA = It->second.ClobberMA;
2603 if (MA == Clobbers.
back())
2620bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2621 SmallVectorImpl<ReachingMemVal> &
Values,
2623 EarliestEscapeAnalysis EA(*DT, LI);
2624 BatchAAResults AA(AAR, &EA);
2626 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2632 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2645 if (
auto RMV = scanMemoryAccessesUsers(
2646 Loc, IsInvariantLoad, StartBlock,
2648 Values.emplace_back(*RMV);
2659 accessMayModifyLocation(ClobberMA, Loc,
L->getAlign(),
2660 IsInvariantLoad, StartBlock, MSSA, AA)) {
2661 Values.emplace_back(*RMV);
2668 }
while (ClobberMA->
getBlock() == StartBlock);
2671 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2672 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2681 DependencyBlockSet Blocks;
2682 SmallVector<BasicBlock *, 16> InitialWorklist;
2683 const DataLayout &
DL =
L->getModule()->getDataLayout();
2684 if (!collectPredecessors(StartBlock,
2685 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2686 ClobberMA, Blocks, InitialWorklist))
2690 auto Worklist = InitialWorklist;
2691 while (!Worklist.
empty()) {
2696 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2699 if (!
Info.Addr.getAddr())
2709 accessMayModifyLocation(
Info.ClobberMA, BBLoc,
L->getAlign(),
2710 IsInvariantLoad, BB, MSSA, AA)) {
2715 "LiveOnEntry aliases everything");
2731 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2732 Info.ForceUnknown =
true;
2735 if (BB != StartBlock &&
2736 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2737 Info.ForceUnknown =
true;
2747 Worklist = InitialWorklist;
2748 for (BasicBlock *BB : Worklist) {
2749 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2750 Info.Visited =
true;
2754 while (!Worklist.empty()) {
2755 auto *BB = Worklist.pop_back_val();
2756 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2760 if (!
Info.Addr.getAddr()) {
2761 Values.push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2766 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2769 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2781 if (
Info.ForceUnknown) {
2782 Values.push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2788 auto It = Blocks.find(Pred);
2789 if (It == Blocks.end())
2791 DependencyBlockInfo &PredInfo = It->second;
2792 if (PredInfo.Visited)
2794 PredInfo.Visited =
true;
2795 Worklist.push_back(Pred);
2804bool GVNPass::processLoad(LoadInst *L) {
2809 if (!
L->isUnordered())
2812 if (
L->getType()->isTokenLikeTy())
2815 if (
L->use_empty()) {
2820 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2823 MemDepResult Dep = MD->getDependency(L);
2827 return processNonLocalLoad(L);
2831 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2834 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2837 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2839 assert(MemVals.
size() &&
"Expected at least an unknown value");
2840 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2841 return processNonLocalLoad(L, MemVals);
2843 MemVal = MemVals[0];
2846 if (MemVal.Kind == DepKind::Other) {
2850 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2851 dbgs() <<
" has unknown dependence\n";);
2855 auto AV = analyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2862 ICF->removeUsersOf(L);
2865 MSSAU->removeMemoryAccess(L);
2878bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2881 MemDepResult Dep = MD->getDependency(
I);
2887 Value *Passthrough =
I->getOperand(2);
2891 StoreVal->
getType() !=
I->getType())
2898 ICF->removeUsersOf(
I);
2899 I->replaceAllUsesWith(OpToForward);
2907std::pair<uint32_t, bool>
2908GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2909 uint32_t &
E = ExpressionNumbering[
Exp];
2910 bool CreateNewValNum = !
E;
2911 if (CreateNewValNum) {
2912 Expressions.push_back(Exp);
2913 if (ExprIdx.size() < NextValueNumber + 1)
2914 ExprIdx.resize(NextValueNumber * 2);
2915 E = NextValueNumber;
2916 ExprIdx[NextValueNumber++] = NextExprNumber++;
2918 return {
E, CreateNewValNum};
2923bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2926 GVN.LeaderTable.getLeaders(Num),
2934 auto FindRes = PhiTranslateTable.find({Num, Pred});
2935 if (FindRes != PhiTranslateTable.end())
2936 return FindRes->second;
2937 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2938 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2949 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2950 for (
const auto &Entry : Leaders) {
2952 if (
Call &&
Call->getParent() == PhiBlock)
2956 if (
AA->doesNotAccessMemory(
Call))
2959 if (!MD || !
AA->onlyReadsMemory(
Call))
2971 if (
D.getResult().isNonFuncLocal())
2979uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2980 const BasicBlock *PhiBlock,
2984 if (PHINode *PN = NumberingPhi[Num]) {
2985 if (PN->getParent() != PhiBlock)
2987 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2988 if (PN->getIncomingBlock(
I) != Pred)
2990 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2996 if (BasicBlock *BB = NumberingBB[Num]) {
2997 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
3009 return lookupOrAdd(PredPhi->getBlock());
3015 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
3021 if (!areAllValsInBB(Num, PhiBlock, GVN))
3024 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
3028 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
3032 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
3033 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
3034 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
3036 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
3039 if (
Exp.Commutative) {
3040 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
3041 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
3043 uint32_t Opcode =
Exp.Opcode >> 8;
3044 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
3045 Exp.Opcode = (Opcode << 8) |
3051 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
3052 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
3053 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3061void GVNPass::ValueTable::eraseTranslateCacheEntry(
3064 PhiTranslateTable.erase({Num, Pred});
3073 auto Leaders = LeaderTable.getLeaders(Num);
3074 if (Leaders.empty())
3077 Value *Val =
nullptr;
3078 for (
const auto &Entry : Leaders) {
3079 if (DT->dominates(Entry.BB, BB)) {
3099 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3100 assert((!Pred || Pred ==
E.getStart()) &&
3101 "No edge between these basic blocks!");
3102 return Pred !=
nullptr;
3105void GVNPass::assignBlockRPONumber(
Function &
F) {
3106 BlockRPONumber.clear();
3107 uint32_t NextBlockNumber = 1;
3108 ReversePostOrderTraversal<Function *> RPOT(&
F);
3109 for (BasicBlock *BB : RPOT)
3110 BlockRPONumber[BB] = NextBlockNumber++;
3111 InvalidBlockRPONumbers =
false;
3119bool GVNPass::propagateEquality(
3121 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3123 SmallDenseSet<std::pair<Value *, Value *>, 4> Visited;
3127 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3134 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3138 while (!Worklist.
empty()) {
3139 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3140 LHS = Item.first;
RHS = Item.second;
3154 const DataLayout &
DL =
3163 uint32_t LVN = VN.lookupOrAdd(
LHS);
3168 uint32_t RVN = VN.lookupOrAdd(
RHS);
3175 if (!Visited.
insert({LHS, RHS}).second)
3188 for (
const BasicBlock *BB : DominatedBlocks)
3189 LeaderTable.insert(LVN,
RHS, BB);
3196 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3199 unsigned NumReplacements;
3200 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3202 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3205 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3206 CanReplacePointersCallBack);
3208 if (NumReplacements > 0) {
3210 NumGVNEqProp += NumReplacements;
3213 MD->invalidateCachedPointerInfo(
LHS);
3230 bool IsKnownFalse = !IsKnownTrue;
3246 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3251 if (
Cmp->isEquivalence(IsKnownFalse))
3252 Worklist.
push_back(std::make_pair(Op0, Op1));
3256 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3260 uint32_t NextNum = VN.getNextUnusedValueNumber();
3261 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3264 if (Num < NextNum) {
3265 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3270 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3271 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3272 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3275 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3276 if (!DT->dominates(
Entry.BB, InstBB) &&
3277 !DT->dominates(InstBB,
Entry.BB))
3283 unsigned NumReplacements;
3284 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3289 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3290 Changed |= NumReplacements > 0;
3291 NumGVNEqProp += NumReplacements;
3294 MD->invalidateCachedPointerInfo(NotCmp);
3302 for (
const BasicBlock *BB : DominatedBlocks)
3303 LeaderTable.insert(Num, NotVal, BB);
3312 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3317 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3327bool GVNPass::processInstruction(Instruction *
I) {
3332 const DataLayout &
DL =
I->getDataLayout();
3335 if (!
I->use_empty()) {
3338 ICF->removeUsersOf(
I);
3339 I->replaceAllUsesWith(V);
3347 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3348 MD->invalidateCachedPointerInfo(V);
3355 return processAssumeIntrinsic(Assume);
3358 if (processLoad(
Load))
3361 unsigned Num = VN.lookupOrAdd(
Load);
3362 LeaderTable.insert(Num,
Load,
Load->getParent());
3374 return processFoldableCondBr(BI);
3376 Value *BranchCond = BI->getCondition();
3380 if (TrueSucc == FalseSucc)
3387 BasicBlockEdge TrueE(Parent, TrueSucc);
3388 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3391 BasicBlockEdge FalseE(Parent, FalseSucc);
3392 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3399 Value *SwitchCond =
SI->getCondition();
3404 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3406 ++SwitchEdges[Succ];
3408 for (
const auto &Case :
SI->cases()) {
3411 if (SwitchEdges.
lookup(Dst) == 1) {
3412 BasicBlockEdge
E(Parent, Dst);
3413 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3421 if (
I->getType()->isVoidTy())
3424 uint32_t NextNum = VN.getNextUnusedValueNumber();
3425 unsigned Num = VN.lookupOrAdd(
I);
3430 LeaderTable.insert(Num,
I,
I->getParent());
3437 const DataLayout &
DL =
I->getDataLayout();
3438 unsigned AS = PTA->getPointerAddressSpace();
3439 if (
DL.getAddressSizeInBits(AS) ==
DL.getPointerSizeInBits(AS) &&
3440 !
DL.hasUnstableRepresentation(AS)) {
3442 VN.lookupPtrToInt(PTA->getPointerOperand(), PTA->getType());
3443 if (
Value *PTI = findLeader(
I->getParent(), PTINum)) {
3454 if (Num >= NextNum) {
3455 LeaderTable.insert(Num,
I,
I->getParent());
3461 Value *Repl = findLeader(
I->getParent(), Num);
3464 LeaderTable.insert(Num,
I,
I->getParent());
3477 MD->invalidateCachedPointerInfo(Repl);
3483bool GVNPass::runImpl(
Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3484 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3485 MemoryDependenceResults *RunMD, LoopInfo &LI,
3486 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3494 "mutually exclusive",
3501 VN.setAliasAnalysis(&RunAA);
3503 ImplicitControlFlowTracking ImplicitCFT;
3512 InvalidBlockRPONumbers =
true;
3513 MemorySSAUpdater Updater(MSSA);
3514 MSSAU = MSSA ? &Updater :
nullptr;
3517 bool ShouldContinue =
true;
3519 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3531 unsigned Iteration = 0;
3532 while (ShouldContinue) {
3535 ShouldContinue = iterateOnFunction(
F);
3543 assignValNumForDeadCode();
3544 bool PREChanged =
true;
3545 while (PREChanged) {
3546 PREChanged = performPRE(
F);
3556 cleanupGlobalSets();
3567bool GVNPass::processBlock(BasicBlock *BB) {
3568 if (DeadBlocks.count(BB))
3571 bool ChangedFunction =
false;
3577 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3579 for (PHINode *PN : PHINodesToRemove) {
3580 removeInstruction(PN);
3583 ChangedFunction |= processInstruction(&Inst);
3584 return ChangedFunction;
3588bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3589 BasicBlock *Curr,
unsigned int ValNo) {
3595 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3603 if (!VN.exists(
Op)) {
3608 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3609 if (
Value *V = findLeader(Pred, TValNo)) {
3627 ICF->insertInstructionTo(Instr, Pred);
3629 unsigned Num = VN.lookupOrAdd(Instr);
3633 LeaderTable.insert(Num, Instr, Pred);
3637bool GVNPass::performScalarPRE(Instruction *CurInst) {
3663 if (CallB->isInlineAsm())
3667 uint32_t ValNo = VN.lookup(CurInst);
3675 unsigned NumWith = 0;
3676 unsigned NumWithout = 0;
3681 if (InvalidBlockRPONumbers)
3682 assignBlockRPONumber(*CurrentBlock->
getParent());
3688 if (!DT->isReachableFromEntry(
P)) {
3693 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3694 "Invalid BlockRPONumber map.");
3695 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3700 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3701 Value *PredV = findLeader(
P, TValNo);
3706 }
else if (PredV == CurInst) {
3718 if (NumWithout > 1 || NumWith == 0)
3726 if (NumWithout != 0) {
3732 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3745 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3749 PREInstr = CurInst->
clone();
3750 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3753 verifyRemoved(PREInstr);
3762 assert(PREInstr !=
nullptr || NumWithout == 0);
3768 CurInst->
getName() +
".pre-phi");
3769 Phi->insertBefore(CurrentBlock->begin());
3770 for (
auto &[V, BB] : PredMap) {
3775 Phi->addIncoming(V, BB);
3777 Phi->addIncoming(PREInstr, PREPred);
3783 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3784 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3787 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3788 MD->invalidateCachedPointerInfo(Phi);
3789 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3792 removeInstruction(CurInst);
3801 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3803 if (CurrentBlock == &
F.getEntryBlock())
3807 if (CurrentBlock->isEHPad())
3811 BE = CurrentBlock->end();
3814 Changed |= performScalarPRE(CurInst);
3818 if (splitCriticalEdges())
3826BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3831 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3834 MD->invalidateCachedPredecessors();
3835 InvalidBlockRPONumbers =
true;
3842bool GVNPass::splitCriticalEdges() {
3843 if (ToSplit.empty())
3848 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3850 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3852 }
while (!ToSplit.empty());
3855 MD->invalidateCachedPredecessors();
3856 InvalidBlockRPONumbers =
true;
3862bool GVNPass::iterateOnFunction(
Function &
F) {
3863 cleanupGlobalSets();
3870 ReversePostOrderTraversal<Function *> RPOT(&
F);
3872 for (BasicBlock *BB : RPOT)
3878void GVNPass::cleanupGlobalSets() {
3880 LeaderTable.clear();
3881 BlockRPONumber.clear();
3883 InvalidBlockRPONumbers =
true;
3886void GVNPass::removeInstruction(Instruction *
I) {
3888 if (MD) MD->removeInstruction(
I);
3890 MSSAU->removeMemoryAccess(
I);
3894 ICF->removeInstruction(
I);
3895 I->eraseFromParent();
3901void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3902 VN.verifyRemoved(Inst);
3909void GVNPass::addDeadBlock(BasicBlock *BB) {
3911 SmallSetVector<BasicBlock *, 4>
DF;
3914 while (!NewDead.
empty()) {
3916 if (DeadBlocks.count(
D))
3920 SmallVector<BasicBlock *, 8> Dom;
3921 DT->getDescendants(
D, Dom);
3922 DeadBlocks.insert_range(Dom);
3925 for (BasicBlock *
B : Dom) {
3927 if (DeadBlocks.count(S))
3930 bool AllPredDead =
true;
3932 if (!DeadBlocks.count(
P)) {
3933 AllPredDead =
false;
3953 for (BasicBlock *
B :
DF) {
3954 if (DeadBlocks.count(
B))
3960 for (BasicBlock *
P : Preds) {
3961 if (!DeadBlocks.count(
P))
3966 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3967 DeadBlocks.insert(
P = S);
3973 if (!DeadBlocks.count(
P))
3975 for (PHINode &Phi :
B->phis()) {
3978 MD->invalidateCachedPointerInfo(&Phi);
3997bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
4008 if (DeadBlocks.count(DeadRoot))
4012 DeadRoot = splitCriticalEdges(BI->
getParent(), DeadRoot);
4014 addDeadBlock(DeadRoot);
4022void GVNPass::assignValNumForDeadCode() {
4023 for (BasicBlock *BB : DeadBlocks) {
4024 for (Instruction &Inst : *BB) {
4025 unsigned ValNum = VN.lookupOrAdd(&Inst);
4026 LeaderTable.insert(ValNum, &Inst, BB);
4037 bool ScalarPRE =
true)
4039 .setMemDep(MemDepAnalysis)
4040 .setMemorySSA(MemSSAAnalysis)
4041 .setScalarPRE(ScalarPRE)) {
4050 if (Impl.isMemorySSAEnabled() && !MSSAWP)
4053 return Impl.runImpl(
4058 Impl.isMemDepEnabled()
4063 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
4071 if (Impl.isMemDepEnabled())
4080 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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")
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 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 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)
GVNPass::AvailableValue AvailableValue
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< uint32_t > MaxNumReachingBlocks("gvn-max-num-reaching-blocks", cl::Hidden, cl::init(200), cl::desc("Max number of blocks scanned per load in the MemorySSA " "reaching-value analysis (default = 200)"))
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 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)"))
@ 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))
GVNPass::AvailableValueInBlock AvailableValueInBlock
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.
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.
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
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)
This class holds the mapping between values and value numbers.
LLVM_ABI uint32_t lookupOrAdd(MemoryAccess *MA)
The core GVN pass object.
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
friend class GVNLegacyPass
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(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object 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.
std::pair< Value *, SelectAddrs > getSelectCondAndAddrs() 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.
int getNumOccurrences() const
std::pair< iterator, bool > insert(const ValueT &V)
An efficient, type-erasing, non-owning reference to a callable.
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.
@ 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.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
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_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_MaskedStore(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedStore Intrinsic.
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)
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.
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...
RelativeUniformCounterPtr Values
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.
@ Load
The value being inserted comes from a load (InsertElement only).
constexpr from_range_t from_range
LLVM_ABI bool isStorePreservingMemoryLocation(const StoreInst *SI, const MemoryLocation &MemLoc, Align MemLocAlign, BatchAAResults &AA, unsigned ScanLimit)
Check whether SI, which may alias MemLoc, can be safely skipped.
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 ...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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 report_fatal_error(Error Err, bool gen_crash_diag=true)
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...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
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...
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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 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.
Represents an AvailableValue which can be rematerialized at the end of the associated BasicBlock.
Value * MaterializeAdjustedValue(LoadInst *Load) const
Emit code at the end of this block to adjust the value defined here to the specified type.
static AvailableValueInBlock get(BasicBlock *BB, Value *V, unsigned Offset=0)
AvailableValue AV
AV - The actual available value.
static AvailableValueInBlock getUndef(BasicBlock *BB)
BasicBlock * BB
BB - The basic block in question.
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV)
Represents a particular available value that we know how to materialize.
static AvailableValue getUndef()
unsigned Offset
Offset - The byte offset in Val that is interesting for the load query.
ValType Kind
Kind of the live-out value.
bool isCoercedLoadValue() const
Value * getSimpleValue() const
LoadInst * getCoercedLoadValue() const
bool isSelectValue() const
Value * Val
Val - The value that is live out of the block.
static AvailableValue getSelect(Value *Cond, Value *V1, Value *V2)
static AvailableValue get(Value *V, unsigned Offset=0)
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset=0)
bool isSimpleValue() const
bool isUndefValue() const
Value * getSelectCondition() const
static AvailableValue getLoad(LoadInst *Load, unsigned Offset=0)
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.
bool isMemIntrinValue() const
Value * V1
V1, V2 - The dominating non-clobbered values of SelectVal.
bool operator==(const Expression &Other) const
friend hash_code hash_value(const Expression &Value)
SmallVector< uint32_t, 4 > VarArgs
Expression(uint32_t Op=~2U)