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,
bool IsInvariantLoad,
2406 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;
2456 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2461 "Must be the superset/partial overlap case with positive offset");
2462 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2467 return std::nullopt;
2468 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2470 if (AA.isMustAlias(IIObjLoc, Loc))
2471 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2472 return std::nullopt;
2480 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2481 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2487 return std::nullopt;
2491 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2495 return std::nullopt;
2499 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2505bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2506 MemoryAccess *ClobberMA,
2507 DependencyBlockSet &Blocks,
2508 SmallVectorImpl<BasicBlock *> &Worklist) {
2518 if (!DT->isReachableFromEntry(Pred))
2522 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2525 PHITransAddr TransAddr = Addr;
2529 auto It = Blocks.find(Pred);
2530 if (It != Blocks.end()) {
2534 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2541 Pred, DependencyBlockInfo(TransAddr,
2542 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2549 for (
auto &
P : Preds) {
2550 [[maybe_unused]]
auto It =
2551 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2563void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2565 const DependencyBlockInfo &StartInfo,
2566 const DependencyBlockSet &Blocks,
2568 MemoryAccess *MA = StartInfo.InitialClobberMA;
2569 MemoryAccess *LastMA = StartInfo.ClobberMA;
2572 while (MA != LastMA) {
2586 BB = DT->getNode(BB)->getIDom()->getBlock();
2590 auto It = Blocks.find(BB);
2591 if (It == Blocks.end())
2594 MA = It->second.InitialClobberMA;
2595 LastMA = It->second.ClobberMA;
2596 if (MA == Clobbers.
back())
2613bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2614 SmallVectorImpl<ReachingMemVal> &
Values,
2616 EarliestEscapeAnalysis EA(*DT, LI);
2617 BatchAAResults AA(AAR, &EA);
2619 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2625 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2638 if (
auto RMV = scanMemoryAccessesUsers(
2639 Loc, IsInvariantLoad, StartBlock,
2641 Values.emplace_back(*RMV);
2651 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2652 StartBlock, MSSA, AA)) {
2653 Values.emplace_back(*RMV);
2660 }
while (ClobberMA->
getBlock() == StartBlock);
2663 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2664 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2673 DependencyBlockSet Blocks;
2674 SmallVector<BasicBlock *, 16> InitialWorklist;
2675 const DataLayout &
DL =
L->getModule()->getDataLayout();
2676 if (!collectPredecessors(StartBlock,
2677 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2678 ClobberMA, Blocks, InitialWorklist))
2682 auto Worklist = InitialWorklist;
2683 while (!Worklist.
empty()) {
2688 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2691 if (!
Info.Addr.getAddr())
2699 if (
auto RMV = accessMayModifyLocation(
2701 IsInvariantLoad, BB, MSSA, AA)) {
2706 "LiveOnEntry aliases everything");
2722 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2723 Info.ForceUnknown =
true;
2726 if (BB != StartBlock &&
2727 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2728 Info.ForceUnknown =
true;
2738 Worklist = InitialWorklist;
2739 for (BasicBlock *BB : Worklist) {
2740 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2741 Info.Visited =
true;
2745 while (!Worklist.empty()) {
2746 auto *BB = Worklist.pop_back_val();
2747 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2751 if (!
Info.Addr.getAddr()) {
2752 Values.push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2757 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2760 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2772 if (
Info.ForceUnknown) {
2773 Values.push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2779 auto It = Blocks.find(Pred);
2780 if (It == Blocks.end())
2782 DependencyBlockInfo &PredInfo = It->second;
2783 if (PredInfo.Visited)
2785 PredInfo.Visited =
true;
2786 Worklist.push_back(Pred);
2795bool GVNPass::processLoad(LoadInst *L) {
2800 if (!
L->isUnordered())
2803 if (
L->getType()->isTokenLikeTy())
2806 if (
L->use_empty()) {
2811 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2814 MemDepResult Dep = MD->getDependency(L);
2818 return processNonLocalLoad(L);
2822 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2825 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2828 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2830 assert(MemVals.
size() &&
"Expected at least an unknown value");
2831 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2832 return processNonLocalLoad(L, MemVals);
2834 MemVal = MemVals[0];
2837 if (MemVal.Kind == DepKind::Other) {
2841 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2842 dbgs() <<
" has unknown dependence\n";);
2846 auto AV = analyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2853 ICF->removeUsersOf(L);
2856 MSSAU->removeMemoryAccess(L);
2869bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2872 MemDepResult Dep = MD->getDependency(
I);
2878 Value *Passthrough =
I->getOperand(2);
2882 StoreVal->
getType() !=
I->getType())
2889 ICF->removeUsersOf(
I);
2890 I->replaceAllUsesWith(OpToForward);
2898std::pair<uint32_t, bool>
2899GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2900 uint32_t &
E = ExpressionNumbering[
Exp];
2901 bool CreateNewValNum = !
E;
2902 if (CreateNewValNum) {
2903 Expressions.push_back(Exp);
2904 if (ExprIdx.size() < NextValueNumber + 1)
2905 ExprIdx.resize(NextValueNumber * 2);
2906 E = NextValueNumber;
2907 ExprIdx[NextValueNumber++] = NextExprNumber++;
2909 return {
E, CreateNewValNum};
2914bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2917 GVN.LeaderTable.getLeaders(Num),
2925 auto FindRes = PhiTranslateTable.find({Num, Pred});
2926 if (FindRes != PhiTranslateTable.end())
2927 return FindRes->second;
2928 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2929 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2940 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2941 for (
const auto &Entry : Leaders) {
2943 if (
Call &&
Call->getParent() == PhiBlock)
2947 if (
AA->doesNotAccessMemory(
Call))
2950 if (!MD || !
AA->onlyReadsMemory(
Call))
2962 if (
D.getResult().isNonFuncLocal())
2970uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2971 const BasicBlock *PhiBlock,
2975 if (PHINode *PN = NumberingPhi[Num]) {
2976 if (PN->getParent() != PhiBlock)
2978 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2979 if (PN->getIncomingBlock(
I) != Pred)
2981 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2987 if (BasicBlock *BB = NumberingBB[Num]) {
2988 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
3000 return lookupOrAdd(PredPhi->getBlock());
3006 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
3012 if (!areAllValsInBB(Num, PhiBlock, GVN))
3015 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
3019 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
3023 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
3024 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
3025 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
3027 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
3030 if (
Exp.Commutative) {
3031 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
3032 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
3034 uint32_t Opcode =
Exp.Opcode >> 8;
3035 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
3036 Exp.Opcode = (Opcode << 8) |
3042 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
3043 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
3044 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3052void GVNPass::ValueTable::eraseTranslateCacheEntry(
3055 PhiTranslateTable.erase({Num, Pred});
3064 auto Leaders = LeaderTable.getLeaders(Num);
3065 if (Leaders.empty())
3068 Value *Val =
nullptr;
3069 for (
const auto &Entry : Leaders) {
3070 if (DT->dominates(Entry.BB, BB)) {
3090 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3091 assert((!Pred || Pred ==
E.getStart()) &&
3092 "No edge between these basic blocks!");
3093 return Pred !=
nullptr;
3096void GVNPass::assignBlockRPONumber(
Function &
F) {
3097 BlockRPONumber.clear();
3098 uint32_t NextBlockNumber = 1;
3099 ReversePostOrderTraversal<Function *> RPOT(&
F);
3100 for (BasicBlock *BB : RPOT)
3101 BlockRPONumber[BB] = NextBlockNumber++;
3102 InvalidBlockRPONumbers =
false;
3110bool GVNPass::propagateEquality(
3112 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3114 SmallDenseSet<std::pair<Value *, Value *>, 4> Visited;
3118 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3125 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3129 while (!Worklist.
empty()) {
3130 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3131 LHS = Item.first;
RHS = Item.second;
3145 const DataLayout &
DL =
3154 uint32_t LVN = VN.lookupOrAdd(
LHS);
3159 uint32_t RVN = VN.lookupOrAdd(
RHS);
3166 if (!Visited.
insert({LHS, RHS}).second)
3179 for (
const BasicBlock *BB : DominatedBlocks)
3180 LeaderTable.insert(LVN,
RHS, BB);
3187 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3190 unsigned NumReplacements;
3191 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3193 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3196 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3197 CanReplacePointersCallBack);
3199 if (NumReplacements > 0) {
3201 NumGVNEqProp += NumReplacements;
3204 MD->invalidateCachedPointerInfo(
LHS);
3221 bool IsKnownFalse = !IsKnownTrue;
3237 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3242 if (
Cmp->isEquivalence(IsKnownFalse))
3243 Worklist.
push_back(std::make_pair(Op0, Op1));
3247 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3251 uint32_t NextNum = VN.getNextUnusedValueNumber();
3252 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3255 if (Num < NextNum) {
3256 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3261 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3262 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3263 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3266 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3267 if (!DT->dominates(
Entry.BB, InstBB) &&
3268 !DT->dominates(InstBB,
Entry.BB))
3274 unsigned NumReplacements;
3275 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3280 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3281 Changed |= NumReplacements > 0;
3282 NumGVNEqProp += NumReplacements;
3285 MD->invalidateCachedPointerInfo(NotCmp);
3293 for (
const BasicBlock *BB : DominatedBlocks)
3294 LeaderTable.insert(Num, NotVal, BB);
3303 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3308 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3318bool GVNPass::processInstruction(Instruction *
I) {
3323 const DataLayout &
DL =
I->getDataLayout();
3326 if (!
I->use_empty()) {
3329 ICF->removeUsersOf(
I);
3330 I->replaceAllUsesWith(V);
3338 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3339 MD->invalidateCachedPointerInfo(V);
3346 return processAssumeIntrinsic(Assume);
3349 if (processLoad(
Load))
3352 unsigned Num = VN.lookupOrAdd(
Load);
3353 LeaderTable.insert(Num,
Load,
Load->getParent());
3365 return processFoldableCondBr(BI);
3367 Value *BranchCond = BI->getCondition();
3371 if (TrueSucc == FalseSucc)
3378 BasicBlockEdge TrueE(Parent, TrueSucc);
3379 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3382 BasicBlockEdge FalseE(Parent, FalseSucc);
3383 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3390 Value *SwitchCond =
SI->getCondition();
3395 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3397 ++SwitchEdges[Succ];
3399 for (
const auto &Case :
SI->cases()) {
3402 if (SwitchEdges.
lookup(Dst) == 1) {
3403 BasicBlockEdge
E(Parent, Dst);
3404 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3412 if (
I->getType()->isVoidTy())
3415 uint32_t NextNum = VN.getNextUnusedValueNumber();
3416 unsigned Num = VN.lookupOrAdd(
I);
3421 LeaderTable.insert(Num,
I,
I->getParent());
3428 const DataLayout &
DL =
I->getDataLayout();
3429 unsigned AS = PTA->getPointerAddressSpace();
3430 if (
DL.getAddressSizeInBits(AS) ==
DL.getPointerSizeInBits(AS) &&
3431 !
DL.hasUnstableRepresentation(AS)) {
3433 VN.lookupPtrToInt(PTA->getPointerOperand(), PTA->getType());
3434 if (
Value *PTI = findLeader(
I->getParent(), PTINum)) {
3445 if (Num >= NextNum) {
3446 LeaderTable.insert(Num,
I,
I->getParent());
3452 Value *Repl = findLeader(
I->getParent(), Num);
3455 LeaderTable.insert(Num,
I,
I->getParent());
3468 MD->invalidateCachedPointerInfo(Repl);
3474bool GVNPass::runImpl(
Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3475 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3476 MemoryDependenceResults *RunMD, LoopInfo &LI,
3477 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3485 "mutually exclusive",
3492 VN.setAliasAnalysis(&RunAA);
3494 ImplicitControlFlowTracking ImplicitCFT;
3503 InvalidBlockRPONumbers =
true;
3504 MemorySSAUpdater Updater(MSSA);
3505 MSSAU = MSSA ? &Updater :
nullptr;
3508 bool ShouldContinue =
true;
3510 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3522 unsigned Iteration = 0;
3523 while (ShouldContinue) {
3526 ShouldContinue = iterateOnFunction(
F);
3534 assignValNumForDeadCode();
3535 bool PREChanged =
true;
3536 while (PREChanged) {
3537 PREChanged = performPRE(
F);
3547 cleanupGlobalSets();
3558bool GVNPass::processBlock(BasicBlock *BB) {
3559 if (DeadBlocks.count(BB))
3562 bool ChangedFunction =
false;
3568 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3570 for (PHINode *PN : PHINodesToRemove) {
3571 removeInstruction(PN);
3574 ChangedFunction |= processInstruction(&Inst);
3575 return ChangedFunction;
3579bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3580 BasicBlock *Curr,
unsigned int ValNo) {
3586 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3594 if (!VN.exists(
Op)) {
3599 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3600 if (
Value *V = findLeader(Pred, TValNo)) {
3618 ICF->insertInstructionTo(Instr, Pred);
3620 unsigned Num = VN.lookupOrAdd(Instr);
3624 LeaderTable.insert(Num, Instr, Pred);
3628bool GVNPass::performScalarPRE(Instruction *CurInst) {
3654 if (CallB->isInlineAsm())
3658 uint32_t ValNo = VN.lookup(CurInst);
3666 unsigned NumWith = 0;
3667 unsigned NumWithout = 0;
3672 if (InvalidBlockRPONumbers)
3673 assignBlockRPONumber(*CurrentBlock->
getParent());
3679 if (!DT->isReachableFromEntry(
P)) {
3684 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3685 "Invalid BlockRPONumber map.");
3686 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3691 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3692 Value *PredV = findLeader(
P, TValNo);
3697 }
else if (PredV == CurInst) {
3709 if (NumWithout > 1 || NumWith == 0)
3717 if (NumWithout != 0) {
3723 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3736 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3740 PREInstr = CurInst->
clone();
3741 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3744 verifyRemoved(PREInstr);
3753 assert(PREInstr !=
nullptr || NumWithout == 0);
3759 CurInst->
getName() +
".pre-phi");
3760 Phi->insertBefore(CurrentBlock->begin());
3761 for (
auto &[V, BB] : PredMap) {
3766 Phi->addIncoming(V, BB);
3768 Phi->addIncoming(PREInstr, PREPred);
3774 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3775 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3778 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3779 MD->invalidateCachedPointerInfo(Phi);
3780 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3783 removeInstruction(CurInst);
3792 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3794 if (CurrentBlock == &
F.getEntryBlock())
3798 if (CurrentBlock->isEHPad())
3802 BE = CurrentBlock->end();
3805 Changed |= performScalarPRE(CurInst);
3809 if (splitCriticalEdges())
3817BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3822 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3825 MD->invalidateCachedPredecessors();
3826 InvalidBlockRPONumbers =
true;
3833bool GVNPass::splitCriticalEdges() {
3834 if (ToSplit.empty())
3839 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3841 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3843 }
while (!ToSplit.empty());
3846 MD->invalidateCachedPredecessors();
3847 InvalidBlockRPONumbers =
true;
3853bool GVNPass::iterateOnFunction(
Function &
F) {
3854 cleanupGlobalSets();
3861 ReversePostOrderTraversal<Function *> RPOT(&
F);
3863 for (BasicBlock *BB : RPOT)
3869void GVNPass::cleanupGlobalSets() {
3871 LeaderTable.clear();
3872 BlockRPONumber.clear();
3874 InvalidBlockRPONumbers =
true;
3877void GVNPass::removeInstruction(Instruction *
I) {
3879 if (MD) MD->removeInstruction(
I);
3881 MSSAU->removeMemoryAccess(
I);
3885 ICF->removeInstruction(
I);
3886 I->eraseFromParent();
3892void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3893 VN.verifyRemoved(Inst);
3900void GVNPass::addDeadBlock(BasicBlock *BB) {
3902 SmallSetVector<BasicBlock *, 4>
DF;
3905 while (!NewDead.
empty()) {
3907 if (DeadBlocks.count(
D))
3911 SmallVector<BasicBlock *, 8> Dom;
3912 DT->getDescendants(
D, Dom);
3913 DeadBlocks.insert_range(Dom);
3916 for (BasicBlock *
B : Dom) {
3918 if (DeadBlocks.count(S))
3921 bool AllPredDead =
true;
3923 if (!DeadBlocks.count(
P)) {
3924 AllPredDead =
false;
3944 for (BasicBlock *
B :
DF) {
3945 if (DeadBlocks.count(
B))
3951 for (BasicBlock *
P : Preds) {
3952 if (!DeadBlocks.count(
P))
3957 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3958 DeadBlocks.insert(
P = S);
3964 if (!DeadBlocks.count(
P))
3966 for (PHINode &Phi :
B->phis()) {
3969 MD->invalidateCachedPointerInfo(&Phi);
3988bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
3999 if (DeadBlocks.count(DeadRoot))
4003 DeadRoot = splitCriticalEdges(BI->
getParent(), DeadRoot);
4005 addDeadBlock(DeadRoot);
4013void GVNPass::assignValNumForDeadCode() {
4014 for (BasicBlock *BB : DeadBlocks) {
4015 for (Instruction &Inst : *BB) {
4016 unsigned ValNum = VN.lookupOrAdd(&Inst);
4017 LeaderTable.insert(ValNum, &Inst, BB);
4028 bool ScalarPRE =
true)
4030 .setMemDep(MemDepAnalysis)
4031 .setMemorySSA(MemSSAAnalysis)
4032 .setScalarPRE(ScalarPRE)) {
4041 if (Impl.isMemorySSAEnabled() && !MSSAWP)
4044 return Impl.runImpl(
4049 Impl.isMemDepEnabled()
4054 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
4062 if (Impl.isMemDepEnabled())
4071 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
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...
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 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.
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)