90#define DEBUG_TYPE "gvn"
92STATISTIC(NumGVNInstr,
"Number of instructions deleted");
94STATISTIC(NumGVNPRE,
"Number of instructions PRE'd");
96STATISTIC(NumGVNSimpl,
"Number of instructions simplified");
97STATISTIC(NumGVNEqProp,
"Number of equalities propagated");
99STATISTIC(NumPRELoopLoad,
"Number of loop loads PRE'd");
101 "Number of loads moved to predecessor of a critical edge in PRE");
103STATISTIC(IsValueFullyAvailableInBlockNumSpeculationsMax,
104 "Number of blocks speculated as available in "
105 "IsValueFullyAvailableInBlock(), max");
107 "Number of times we we reached gvn-max-block-speculations cut-off "
108 "preventing further exploration");
124 cl::desc(
"The number of memory accesses to scan in a block in reaching "
125 "memory values analysis (default = 100)"));
129 cl::desc(
"Max number of dependences to attempt Load PRE (default = 100)"));
133 cl::desc(
"Max number of blocks scanned per load in the MemorySSA "
134 "reaching-value analysis (default = 200)"));
139 cl::desc(
"Max number of blocks we're willing to speculate on (and recurse "
140 "into) when deducing if a value is fully available or not in GVN "
145 cl::desc(
"Max number of visited instructions when trying to find "
146 "dominating value of select dependency (default = 100)"));
150 cl::desc(
"Max number of instructions to scan in each basic block in GVN "
166 if (
Opcode != Other.Opcode)
174 if ((!
Attrs.isEmpty() || !Other.Attrs.isEmpty()) &&
175 !
Attrs.intersectWith(
Ty->getContext(), Other.Attrs).has_value())
309 Res.
AV = std::move(
AV);
325 return AV.MaterializeAdjustedValue(
Load,
BB->getTerminator());
336 E.Opcode =
I->getOpcode();
341 E.VarArgs.push_back(
lookupOrAdd(GCR->getOperand(0)));
342 E.VarArgs.push_back(
lookupOrAdd(GCR->getBasePtr()));
343 E.VarArgs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
345 for (
Use &
Op :
I->operands())
348 if (
I->isCommutative()) {
353 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
354 if (
E.VarArgs[0] >
E.VarArgs[1])
356 E.Commutative =
true;
362 if (
E.VarArgs[0] >
E.VarArgs[1]) {
367 E.Commutative =
true;
369 E.VarArgs.append(IVI->idx_begin(), IVI->idx_end());
371 ArrayRef<int> ShuffleMask = SVI->getShuffleMask();
372 E.VarArgs.append(ShuffleMask.
begin(), ShuffleMask.
end());
374 E.Attrs = CB->getAttributes();
380GVNPass::Expression GVNPass::ValueTable::createCmpExpr(
382 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
383 "Not a comparison!");
386 E.VarArgs.push_back(lookupOrAdd(
LHS));
387 E.VarArgs.push_back(lookupOrAdd(
RHS));
390 if (
E.VarArgs[0] >
E.VarArgs[1]) {
394 E.Opcode = (Opcode << 8) | Predicate;
395 E.Commutative =
true;
400GVNPass::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) {
401 assert(EI &&
"Not an ExtractValueInst?");
412 E.VarArgs.push_back(lookupOrAdd(WO->
getLHS()));
413 E.VarArgs.push_back(lookupOrAdd(WO->
getRHS()));
421 E.VarArgs.push_back(lookupOrAdd(
Op));
428GVNPass::Expression GVNPass::ValueTable::createGEPExpr(GetElementPtrInst *
GEP) {
430 Type *PtrTy =
GEP->getType()->getScalarType();
431 const DataLayout &
DL =
GEP->getDataLayout();
432 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
433 SmallMapVector<Value *, APInt, 4> VariableOffsets;
435 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
439 E.Opcode =
GEP->getOpcode();
441 E.VarArgs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
442 for (
const auto &[V, Scale] : VariableOffsets) {
443 E.VarArgs.push_back(lookupOrAdd(V));
444 E.VarArgs.push_back(lookupOrAdd(ConstantInt::get(
Context, Scale)));
446 if (!ConstantOffset.isZero())
448 lookupOrAdd(ConstantInt::get(
Context, ConstantOffset)));
452 E.Opcode =
GEP->getOpcode();
453 E.Ty =
GEP->getSourceElementType();
454 for (Use &
Op :
GEP->operands())
455 E.VarArgs.push_back(lookupOrAdd(
Op));
464GVNPass::ValueTable::ValueTable() =
default;
465GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
466GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
467GVNPass::ValueTable::~ValueTable() =
default;
473 ValueNumbering.
insert(std::make_pair(V, Num));
475 NumberingPhi[Num] = PN;
485 assert(MSSA &&
"addMemoryStateToExp should not be called without MemorySSA");
486 assert(MSSA->getMemoryAccess(
I) &&
"Instruction does not access memory");
487 MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(
I);
488 Exp.VarArgs.push_back(lookupOrAdd(MA));
499 if (
C->getFunction()->isPresplitCoroutine()) {
500 ValueNumbering[
C] = NextValueNumber;
501 return NextValueNumber++;
507 if (
C->isConvergent()) {
508 ValueNumbering[
C] = NextValueNumber;
509 return NextValueNumber++;
515 if (
C->hasOperandBundles()) {
516 ValueNumbering[
C] = NextValueNumber;
517 return NextValueNumber++;
520 if (AA->doesNotAccessMemory(
C)) {
522 uint32_t
E = assignExpNewValueNum(Exp).first;
523 ValueNumbering[
C] =
E;
527 if (MD && AA->onlyReadsMemory(
C)) {
529 auto [
E, IsValNumNew] = assignExpNewValueNum(Exp);
531 ValueNumbering[
C] =
E;
535 MemDepResult LocalDep = MD->getDependency(
C);
538 ValueNumbering[
C] = NextValueNumber;
539 return NextValueNumber++;
542 if (LocalDep.
isDef()) {
547 if (!LocalDepCall || LocalDepCall->
arg_size() !=
C->arg_size()) {
548 ValueNumbering[
C] = NextValueNumber;
549 return NextValueNumber++;
552 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
553 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
554 uint32_t LocalDepCallVN = lookupOrAdd(LocalDepCall->
getArgOperand(
I));
555 if (CVN != LocalDepCallVN) {
556 ValueNumbering[
C] = NextValueNumber;
557 return NextValueNumber++;
561 uint32_t
V = lookupOrAdd(LocalDepCall);
562 ValueNumbering[
C] =
V;
568 MD->getNonLocalCallDependency(
C);
570 CallInst *CDep =
nullptr;
574 for (
const NonLocalDepEntry &
I : Deps) {
575 if (
I.getResult().isNonLocal())
580 if (!
I.getResult().isDef() || CDep !=
nullptr) {
587 if (NonLocalDepCall && DT->properlyDominates(
I.getBB(),
C->getParent())) {
588 CDep = NonLocalDepCall;
597 ValueNumbering[
C] = NextValueNumber;
598 return NextValueNumber++;
602 ValueNumbering[
C] = NextValueNumber;
603 return NextValueNumber++;
605 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
606 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
609 ValueNumbering[
C] = NextValueNumber;
610 return NextValueNumber++;
614 uint32_t
V = lookupOrAdd(CDep);
615 ValueNumbering[
C] =
V;
619 if (MSSA && IsMSSAEnabled && AA->onlyReadsMemory(
C)) {
621 addMemoryStateToExp(
C, Exp);
622 auto [
V,
_] = assignExpNewValueNum(Exp);
623 ValueNumbering[
C] =
V;
627 ValueNumbering[
C] = NextValueNumber;
628 return NextValueNumber++;
632uint32_t GVNPass::ValueTable::computeLoadStoreVN(Instruction *
I) {
633 if (!MSSA || !IsMSSAEnabled) {
634 ValueNumbering[
I] = NextValueNumber;
635 return NextValueNumber++;
639 Exp.Ty =
I->getType();
640 Exp.Opcode =
I->getOpcode();
641 for (Use &
Op :
I->operands())
642 Exp.VarArgs.push_back(lookupOrAdd(
Op));
643 addMemoryStateToExp(
I, Exp);
645 auto [
V,
_] = assignExpNewValueNum(Exp);
646 ValueNumbering[
I] =
V;
651bool GVNPass::ValueTable::exists(
Value *V)
const {
652 return ValueNumbering.contains(V);
664 auto VI = ValueNumbering.find(V);
665 if (VI != ValueNumbering.end())
670 ValueNumbering[V] = NextValueNumber;
673 return NextValueNumber++;
677 switch (
I->getOpcode()) {
678 case Instruction::Call:
680 case Instruction::FNeg:
681 case Instruction::Add:
682 case Instruction::FAdd:
683 case Instruction::Sub:
684 case Instruction::FSub:
685 case Instruction::Mul:
686 case Instruction::FMul:
687 case Instruction::UDiv:
688 case Instruction::SDiv:
689 case Instruction::FDiv:
690 case Instruction::URem:
691 case Instruction::SRem:
692 case Instruction::FRem:
693 case Instruction::Shl:
694 case Instruction::LShr:
695 case Instruction::AShr:
696 case Instruction::And:
697 case Instruction::Or:
698 case Instruction::Xor:
699 case Instruction::ICmp:
700 case Instruction::FCmp:
701 case Instruction::Trunc:
702 case Instruction::ZExt:
703 case Instruction::SExt:
704 case Instruction::FPToUI:
705 case Instruction::FPToSI:
706 case Instruction::UIToFP:
707 case Instruction::SIToFP:
708 case Instruction::FPTrunc:
709 case Instruction::FPExt:
710 case Instruction::PtrToInt:
711 case Instruction::PtrToAddr:
712 case Instruction::IntToPtr:
713 case Instruction::AddrSpaceCast:
714 case Instruction::BitCast:
715 case Instruction::Select:
716 case Instruction::Freeze:
717 case Instruction::ExtractElement:
718 case Instruction::InsertElement:
719 case Instruction::ShuffleVector:
720 case Instruction::InsertValue:
723 case Instruction::GetElementPtr:
726 case Instruction::ExtractValue:
729 case Instruction::PHI:
730 ValueNumbering[V] = NextValueNumber;
732 return NextValueNumber++;
733 case Instruction::Load:
734 case Instruction::Store:
735 return computeLoadStoreVN(
I);
737 ValueNumbering[V] = NextValueNumber;
738 return NextValueNumber++;
741 uint32_t E = assignExpNewValueNum(Exp).first;
742 ValueNumbering[V] = E;
749 auto VI = ValueNumbering.find(V);
751 assert(VI != ValueNumbering.end() &&
"Value not numbered?");
754 return (VI != ValueNumbering.end()) ? VI->second : 0;
761uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
764 Expression Exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
765 return assignExpNewValueNum(Exp).first;
773 return ExpressionNumbering.lookup(Exp);
778 ValueNumbering.clear();
779 ExpressionNumbering.clear();
780 NumberingPhi.clear();
782 PhiTranslateTable.clear();
791 uint32_t Num = ValueNumbering.lookup(V);
792 ValueNumbering.erase(V);
795 NumberingPhi.erase(Num);
797 NumberingBB.erase(Num);
802void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
803 assert(!ValueNumbering.contains(V) &&
804 "Inst still occurs in value numbering map!");
813 const auto &[It, Inserted] = NumToLeaders.try_emplace(
N, V, BB,
nullptr);
816 auto *NewSlot = TableAllocator.Allocate<LeaderListNode>();
817 new (NewSlot) LeaderListNode(V, BB, It->second.Next);
818 It->second.Next = NewSlot;
826 auto It = NumToLeaders.find(
N);
827 if (It == NumToLeaders.end())
830 LeaderListNode *Prev =
nullptr;
831 LeaderListNode *Curr = &It->second;
833 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
843 Prev->Next = Curr->Next;
844 Curr->~LeaderListNode();
845 TableAllocator.Deallocate<LeaderListNode>(Curr);
850 NumToLeaders.erase(It);
853 LeaderListNode *
Next = Curr->Next;
854 Curr->Entry.Val = std::move(
Next->Entry.Val);
855 Curr->Entry.BB =
Next->Entry.BB;
856 Curr->Next =
Next->Next;
857 Next->~LeaderListNode();
858 TableAllocator.Deallocate<LeaderListNode>(
Next);
880 return Options.AllowLoadPRESplitBackedge.value_or(
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())
2125 AvailValInBlkVect ValuesPerBlock;
2126 UnavailBlkVect UnavailableBlocks;
2127 analyzeLoadAvailability(
Load, Deps, ValuesPerBlock, UnavailableBlocks);
2131 if (ValuesPerBlock.empty())
2139 if (UnavailableBlocks.empty()) {
2145 ICF->removeUsersOf(
Load);
2146 Load->replaceAllUsesWith(V);
2154 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2155 I->setDebugLoc(
Load->getDebugLoc());
2156 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2157 MD->invalidateCachedPointerInfo(V);
2170 if (performLoopLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks) ||
2171 performLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks))
2177bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2181 if (
Cond->isZero()) {
2191 const MemoryUseOrDef *FirstNonDom =
nullptr;
2193 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2200 for (
const auto &Acc : *AL) {
2202 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2203 FirstNonDom = Current;
2210 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2212 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2213 : MSSAU->createMemoryAccessInBB(
2235 return propagateEquality(V, True, IntrinsicI);
2240 I->replaceAllUsesWith(Repl);
2247 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2258 PointerUsesQueue.
push_back(PointerOperand);
2263 while (!PointerUsesQueue.
empty()) {
2266 "Null or GlobalValue should not be inserted");
2270 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2285 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2287 MostDominatingInstruction =
I;
2291 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2297static std::optional<MemoryLocation>
2304 switch (
II->getIntrinsicID()) {
2305 case Intrinsic::masked_load:
2307 case Intrinsic::masked_store:
2310 return std::nullopt;
2317 return std::nullopt;
2321 return std::nullopt;
2327std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2328 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2329 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2330 BatchAAResults &AA, LoadInst *L) {
2333 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2337 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2339 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2347 Choice->Kind = DepKind::Clobber;
2348 Choice->Offset = AR.getOffset();
2350 Choice->Kind = DepKind::Def;
2351 Choice->Offset = -1;
2354 Choice->Inst = Candidate;
2355 Choice->Block = Candidate->getParent();
2358 std::optional<ReachingMemVal> ReachingVal;
2359 for (MemoryAccess *MA : ClobbersList) {
2361 for (User *U : MA->
users()) {
2363 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2366 if (!UseOrDef || UseOrDef->getBlock() != BB)
2375 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2389 UpdateChoice(ReachingVal, AR, MemI);
2401std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2402 MemoryAccess *ClobberMA,
const MemoryLocation &Loc,
bool IsInvariantLoad,
2403 BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2411 if (
Alloc->getParent() == BB)
2412 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2413 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2417 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2418 return std::nullopt;
2422 return L->getOrdering();
2429 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2431 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2442 return std::nullopt;
2443 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2448 return std::nullopt;
2453 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2458 "Must be the superset/partial overlap case with positive offset");
2459 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2464 return std::nullopt;
2465 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2467 if (AA.isMustAlias(IIObjLoc, Loc))
2468 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2469 return std::nullopt;
2477 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2478 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2484 return std::nullopt;
2488 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2492 return std::nullopt;
2496 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2502bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2503 MemoryAccess *ClobberMA,
2504 DependencyBlockSet &Blocks,
2505 SmallVectorImpl<BasicBlock *> &Worklist) {
2515 if (!DT->isReachableFromEntry(Pred))
2519 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2522 PHITransAddr TransAddr = Addr;
2526 auto It = Blocks.find(Pred);
2527 if (It != Blocks.end()) {
2531 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2538 Pred, DependencyBlockInfo(TransAddr,
2539 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2546 for (
auto &
P : Preds) {
2547 [[maybe_unused]]
auto It =
2548 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2560void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2562 const DependencyBlockInfo &StartInfo,
2563 const DependencyBlockSet &Blocks,
2565 MemoryAccess *MA = StartInfo.InitialClobberMA;
2566 MemoryAccess *LastMA = StartInfo.ClobberMA;
2569 while (MA != LastMA) {
2583 BB = DT->getNode(BB)->getIDom()->getBlock();
2587 auto It = Blocks.find(BB);
2588 if (It == Blocks.end())
2591 MA = It->second.InitialClobberMA;
2592 LastMA = It->second.ClobberMA;
2593 if (MA == Clobbers.
back())
2610bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2611 SmallVectorImpl<ReachingMemVal> &
Values,
2613 EarliestEscapeAnalysis EA(*DT, LI);
2614 BatchAAResults AA(AAR, &EA);
2616 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2622 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2635 if (
auto RMV = scanMemoryAccessesUsers(
2636 Loc, IsInvariantLoad, StartBlock,
2638 Values.emplace_back(*RMV);
2648 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2649 StartBlock, MSSA, AA)) {
2650 Values.emplace_back(*RMV);
2657 }
while (ClobberMA->
getBlock() == StartBlock);
2660 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2661 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2670 DependencyBlockSet Blocks;
2671 SmallVector<BasicBlock *, 16> InitialWorklist;
2672 const DataLayout &
DL =
L->getModule()->getDataLayout();
2673 if (!collectPredecessors(StartBlock,
2674 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2675 ClobberMA, Blocks, InitialWorklist))
2679 auto Worklist = InitialWorklist;
2680 while (!Worklist.
empty()) {
2685 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2688 if (!
Info.Addr.getAddr())
2696 if (
auto RMV = accessMayModifyLocation(
2698 IsInvariantLoad, BB, MSSA, AA)) {
2703 "LiveOnEntry aliases everything");
2719 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2720 Info.ForceUnknown =
true;
2723 if (BB != StartBlock &&
2724 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2725 Info.ForceUnknown =
true;
2735 Worklist = InitialWorklist;
2736 for (BasicBlock *BB : Worklist) {
2737 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2738 Info.Visited =
true;
2742 while (!Worklist.empty()) {
2743 auto *BB = Worklist.pop_back_val();
2744 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2748 if (!
Info.Addr.getAddr()) {
2749 Values.push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2754 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2757 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2769 if (
Info.ForceUnknown) {
2770 Values.push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2776 auto It = Blocks.find(Pred);
2777 if (It == Blocks.end())
2779 DependencyBlockInfo &PredInfo = It->second;
2780 if (PredInfo.Visited)
2782 PredInfo.Visited =
true;
2783 Worklist.push_back(Pred);
2792bool GVNPass::processLoad(LoadInst *L) {
2797 if (!
L->isUnordered())
2800 if (
L->getType()->isTokenLikeTy())
2803 if (
L->use_empty()) {
2808 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2811 MemDepResult Dep = MD->getDependency(L);
2815 return processNonLocalLoad(L);
2819 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2822 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2825 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2827 assert(MemVals.
size() &&
"Expected at least an unknown value");
2828 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2829 return processNonLocalLoad(L, MemVals);
2831 MemVal = MemVals[0];
2834 if (MemVal.Kind == DepKind::Other) {
2838 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2839 dbgs() <<
" has unknown dependence\n";);
2843 auto AV = analyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2850 ICF->removeUsersOf(L);
2853 MSSAU->removeMemoryAccess(L);
2866bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2869 MemDepResult Dep = MD->getDependency(
I);
2875 Value *Passthrough =
I->getOperand(2);
2879 StoreVal->
getType() !=
I->getType())
2886 ICF->removeUsersOf(
I);
2887 I->replaceAllUsesWith(OpToForward);
2895std::pair<uint32_t, bool>
2896GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2897 uint32_t &
E = ExpressionNumbering[
Exp];
2898 bool CreateNewValNum = !
E;
2899 if (CreateNewValNum) {
2900 Expressions.push_back(Exp);
2901 if (ExprIdx.size() < NextValueNumber + 1)
2902 ExprIdx.resize(NextValueNumber * 2);
2903 E = NextValueNumber;
2904 ExprIdx[NextValueNumber++] = NextExprNumber++;
2906 return {
E, CreateNewValNum};
2911bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2914 GVN.LeaderTable.getLeaders(Num),
2922 auto FindRes = PhiTranslateTable.find({Num, Pred});
2923 if (FindRes != PhiTranslateTable.end())
2924 return FindRes->second;
2925 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2926 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2937 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2938 for (
const auto &Entry : Leaders) {
2940 if (
Call &&
Call->getParent() == PhiBlock)
2944 if (
AA->doesNotAccessMemory(
Call))
2947 if (!MD || !
AA->onlyReadsMemory(
Call))
2959 if (
D.getResult().isNonFuncLocal())
2967uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2968 const BasicBlock *PhiBlock,
2972 if (PHINode *PN = NumberingPhi[Num]) {
2973 if (PN->getParent() != PhiBlock)
2975 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2976 if (PN->getIncomingBlock(
I) != Pred)
2978 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2984 if (BasicBlock *BB = NumberingBB[Num]) {
2985 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
2997 return lookupOrAdd(PredPhi->getBlock());
3003 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
3009 if (!areAllValsInBB(Num, PhiBlock, GVN))
3012 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
3016 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
3020 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
3021 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
3022 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
3024 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
3027 if (
Exp.Commutative) {
3028 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
3029 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
3031 uint32_t Opcode =
Exp.Opcode >> 8;
3032 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
3033 Exp.Opcode = (Opcode << 8) |
3039 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
3040 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
3041 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3049void GVNPass::ValueTable::eraseTranslateCacheEntry(
3052 PhiTranslateTable.erase({Num, Pred});
3061 auto Leaders = LeaderTable.getLeaders(Num);
3062 if (Leaders.empty())
3065 Value *Val =
nullptr;
3066 for (
const auto &Entry : Leaders) {
3067 if (DT->dominates(Entry.BB, BB)) {
3087 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3088 assert((!Pred || Pred ==
E.getStart()) &&
3089 "No edge between these basic blocks!");
3090 return Pred !=
nullptr;
3093void GVNPass::assignBlockRPONumber(
Function &
F) {
3094 BlockRPONumber.clear();
3095 uint32_t NextBlockNumber = 1;
3096 ReversePostOrderTraversal<Function *> RPOT(&
F);
3097 for (BasicBlock *BB : RPOT)
3098 BlockRPONumber[BB] = NextBlockNumber++;
3099 InvalidBlockRPONumbers =
false;
3107bool GVNPass::propagateEquality(
3109 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3111 SmallDenseSet<std::pair<Value *, Value *>, 4> Visited;
3115 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3122 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3126 while (!Worklist.
empty()) {
3127 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3128 LHS = Item.first;
RHS = Item.second;
3142 const DataLayout &
DL =
3151 uint32_t LVN = VN.lookupOrAdd(
LHS);
3156 uint32_t RVN = VN.lookupOrAdd(
RHS);
3163 if (!Visited.
insert({LHS, RHS}).second)
3176 for (
const BasicBlock *BB : DominatedBlocks)
3177 LeaderTable.insert(LVN,
RHS, BB);
3184 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3187 unsigned NumReplacements;
3188 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3190 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3193 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3194 CanReplacePointersCallBack);
3196 if (NumReplacements > 0) {
3198 NumGVNEqProp += NumReplacements;
3201 MD->invalidateCachedPointerInfo(
LHS);
3218 bool IsKnownFalse = !IsKnownTrue;
3234 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3239 if (
Cmp->isEquivalence(IsKnownFalse))
3240 Worklist.
push_back(std::make_pair(Op0, Op1));
3244 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3248 uint32_t NextNum = VN.getNextUnusedValueNumber();
3249 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3252 if (Num < NextNum) {
3253 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3258 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3259 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3260 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3263 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3264 if (!DT->dominates(
Entry.BB, InstBB) &&
3265 !DT->dominates(InstBB,
Entry.BB))
3271 unsigned NumReplacements;
3272 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3277 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3278 Changed |= NumReplacements > 0;
3279 NumGVNEqProp += NumReplacements;
3282 MD->invalidateCachedPointerInfo(NotCmp);
3290 for (
const BasicBlock *BB : DominatedBlocks)
3291 LeaderTable.insert(Num, NotVal, BB);
3300 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3305 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3315bool GVNPass::processInstruction(Instruction *
I) {
3320 const DataLayout &
DL =
I->getDataLayout();
3323 if (!
I->use_empty()) {
3326 ICF->removeUsersOf(
I);
3327 I->replaceAllUsesWith(V);
3335 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3336 MD->invalidateCachedPointerInfo(V);
3343 return processAssumeIntrinsic(Assume);
3346 if (processLoad(
Load))
3349 unsigned Num = VN.lookupOrAdd(
Load);
3350 LeaderTable.insert(Num,
Load,
Load->getParent());
3362 return processFoldableCondBr(BI);
3364 Value *BranchCond = BI->getCondition();
3368 if (TrueSucc == FalseSucc)
3375 BasicBlockEdge TrueE(Parent, TrueSucc);
3376 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3379 BasicBlockEdge FalseE(Parent, FalseSucc);
3380 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3387 Value *SwitchCond =
SI->getCondition();
3392 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3394 ++SwitchEdges[Succ];
3396 for (
const auto &Case :
SI->cases()) {
3399 if (SwitchEdges.
lookup(Dst) == 1) {
3400 BasicBlockEdge
E(Parent, Dst);
3401 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3409 if (
I->getType()->isVoidTy())
3412 uint32_t NextNum = VN.getNextUnusedValueNumber();
3413 unsigned Num = VN.lookupOrAdd(
I);
3418 LeaderTable.insert(Num,
I,
I->getParent());
3425 const DataLayout &
DL =
I->getDataLayout();
3426 unsigned AS = PTA->getPointerAddressSpace();
3427 if (
DL.getAddressSizeInBits(AS) ==
DL.getPointerSizeInBits(AS) &&
3428 !
DL.hasUnstableRepresentation(AS)) {
3430 VN.lookupPtrToInt(PTA->getPointerOperand(), PTA->getType());
3431 if (
Value *PTI = findLeader(
I->getParent(), PTINum)) {
3442 if (Num >= NextNum) {
3443 LeaderTable.insert(Num,
I,
I->getParent());
3449 Value *Repl = findLeader(
I->getParent(), Num);
3452 LeaderTable.insert(Num,
I,
I->getParent());
3465 MD->invalidateCachedPointerInfo(Repl);
3471bool GVNPass::runImpl(
Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3472 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3473 MemoryDependenceResults *RunMD, LoopInfo &LI,
3474 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3480 VN.setAliasAnalysis(&RunAA);
3482 ImplicitControlFlowTracking ImplicitCFT;
3491 InvalidBlockRPONumbers =
true;
3492 MemorySSAUpdater Updater(MSSA);
3493 MSSAU = MSSA ? &Updater :
nullptr;
3496 bool ShouldContinue =
true;
3498 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3510 unsigned Iteration = 0;
3511 while (ShouldContinue) {
3514 ShouldContinue = iterateOnFunction(
F);
3522 assignValNumForDeadCode();
3523 bool PREChanged =
true;
3524 while (PREChanged) {
3525 PREChanged = performPRE(
F);
3535 cleanupGlobalSets();
3546bool GVNPass::processBlock(BasicBlock *BB) {
3547 if (DeadBlocks.count(BB))
3550 bool ChangedFunction =
false;
3556 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3558 for (PHINode *PN : PHINodesToRemove) {
3559 removeInstruction(PN);
3562 ChangedFunction |= processInstruction(&Inst);
3563 return ChangedFunction;
3567bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3568 BasicBlock *Curr,
unsigned int ValNo) {
3574 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3582 if (!VN.exists(
Op)) {
3587 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3588 if (
Value *V = findLeader(Pred, TValNo)) {
3606 ICF->insertInstructionTo(Instr, Pred);
3608 unsigned Num = VN.lookupOrAdd(Instr);
3612 LeaderTable.insert(Num, Instr, Pred);
3616bool GVNPass::performScalarPRE(Instruction *CurInst) {
3642 if (CallB->isInlineAsm())
3646 uint32_t ValNo = VN.lookup(CurInst);
3654 unsigned NumWith = 0;
3655 unsigned NumWithout = 0;
3660 if (InvalidBlockRPONumbers)
3661 assignBlockRPONumber(*CurrentBlock->
getParent());
3667 if (!DT->isReachableFromEntry(
P)) {
3672 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3673 "Invalid BlockRPONumber map.");
3674 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3679 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3680 Value *PredV = findLeader(
P, TValNo);
3685 }
else if (PredV == CurInst) {
3697 if (NumWithout > 1 || NumWith == 0)
3705 if (NumWithout != 0) {
3711 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3724 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3728 PREInstr = CurInst->
clone();
3729 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3732 verifyRemoved(PREInstr);
3741 assert(PREInstr !=
nullptr || NumWithout == 0);
3747 CurInst->
getName() +
".pre-phi");
3748 Phi->insertBefore(CurrentBlock->begin());
3749 for (
auto &[V, BB] : PredMap) {
3754 Phi->addIncoming(V, BB);
3756 Phi->addIncoming(PREInstr, PREPred);
3762 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3763 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3766 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3767 MD->invalidateCachedPointerInfo(Phi);
3768 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3771 removeInstruction(CurInst);
3780 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3782 if (CurrentBlock == &
F.getEntryBlock())
3786 if (CurrentBlock->isEHPad())
3790 BE = CurrentBlock->end();
3793 Changed |= performScalarPRE(CurInst);
3797 if (splitCriticalEdges())
3805BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3810 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3813 MD->invalidateCachedPredecessors();
3814 InvalidBlockRPONumbers =
true;
3821bool GVNPass::splitCriticalEdges() {
3822 if (ToSplit.empty())
3827 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3829 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3831 }
while (!ToSplit.empty());
3834 MD->invalidateCachedPredecessors();
3835 InvalidBlockRPONumbers =
true;
3841bool GVNPass::iterateOnFunction(
Function &
F) {
3842 cleanupGlobalSets();
3849 ReversePostOrderTraversal<Function *> RPOT(&
F);
3851 for (BasicBlock *BB : RPOT)
3857void GVNPass::cleanupGlobalSets() {
3859 LeaderTable.clear();
3860 BlockRPONumber.clear();
3862 InvalidBlockRPONumbers =
true;
3865void GVNPass::removeInstruction(Instruction *
I) {
3867 if (MD) MD->removeInstruction(
I);
3869 MSSAU->removeMemoryAccess(
I);
3873 ICF->removeInstruction(
I);
3874 I->eraseFromParent();
3880void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3881 VN.verifyRemoved(Inst);
3888void GVNPass::addDeadBlock(BasicBlock *BB) {
3890 SmallSetVector<BasicBlock *, 4>
DF;
3893 while (!NewDead.
empty()) {
3895 if (DeadBlocks.count(
D))
3899 SmallVector<BasicBlock *, 8> Dom;
3900 DT->getDescendants(
D, Dom);
3901 DeadBlocks.insert_range(Dom);
3904 for (BasicBlock *
B : Dom) {
3906 if (DeadBlocks.count(S))
3909 bool AllPredDead =
true;
3911 if (!DeadBlocks.count(
P)) {
3912 AllPredDead =
false;
3932 for (BasicBlock *
B :
DF) {
3933 if (DeadBlocks.count(
B))
3939 for (BasicBlock *
P : Preds) {
3940 if (!DeadBlocks.count(
P))
3945 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3946 DeadBlocks.insert(
P = S);
3952 if (!DeadBlocks.count(
P))
3954 for (PHINode &Phi :
B->phis()) {
3957 MD->invalidateCachedPointerInfo(&Phi);
3976bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
3987 if (DeadBlocks.count(DeadRoot))
3991 DeadRoot = splitCriticalEdges(BI->
getParent(), DeadRoot);
3993 addDeadBlock(DeadRoot);
4001void GVNPass::assignValNumForDeadCode() {
4002 for (BasicBlock *BB : DeadBlocks) {
4003 for (Instruction &Inst : *BB) {
4004 unsigned ValNum = VN.lookupOrAdd(&Inst);
4005 LeaderTable.insert(ValNum, &Inst, BB);
4016 bool ScalarPRE =
true)
4018 .setMemDep(MemDepAnalysis)
4019 .setMemorySSA(MemSSAAnalysis)
4020 .setScalarPRE(ScalarPRE)) {
4029 if (Impl.isMemorySSAEnabled() && !MSSAWP)
4032 return Impl.runImpl(
4037 Impl.isMemDepEnabled()
4042 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
4050 if (Impl.isMemDepEnabled())
4059 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.
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 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)