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)"));
134 cl::desc(
"Max number of blocks we're willing to speculate on (and recurse "
135 "into) when deducing if a value is fully available or not in GVN "
140 cl::desc(
"Max number of visited instructions when trying to find "
141 "dominating value of select dependency (default = 100)"));
145 cl::desc(
"Max number of instructions to scan in each basic block in GVN "
161 if (
Opcode != Other.Opcode)
169 if ((!
Attrs.isEmpty() || !Other.Attrs.isEmpty()) &&
170 !
Attrs.intersectWith(
Ty->getContext(), Other.Attrs).has_value())
304 Res.
AV = std::move(
AV);
320 return AV.MaterializeAdjustedValue(
Load,
BB->getTerminator());
331 E.Opcode =
I->getOpcode();
336 E.VarArgs.push_back(
lookupOrAdd(GCR->getOperand(0)));
337 E.VarArgs.push_back(
lookupOrAdd(GCR->getBasePtr()));
338 E.VarArgs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
340 for (
Use &
Op :
I->operands())
343 if (
I->isCommutative()) {
348 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
349 if (
E.VarArgs[0] >
E.VarArgs[1])
351 E.Commutative =
true;
357 if (
E.VarArgs[0] >
E.VarArgs[1]) {
362 E.Commutative =
true;
364 E.VarArgs.append(IVI->idx_begin(), IVI->idx_end());
366 ArrayRef<int> ShuffleMask = SVI->getShuffleMask();
367 E.VarArgs.append(ShuffleMask.
begin(), ShuffleMask.
end());
369 E.Attrs = CB->getAttributes();
375GVNPass::Expression GVNPass::ValueTable::createCmpExpr(
377 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
378 "Not a comparison!");
381 E.VarArgs.push_back(lookupOrAdd(
LHS));
382 E.VarArgs.push_back(lookupOrAdd(
RHS));
385 if (
E.VarArgs[0] >
E.VarArgs[1]) {
389 E.Opcode = (Opcode << 8) | Predicate;
390 E.Commutative =
true;
395GVNPass::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) {
396 assert(EI &&
"Not an ExtractValueInst?");
407 E.VarArgs.push_back(lookupOrAdd(WO->
getLHS()));
408 E.VarArgs.push_back(lookupOrAdd(WO->
getRHS()));
416 E.VarArgs.push_back(lookupOrAdd(
Op));
423GVNPass::Expression GVNPass::ValueTable::createGEPExpr(GetElementPtrInst *
GEP) {
425 Type *PtrTy =
GEP->getType()->getScalarType();
426 const DataLayout &
DL =
GEP->getDataLayout();
427 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
428 SmallMapVector<Value *, APInt, 4> VariableOffsets;
430 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
434 E.Opcode =
GEP->getOpcode();
436 E.VarArgs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
437 for (
const auto &[V, Scale] : VariableOffsets) {
438 E.VarArgs.push_back(lookupOrAdd(V));
439 E.VarArgs.push_back(lookupOrAdd(ConstantInt::get(
Context, Scale)));
441 if (!ConstantOffset.isZero())
443 lookupOrAdd(ConstantInt::get(
Context, ConstantOffset)));
447 E.Opcode =
GEP->getOpcode();
448 E.Ty =
GEP->getSourceElementType();
449 for (Use &
Op :
GEP->operands())
450 E.VarArgs.push_back(lookupOrAdd(
Op));
459GVNPass::ValueTable::ValueTable() =
default;
460GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
461GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
462GVNPass::ValueTable::~ValueTable() =
default;
468 ValueNumbering.
insert(std::make_pair(V, Num));
470 NumberingPhi[Num] = PN;
480 assert(MSSA &&
"addMemoryStateToExp should not be called without MemorySSA");
481 assert(MSSA->getMemoryAccess(
I) &&
"Instruction does not access memory");
482 MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(
I);
483 Exp.VarArgs.push_back(lookupOrAdd(MA));
494 if (
C->getFunction()->isPresplitCoroutine()) {
495 ValueNumbering[
C] = NextValueNumber;
496 return NextValueNumber++;
502 if (
C->isConvergent()) {
503 ValueNumbering[
C] = NextValueNumber;
504 return NextValueNumber++;
507 if (AA->doesNotAccessMemory(
C)) {
509 uint32_t
E = assignExpNewValueNum(Exp).first;
510 ValueNumbering[
C] =
E;
514 if (MD && AA->onlyReadsMemory(
C)) {
516 auto [
E, IsValNumNew] = assignExpNewValueNum(Exp);
518 ValueNumbering[
C] =
E;
522 MemDepResult LocalDep = MD->getDependency(
C);
525 ValueNumbering[
C] = NextValueNumber;
526 return NextValueNumber++;
529 if (LocalDep.
isDef()) {
534 if (!LocalDepCall || LocalDepCall->
arg_size() !=
C->arg_size()) {
535 ValueNumbering[
C] = NextValueNumber;
536 return NextValueNumber++;
539 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
540 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
541 uint32_t LocalDepCallVN = lookupOrAdd(LocalDepCall->
getArgOperand(
I));
542 if (CVN != LocalDepCallVN) {
543 ValueNumbering[
C] = NextValueNumber;
544 return NextValueNumber++;
548 uint32_t
V = lookupOrAdd(LocalDepCall);
549 ValueNumbering[
C] =
V;
555 MD->getNonLocalCallDependency(
C);
557 CallInst *CDep =
nullptr;
561 for (
const NonLocalDepEntry &
I : Deps) {
562 if (
I.getResult().isNonLocal())
567 if (!
I.getResult().isDef() || CDep !=
nullptr) {
574 if (NonLocalDepCall && DT->properlyDominates(
I.getBB(),
C->getParent())) {
575 CDep = NonLocalDepCall;
584 ValueNumbering[
C] = NextValueNumber;
585 return NextValueNumber++;
589 ValueNumbering[
C] = NextValueNumber;
590 return NextValueNumber++;
592 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
593 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
596 ValueNumbering[
C] = NextValueNumber;
597 return NextValueNumber++;
601 uint32_t
V = lookupOrAdd(CDep);
602 ValueNumbering[
C] =
V;
606 if (MSSA && IsMSSAEnabled && AA->onlyReadsMemory(
C)) {
608 addMemoryStateToExp(
C, Exp);
609 auto [
V,
_] = assignExpNewValueNum(Exp);
610 ValueNumbering[
C] =
V;
614 ValueNumbering[
C] = NextValueNumber;
615 return NextValueNumber++;
619uint32_t GVNPass::ValueTable::computeLoadStoreVN(Instruction *
I) {
620 if (!MSSA || !IsMSSAEnabled) {
621 ValueNumbering[
I] = NextValueNumber;
622 return NextValueNumber++;
626 Exp.Ty =
I->getType();
627 Exp.Opcode =
I->getOpcode();
628 for (Use &
Op :
I->operands())
629 Exp.VarArgs.push_back(lookupOrAdd(
Op));
630 addMemoryStateToExp(
I, Exp);
632 auto [
V,
_] = assignExpNewValueNum(Exp);
633 ValueNumbering[
I] =
V;
638bool GVNPass::ValueTable::exists(
Value *V)
const {
639 return ValueNumbering.contains(V);
651 auto VI = ValueNumbering.find(V);
652 if (VI != ValueNumbering.end())
657 ValueNumbering[V] = NextValueNumber;
660 return NextValueNumber++;
664 switch (
I->getOpcode()) {
665 case Instruction::Call:
667 case Instruction::FNeg:
668 case Instruction::Add:
669 case Instruction::FAdd:
670 case Instruction::Sub:
671 case Instruction::FSub:
672 case Instruction::Mul:
673 case Instruction::FMul:
674 case Instruction::UDiv:
675 case Instruction::SDiv:
676 case Instruction::FDiv:
677 case Instruction::URem:
678 case Instruction::SRem:
679 case Instruction::FRem:
680 case Instruction::Shl:
681 case Instruction::LShr:
682 case Instruction::AShr:
683 case Instruction::And:
684 case Instruction::Or:
685 case Instruction::Xor:
686 case Instruction::ICmp:
687 case Instruction::FCmp:
688 case Instruction::Trunc:
689 case Instruction::ZExt:
690 case Instruction::SExt:
691 case Instruction::FPToUI:
692 case Instruction::FPToSI:
693 case Instruction::UIToFP:
694 case Instruction::SIToFP:
695 case Instruction::FPTrunc:
696 case Instruction::FPExt:
697 case Instruction::PtrToInt:
698 case Instruction::PtrToAddr:
699 case Instruction::IntToPtr:
700 case Instruction::AddrSpaceCast:
701 case Instruction::BitCast:
702 case Instruction::Select:
703 case Instruction::Freeze:
704 case Instruction::ExtractElement:
705 case Instruction::InsertElement:
706 case Instruction::ShuffleVector:
707 case Instruction::InsertValue:
710 case Instruction::GetElementPtr:
713 case Instruction::ExtractValue:
716 case Instruction::PHI:
717 ValueNumbering[V] = NextValueNumber;
719 return NextValueNumber++;
720 case Instruction::Load:
721 case Instruction::Store:
722 return computeLoadStoreVN(
I);
724 ValueNumbering[V] = NextValueNumber;
725 return NextValueNumber++;
728 uint32_t E = assignExpNewValueNum(Exp).first;
729 ValueNumbering[V] = E;
736 auto VI = ValueNumbering.find(V);
738 assert(VI != ValueNumbering.end() &&
"Value not numbered?");
741 return (VI != ValueNumbering.end()) ? VI->second : 0;
748uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
751 Expression Exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
752 return assignExpNewValueNum(Exp).first;
760 return ExpressionNumbering.lookup(Exp);
765 ValueNumbering.clear();
766 ExpressionNumbering.clear();
767 NumberingPhi.clear();
769 PhiTranslateTable.clear();
778 uint32_t Num = ValueNumbering.lookup(V);
779 ValueNumbering.erase(V);
782 NumberingPhi.erase(Num);
784 NumberingBB.erase(Num);
789void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
790 assert(!ValueNumbering.contains(V) &&
791 "Inst still occurs in value numbering map!");
800 const auto &[It, Inserted] = NumToLeaders.try_emplace(
N, V, BB,
nullptr);
803 auto *NewSlot = TableAllocator.Allocate<LeaderListNode>();
804 new (NewSlot) LeaderListNode(V, BB, It->second.Next);
805 It->second.Next = NewSlot;
813 auto It = NumToLeaders.find(
N);
814 if (It == NumToLeaders.end())
817 LeaderListNode *Prev =
nullptr;
818 LeaderListNode *Curr = &It->second;
820 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
830 Prev->Next = Curr->Next;
831 Curr->~LeaderListNode();
832 TableAllocator.Deallocate<LeaderListNode>(Curr);
837 NumToLeaders.erase(It);
840 LeaderListNode *
Next = Curr->Next;
841 Curr->Entry.Val = std::move(
Next->Entry.Val);
842 Curr->Entry.BB =
Next->Entry.BB;
843 Curr->Next =
Next->Next;
844 Next->~LeaderListNode();
845 TableAllocator.Deallocate<LeaderListNode>(
Next);
867 return Options.AllowLoadPRESplitBackedge.value_or(
894 "On-demand computation of MemSSA implies that MemDep is disabled!");
898 bool Changed = runImpl(
F, AC, DT, TLI, AA, MemDep, LI, &ORE,
899 MSSA ? &MSSA->getMSSA() :
nullptr);
914 OS, MapClassName2PassName);
917 if (Options.AllowScalarPRE != std::nullopt)
918 OS << (*Options.AllowScalarPRE ?
"" :
"no-") <<
"scalar-pre;";
919 if (Options.AllowLoadPRE != std::nullopt)
920 OS << (*Options.AllowLoadPRE ?
"" :
"no-") <<
"load-pre;";
921 if (Options.AllowLoadPRESplitBackedge != std::nullopt)
922 OS << (*Options.AllowLoadPRESplitBackedge ?
"" :
"no-")
923 <<
"split-backedge-load-pre;";
924 if (Options.AllowMemDep != std::nullopt)
925 OS << (*Options.AllowMemDep ?
"" :
"no-") <<
"memdep;";
926 if (Options.AllowMemorySSA != std::nullopt)
927 OS << (*Options.AllowMemorySSA ?
"" :
"no-") <<
"memoryssa";
934 removeInstruction(
I);
961 std::optional<BasicBlock *> UnavailableBB;
965 unsigned NumNewNewSpeculativelyAvailableBBs = 0;
973 while (!Worklist.
empty()) {
977 std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator,
bool>
IV =
985 UnavailableBB = CurrBB;
996 ++NumNewNewSpeculativelyAvailableBBs;
1002 MaxBBSpeculationCutoffReachedTimes += (int)OutOfBudget;
1004 UnavailableBB = CurrBB;
1010 NewSpeculativelyAvailableBBs.
insert(CurrBB);
1016#if LLVM_ENABLE_STATS
1017 IsValueFullyAvailableInBlockNumSpeculationsMax.updateMax(
1018 NumNewNewSpeculativelyAvailableBBs);
1023 auto MarkAsFixpointAndEnqueueSuccessors =
1025 auto It = FullyAvailableBlocks.
find(BB);
1026 if (It == FullyAvailableBlocks.
end())
1033 State = FixpointState;
1036 "Found a speculatively available successor leftover?");
1044 if (UnavailableBB) {
1051 while (!Worklist.
empty())
1052 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1060 while (!Worklist.
empty())
1061 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1065 "Must have fixed all the new speculatively available blocks.");
1068 return !UnavailableBB;
1077 if (V.AV.Val == OldValue)
1078 V.AV.Val = NewValue;
1079 if (V.AV.isSelectValue()) {
1080 if (V.AV.V1 == OldValue)
1082 if (V.AV.V2 == OldValue)
1097 if (ValuesPerBlock.
size() == 1 &&
1099 Load->getParent())) {
1100 assert(!ValuesPerBlock[0].AV.isUndefValue() &&
1101 "Dead BB dominate this block");
1102 return ValuesPerBlock[0].MaterializeAdjustedValue(
Load);
1113 if (AV.AV.isUndefValue())
1123 if (BB ==
Load->getParent() &&
1124 ((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() ==
Load) ||
1125 (AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() ==
Load)))
1142 if (Res->
getType() != LoadTy) {
1157 Load->getFunction());
1168 if (!CoercedLoad->
hasMetadata(LLVMContext::MD_noundef))
1170 {LLVMContext::MD_dereferenceable,
1171 LLVMContext::MD_dereferenceable_or_null,
1172 LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group,
1173 LLVMContext::MD_alias_scope, LLVMContext::MD_noalias});
1189 assert(
V1 &&
V2 &&
"both value operands of the select must be present");
1197 assert(Res &&
"failed to materialize?");
1203 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1220 Value *PtrOp =
Load->getPointerOperand();
1226 for (
auto *U : PtrOp->
users()) {
1247 for (
auto *U : PtrOp->
users()) {
1250 if (
I->getFunction() ==
Load->getFunction() &&
1258 OtherAccess =
nullptr;
1277 using namespace ore;
1280 R <<
"load of type " << NV(
"Type",
Load->getType()) <<
" not eliminated"
1285 R <<
" in favor of " << NV(
"OtherAccess", OtherAccess);
1287 R <<
" because it is clobbered by " << NV(
"ClobberedBy", DepInst);
1301 for (
auto *Inst = BB == FromBB ? From : BB->
getTerminator();
1309 if (
SI->isSimple() &&
SI->getPointerOperand() ==
Loc.Ptr &&
1310 SI->getValueOperand()->getType() == LoadTy)
1311 return SI->getValueOperand();
1315 if (LI->getPointerOperand() ==
Loc.Ptr && LI->getType() == LoadTy)
1321std::optional<AvailableValue>
1323 Value *FalseAddr, Instruction *From) {
1325 "Invalid address type of true side of select dependency");
1327 "Invalid address type of false side of select dependency");
1335 return std::nullopt;
1339 return std::nullopt;
1343std::optional<AvailableValue>
1344GVNPass::analyzeLoadAvailability(LoadInst *
Load,
const ReachingMemVal &Dep,
1346 assert(
Load->isUnordered() &&
"rules below are incorrect for ordered access");
1347 assert((Dep.Kind == DepKind::Def || Dep.Kind == DepKind::Clobber) &&
1348 "expected a local dependence");
1352 const DataLayout &
DL =
Load->getDataLayout();
1353 if (Dep.Kind == DepKind::Clobber) {
1359 if (
Address &&
Load->isAtomic() <= DepSI->isAtomic()) {
1376 Load->isAtomic() <= DepLoad->isAtomic()) {
1383 DepLoad->getFunction())) {
1384 const auto ClobberOff = MD->getClobberOffset(DepLoad);
1386 Offset = (ClobberOff == std::nullopt || *ClobberOff < 0)
1392 DepLoad->getFunction()) ||
1419 dbgs() <<
" is clobbered by " << *DepInst <<
'\n';);
1423 return std::nullopt;
1425 assert(Dep.Kind == DepKind::Def &&
"follows from above");
1432 if (Constant *InitVal =
1442 return std::nullopt;
1445 if (S->isAtomic() <
Load->isAtomic())
1446 return std::nullopt;
1457 return std::nullopt;
1460 if (
LD->isAtomic() <
Load->isAtomic())
1461 return std::nullopt;
1470 assert(Sel->getType() ==
Load->getPointerOperandType());
1471 if (
auto AV = analyzeSelectAvailability(
Load, Sel->getCondition(),
1472 Sel->getTrueValue(),
1473 Sel->getFalseValue(), DepInst))
1475 return std::nullopt;
1482 dbgs() <<
" has unknown def " << *DepInst <<
'\n';);
1483 return std::nullopt;
1486void GVNPass::analyzeLoadAvailability(LoadInst *
Load,
1487 SmallVectorImpl<ReachingMemVal> &Deps,
1488 AvailValInBlkVect &ValuesPerBlock,
1489 UnavailBlkVect &UnavailableBlocks) {
1494 for (
const auto &Dep : Deps) {
1497 if (DeadBlocks.count(DepBB)) {
1504 if (Dep.Kind == DepKind::Other) {
1505 UnavailableBlocks.push_back(DepBB);
1512 if (Dep.Kind == DepKind::Select) {
1513 if (
auto AV = analyzeSelectAvailability(
1515 const_cast<Value *
>(Dep.SelTrueAddr),
1517 ValuesPerBlock.push_back(
1520 UnavailableBlocks.push_back(DepBB);
1529 analyzeLoadAvailability(
Load, Dep,
const_cast<Value *
>(Dep.Addr))) {
1533 ValuesPerBlock.push_back(
1536 UnavailableBlocks.push_back(DepBB);
1540 assert(Deps.size() == ValuesPerBlock.size() + UnavailableBlocks.size() &&
1541 "post condition violation");
1563LoadInst *GVNPass::findLoadToHoistIntoPred(BasicBlock *Pred, BasicBlock *LoadBB,
1567 if (
Term->getNumSuccessors() != 2 ||
Term->isSpecialTerminator())
1569 auto *SuccBB =
Term->getSuccessor(0);
1570 if (SuccBB == LoadBB)
1571 SuccBB =
Term->getSuccessor(1);
1572 if (!SuccBB->getSinglePredecessor())
1576 for (Instruction &Inst : *SuccBB) {
1577 if (Inst.isDebugOrPseudoInst())
1579 if (--NumInsts == 0)
1582 if (!Inst.isIdenticalTo(
Load))
1585 bool HasLocalDep =
true;
1587 MemDepResult Dep = MD->getDependency(&Inst);
1590 auto *MSSA = MSSAU->getMemorySSA();
1592 if (
auto *MA = MSSA->getMemoryAccess(&Inst); MA &&
isa<MemoryUse>(MA)) {
1593 auto *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(MA);
1594 HasLocalDep = Clobber->getBlock() == SuccBB;
1602 if (!HasLocalDep && !ICF->isDominatedByICFIFromSameBlock(&Inst))
1613void GVNPass::eliminatePartiallyRedundantLoad(
1614 LoadInst *
Load, AvailValInBlkVect &ValuesPerBlock,
1615 MapVector<BasicBlock *, Value *> &AvailableLoads,
1616 MapVector<BasicBlock *, LoadInst *> *CriticalEdgePredAndLoad) {
1617 for (
const auto &AvailableLoad : AvailableLoads) {
1618 BasicBlock *UnavailableBlock = AvailableLoad.first;
1619 Value *LoadPtr = AvailableLoad.second;
1622 new LoadInst(
Load->getType(), LoadPtr,
Load->getName() +
".pre",
1623 Load->getProperties(),
1625 NewLoad->setDebugLoc(
Load->getDebugLoc());
1627 auto *NewAccess = MSSAU->createMemoryAccessInBB(
1630 MSSAU->insertDef(NewDef,
true);
1636 AAMDNodes Tags =
Load->getAAMetadata();
1638 NewLoad->setAAMetadata(Tags);
1640 if (
auto *MD =
Load->getMetadata(LLVMContext::MD_invariant_load))
1641 NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
1642 if (
auto *InvGroupMD =
Load->getMetadata(LLVMContext::MD_invariant_group))
1643 NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
1644 if (
auto *RangeMD =
Load->getMetadata(LLVMContext::MD_range))
1645 NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
1646 if (
auto *NoFPClassMD =
Load->getMetadata(LLVMContext::MD_nofpclass))
1647 NewLoad->setMetadata(LLVMContext::MD_nofpclass, NoFPClassMD);
1649 if (
auto *AccessMD =
Load->getMetadata(LLVMContext::MD_access_group))
1650 if (LI->getLoopFor(
Load->getParent()) == LI->getLoopFor(UnavailableBlock))
1651 NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
1660 ValuesPerBlock.push_back(
1663 MD->invalidateCachedPointerInfo(LoadPtr);
1668 if (CriticalEdgePredAndLoad) {
1669 auto It = CriticalEdgePredAndLoad->
find(UnavailableBlock);
1670 if (It != CriticalEdgePredAndLoad->
end()) {
1671 ++NumPRELoadMoved2CEPred;
1672 ICF->insertInstructionTo(NewLoad, UnavailableBlock);
1673 LoadInst *OldLoad = It->second;
1677 if (uint32_t ValNo = VN.lookup(OldLoad,
false))
1678 LeaderTable.erase(ValNo, OldLoad, OldLoad->
getParent());
1679 removeInstruction(OldLoad);
1687 ICF->removeUsersOf(
Load);
1688 Load->replaceAllUsesWith(V);
1692 I->setDebugLoc(
Load->getDebugLoc());
1693 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
1694 MD->invalidateCachedPointerInfo(V);
1697 <<
"load eliminated by PRE";
1702bool GVNPass::performLoadPRE(LoadInst *
Load, AvailValInBlkVect &ValuesPerBlock,
1703 UnavailBlkVect &UnavailableBlocks) {
1712 SmallPtrSet<BasicBlock *, 4> Blockers(
llvm::from_range, UnavailableBlocks);
1734 bool MustEnsureSafetyOfSpeculativeExecution =
1735 ICF->isDominatedByICFIFromSameBlock(
Load);
1739 if (TmpBB == LoadBB)
1741 if (Blockers.count(TmpBB))
1753 MustEnsureSafetyOfSpeculativeExecution =
1754 MustEnsureSafetyOfSpeculativeExecution || ICF->hasICF(TmpBB);
1762 MapVector<BasicBlock *, Value *> PredLoads;
1763 DenseMap<BasicBlock *, AvailabilityState> FullyAvailableBlocks;
1766 for (BasicBlock *UnavailableBB : UnavailableBlocks)
1774 MapVector<BasicBlock *, LoadInst *> CriticalEdgePredAndLoad;
1780 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
1792 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
1799 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
1806 if (DT->dominates(LoadBB, Pred)) {
1809 <<
"COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
1814 if (LoadInst *LI = findLoadToHoistIntoPred(Pred, LoadBB,
Load))
1815 CriticalEdgePredAndLoad[Pred] = LI;
1820 PredLoads[Pred] =
nullptr;
1825 unsigned NumInsertPreds = PredLoads.
size() + CriticalEdgePredSplit.
size();
1826 unsigned NumUnavailablePreds = NumInsertPreds +
1827 CriticalEdgePredAndLoad.
size();
1828 assert(NumUnavailablePreds != 0 &&
1829 "Fully available value should already be eliminated!");
1830 (void)NumUnavailablePreds;
1836 if (NumInsertPreds > 1)
1841 if (MustEnsureSafetyOfSpeculativeExecution) {
1842 if (CriticalEdgePredSplit.
size())
1846 for (
auto &PL : PredLoads)
1850 for (
auto &CEP : CriticalEdgePredAndLoad)
1857 for (BasicBlock *OrigPred : CriticalEdgePredSplit) {
1858 BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
1859 assert(!PredLoads.count(OrigPred) &&
"Split edges shouldn't be in map!");
1860 PredLoads[NewPred] =
nullptr;
1861 LLVM_DEBUG(
dbgs() <<
"Split critical edge " << OrigPred->getName() <<
"->"
1862 << LoadBB->
getName() <<
'\n');
1865 for (
auto &CEP : CriticalEdgePredAndLoad)
1866 PredLoads[CEP.first] =
nullptr;
1869 bool CanDoPRE =
true;
1870 const DataLayout &
DL =
Load->getDataLayout();
1871 SmallVector<Instruction*, 8> NewInsts;
1872 for (
auto &PredLoad : PredLoads) {
1873 BasicBlock *UnavailablePred = PredLoad.first;
1883 Value *LoadPtr =
Load->getPointerOperand();
1885 while (Cur != LoadBB) {
1898 LoadPtr =
Address.translateWithInsertion(LoadBB, UnavailablePred, *DT,
1905 << *
Load->getPointerOperand() <<
"\n");
1910 PredLoad.second = LoadPtr;
1914 while (!NewInsts.
empty()) {
1924 return !CriticalEdgePredSplit.empty();
1932 <<
" INSTS: " << *NewInsts.
back()
1936 for (Instruction *
I : NewInsts) {
1940 I->updateLocationAfterHoist();
1949 eliminatePartiallyRedundantLoad(
Load, ValuesPerBlock, PredLoads,
1950 &CriticalEdgePredAndLoad);
1955bool GVNPass::performLoopLoadPRE(LoadInst *
Load,
1956 AvailValInBlkVect &ValuesPerBlock,
1957 UnavailBlkVect &UnavailableBlocks) {
1958 const Loop *
L = LI->getLoopFor(
Load->getParent());
1960 if (!L ||
L->getHeader() !=
Load->getParent())
1965 if (!Preheader || !Latch)
1968 Value *LoadPtr =
Load->getPointerOperand();
1970 if (!
L->isLoopInvariant(LoadPtr))
1976 if (ICF->isDominatedByICFIFromSameBlock(
Load))
1980 for (
auto *Blocker : UnavailableBlocks) {
1982 if (!
L->contains(Blocker))
1994 if (L != LI->getLoopFor(Blocker))
2002 if (DT->dominates(Blocker, Latch))
2006 if (Blocker->getTerminator()->mayWriteToMemory())
2009 LoopBlock = Blocker;
2021 MapVector<BasicBlock *, Value *> AvailableLoads;
2022 AvailableLoads[LoopBlock] = LoadPtr;
2023 AvailableLoads[Preheader] = LoadPtr;
2026 eliminatePartiallyRedundantLoad(
Load, ValuesPerBlock, AvailableLoads,
2034 using namespace ore;
2038 <<
"load of type " << NV(
"Type",
Load->getType()) <<
" eliminated"
2039 << setExtraArgs() <<
" in favor of "
2046bool GVNPass::processNonLocalLoad(LoadInst *
Load) {
2048 if (
Load->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2049 Load->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2054 MD->getNonLocalPointerDependency(
Load, Deps);
2059 unsigned NumDeps = Deps.size();
2066 for (
const NonLocalDepResult &Dep : Deps) {
2067 const auto &
R = Dep.getResult();
2068 SelectAddr SelAddr = Dep.getAddress();
2074 ReachingMemVal::getSelect(BB,
Cond, Addrs.first, Addrs.second));
2086 return processNonLocalLoad(
Load, MemVals);
2089bool GVNPass::processNonLocalLoad(LoadInst *
Load,
2090 SmallVectorImpl<ReachingMemVal> &Deps) {
2093 if (Deps.
size() == 1 && Deps[0].Kind == DepKind::Other) {
2095 dbgs() <<
" has unknown dependencies\n";);
2103 if (GetElementPtrInst *
GEP =
2105 for (Use &U :
GEP->indices())
2112 AvailValInBlkVect ValuesPerBlock;
2113 UnavailBlkVect UnavailableBlocks;
2114 analyzeLoadAvailability(
Load, Deps, ValuesPerBlock, UnavailableBlocks);
2118 if (ValuesPerBlock.empty())
2126 if (UnavailableBlocks.empty()) {
2132 ICF->removeUsersOf(
Load);
2133 Load->replaceAllUsesWith(V);
2141 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2142 I->setDebugLoc(
Load->getDebugLoc());
2143 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2144 MD->invalidateCachedPointerInfo(V);
2157 if (performLoopLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks) ||
2158 performLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks))
2164bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2168 if (
Cond->isZero()) {
2178 const MemoryUseOrDef *FirstNonDom =
nullptr;
2180 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2187 for (
const auto &Acc : *AL) {
2189 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2190 FirstNonDom = Current;
2197 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2199 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2200 : MSSAU->createMemoryAccessInBB(
2222 return propagateEquality(V, True, IntrinsicI);
2227 I->replaceAllUsesWith(Repl);
2234 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2245 PointerUsesQueue.
push_back(PointerOperand);
2250 while (!PointerUsesQueue.
empty()) {
2253 "Null or GlobalValue should not be inserted");
2257 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2272 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2274 MostDominatingInstruction =
I;
2278 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2284static std::optional<MemoryLocation>
2291 switch (
II->getIntrinsicID()) {
2292 case Intrinsic::masked_load:
2294 case Intrinsic::masked_store:
2297 return std::nullopt;
2304 return std::nullopt;
2308 return std::nullopt;
2314std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2315 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2316 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2317 BatchAAResults &AA, LoadInst *L) {
2320 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2324 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2326 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2334 Choice->Kind = DepKind::Clobber;
2335 Choice->Offset = AR.getOffset();
2337 Choice->Kind = DepKind::Def;
2338 Choice->Offset = -1;
2341 Choice->Inst = Candidate;
2342 Choice->Block = Candidate->getParent();
2345 std::optional<ReachingMemVal> ReachingVal;
2346 for (MemoryAccess *MA : ClobbersList) {
2348 for (User *U : MA->
users()) {
2350 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2353 if (!UseOrDef || UseOrDef->getBlock() != BB)
2362 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2376 UpdateChoice(ReachingVal, AR, MemI);
2388std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2389 MemoryAccess *ClobberMA,
const MemoryLocation &Loc,
bool IsInvariantLoad,
2390 BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2398 if (
Alloc->getParent() == BB)
2399 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2400 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2404 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2405 return std::nullopt;
2409 return L->getOrdering();
2416 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2418 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2429 return std::nullopt;
2430 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2435 return std::nullopt;
2440 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2445 "Must be the superset/partial overlap case with positive offset");
2446 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2451 return std::nullopt;
2452 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2454 if (AA.isMustAlias(IIObjLoc, Loc))
2455 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2456 return std::nullopt;
2464 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2465 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2471 return std::nullopt;
2475 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2479 return std::nullopt;
2483 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2489bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2490 MemoryAccess *ClobberMA,
2491 DependencyBlockSet &Blocks,
2492 SmallVectorImpl<BasicBlock *> &Worklist) {
2502 if (!DT->isReachableFromEntry(Pred))
2506 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2509 PHITransAddr TransAddr = Addr;
2513 auto It = Blocks.find(Pred);
2514 if (It != Blocks.end()) {
2518 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2525 Pred, DependencyBlockInfo(TransAddr,
2526 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2533 for (
auto &
P : Preds) {
2534 [[maybe_unused]]
auto It =
2535 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2547void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2549 const DependencyBlockInfo &StartInfo,
2550 const DependencyBlockSet &Blocks,
2552 MemoryAccess *MA = StartInfo.InitialClobberMA;
2553 MemoryAccess *LastMA = StartInfo.ClobberMA;
2556 while (MA != LastMA) {
2570 BB = DT->getNode(BB)->getIDom()->getBlock();
2574 auto It = Blocks.find(BB);
2575 if (It == Blocks.end())
2578 MA = It->second.InitialClobberMA;
2579 LastMA = It->second.ClobberMA;
2580 if (MA == Clobbers.
back())
2597bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2598 SmallVectorImpl<ReachingMemVal> &
Values,
2600 EarliestEscapeAnalysis EA(*DT, LI);
2601 BatchAAResults AA(AAR, &EA);
2603 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2609 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2622 if (
auto RMV = scanMemoryAccessesUsers(
2623 Loc, IsInvariantLoad, StartBlock,
2625 Values.emplace_back(*RMV);
2635 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2636 StartBlock, MSSA, AA)) {
2637 Values.emplace_back(*RMV);
2644 }
while (ClobberMA->
getBlock() == StartBlock);
2647 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2648 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2657 DependencyBlockSet Blocks;
2658 SmallVector<BasicBlock *, 16> InitialWorklist;
2659 const DataLayout &
DL =
L->getModule()->getDataLayout();
2660 if (!collectPredecessors(StartBlock,
2661 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2662 ClobberMA, Blocks, InitialWorklist))
2666 auto Worklist = InitialWorklist;
2667 while (!Worklist.
empty()) {
2669 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2672 if (!
Info.Addr.getAddr())
2680 if (
auto RMV = accessMayModifyLocation(
2682 IsInvariantLoad, BB, MSSA, AA)) {
2687 "LiveOnEntry aliases everything");
2703 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2704 Info.ForceUnknown =
true;
2707 if (BB != StartBlock &&
2708 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2709 Info.ForceUnknown =
true;
2719 Worklist = InitialWorklist;
2720 for (BasicBlock *BB : Worklist) {
2721 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2722 Info.Visited =
true;
2726 while (!Worklist.empty()) {
2727 auto *BB = Worklist.pop_back_val();
2728 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2732 if (!
Info.Addr.getAddr()) {
2733 Values.push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2738 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2741 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2753 if (
Info.ForceUnknown) {
2754 Values.push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2760 auto It = Blocks.find(Pred);
2761 if (It == Blocks.end())
2763 DependencyBlockInfo &PredInfo = It->second;
2764 if (PredInfo.Visited)
2766 PredInfo.Visited =
true;
2767 Worklist.push_back(Pred);
2776bool GVNPass::processLoad(LoadInst *L) {
2781 if (!
L->isUnordered())
2784 if (
L->getType()->isTokenLikeTy())
2787 if (
L->use_empty()) {
2792 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2795 MemDepResult Dep = MD->getDependency(L);
2799 return processNonLocalLoad(L);
2803 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2806 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2809 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2811 assert(MemVals.
size() &&
"Expected at least an unknown value");
2812 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2813 return processNonLocalLoad(L, MemVals);
2815 MemVal = MemVals[0];
2818 if (MemVal.Kind == DepKind::Other) {
2822 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2823 dbgs() <<
" has unknown dependence\n";);
2827 auto AV = analyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2834 ICF->removeUsersOf(L);
2837 MSSAU->removeMemoryAccess(L);
2850bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2853 MemDepResult Dep = MD->getDependency(
I);
2859 Value *Passthrough =
I->getOperand(2);
2863 StoreVal->
getType() !=
I->getType())
2870 ICF->removeUsersOf(
I);
2871 I->replaceAllUsesWith(OpToForward);
2879std::pair<uint32_t, bool>
2880GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2881 uint32_t &
E = ExpressionNumbering[
Exp];
2882 bool CreateNewValNum = !
E;
2883 if (CreateNewValNum) {
2884 Expressions.push_back(Exp);
2885 if (ExprIdx.size() < NextValueNumber + 1)
2886 ExprIdx.resize(NextValueNumber * 2);
2887 E = NextValueNumber;
2888 ExprIdx[NextValueNumber++] = NextExprNumber++;
2890 return {
E, CreateNewValNum};
2895bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2898 GVN.LeaderTable.getLeaders(Num),
2906 auto FindRes = PhiTranslateTable.find({Num, Pred});
2907 if (FindRes != PhiTranslateTable.end())
2908 return FindRes->second;
2909 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2910 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2921 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2922 for (
const auto &Entry : Leaders) {
2924 if (
Call &&
Call->getParent() == PhiBlock)
2928 if (
AA->doesNotAccessMemory(
Call))
2931 if (!MD || !
AA->onlyReadsMemory(
Call))
2943 if (
D.getResult().isNonFuncLocal())
2951uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2952 const BasicBlock *PhiBlock,
2956 if (PHINode *PN = NumberingPhi[Num]) {
2957 if (PN->getParent() != PhiBlock)
2959 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2960 if (PN->getIncomingBlock(
I) != Pred)
2962 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2968 if (BasicBlock *BB = NumberingBB[Num]) {
2969 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
2981 return lookupOrAdd(PredPhi->getBlock());
2987 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
2993 if (!areAllValsInBB(Num, PhiBlock, GVN))
2996 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
3000 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
3004 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
3005 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
3006 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
3008 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
3011 if (
Exp.Commutative) {
3012 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
3013 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
3015 uint32_t Opcode =
Exp.Opcode >> 8;
3016 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
3017 Exp.Opcode = (Opcode << 8) |
3023 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
3024 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
3025 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3033void GVNPass::ValueTable::eraseTranslateCacheEntry(
3036 PhiTranslateTable.erase({Num, Pred});
3045 auto Leaders = LeaderTable.getLeaders(Num);
3046 if (Leaders.empty())
3049 Value *Val =
nullptr;
3050 for (
const auto &Entry : Leaders) {
3051 if (DT->dominates(Entry.BB, BB)) {
3071 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3072 assert((!Pred || Pred ==
E.getStart()) &&
3073 "No edge between these basic blocks!");
3074 return Pred !=
nullptr;
3077void GVNPass::assignBlockRPONumber(Function &
F) {
3078 BlockRPONumber.clear();
3079 uint32_t NextBlockNumber = 1;
3080 ReversePostOrderTraversal<Function *> RPOT(&
F);
3081 for (BasicBlock *BB : RPOT)
3082 BlockRPONumber[BB] = NextBlockNumber++;
3083 InvalidBlockRPONumbers =
false;
3091bool GVNPass::propagateEquality(
3093 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3098 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3105 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3109 while (!Worklist.
empty()) {
3110 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3111 LHS = Item.first;
RHS = Item.second;
3125 const DataLayout &
DL =
3134 uint32_t LVN = VN.lookupOrAdd(
LHS);
3139 uint32_t RVN = VN.lookupOrAdd(
RHS);
3156 for (
const BasicBlock *BB : DominatedBlocks)
3157 LeaderTable.insert(LVN,
RHS, BB);
3164 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3167 unsigned NumReplacements;
3168 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3170 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3173 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3174 CanReplacePointersCallBack);
3176 if (NumReplacements > 0) {
3178 NumGVNEqProp += NumReplacements;
3181 MD->invalidateCachedPointerInfo(
LHS);
3198 bool IsKnownFalse = !IsKnownTrue;
3214 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3219 if (
Cmp->isEquivalence(IsKnownFalse))
3220 Worklist.
push_back(std::make_pair(Op0, Op1));
3224 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3228 uint32_t NextNum = VN.getNextUnusedValueNumber();
3229 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3232 if (Num < NextNum) {
3233 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3238 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3239 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3240 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3243 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3244 if (!DT->dominates(
Entry.BB, InstBB) &&
3245 !DT->dominates(InstBB,
Entry.BB))
3251 unsigned NumReplacements;
3252 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3257 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3258 Changed |= NumReplacements > 0;
3259 NumGVNEqProp += NumReplacements;
3262 MD->invalidateCachedPointerInfo(NotCmp);
3270 for (
const BasicBlock *BB : DominatedBlocks)
3271 LeaderTable.insert(Num, NotVal, BB);
3280 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3285 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3295bool GVNPass::processInstruction(Instruction *
I) {
3300 const DataLayout &
DL =
I->getDataLayout();
3303 if (!
I->use_empty()) {
3306 ICF->removeUsersOf(
I);
3307 I->replaceAllUsesWith(V);
3315 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3316 MD->invalidateCachedPointerInfo(V);
3323 return processAssumeIntrinsic(Assume);
3326 if (processLoad(
Load))
3329 unsigned Num = VN.lookupOrAdd(
Load);
3330 LeaderTable.insert(Num,
Load,
Load->getParent());
3342 return processFoldableCondBr(BI);
3344 Value *BranchCond = BI->getCondition();
3348 if (TrueSucc == FalseSucc)
3355 BasicBlockEdge TrueE(Parent, TrueSucc);
3356 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3359 BasicBlockEdge FalseE(Parent, FalseSucc);
3360 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3367 Value *SwitchCond =
SI->getCondition();
3372 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3374 ++SwitchEdges[Succ];
3376 for (
const auto &Case :
SI->cases()) {
3379 if (SwitchEdges.
lookup(Dst) == 1) {
3380 BasicBlockEdge
E(Parent, Dst);
3381 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3389 if (
I->getType()->isVoidTy())
3392 uint32_t NextNum = VN.getNextUnusedValueNumber();
3393 unsigned Num = VN.lookupOrAdd(
I);
3398 LeaderTable.insert(Num,
I,
I->getParent());
3405 const DataLayout &
DL =
I->getDataLayout();
3406 unsigned AS = PTA->getPointerAddressSpace();
3407 if (
DL.getAddressSizeInBits(AS) ==
DL.getPointerSizeInBits(AS) &&
3408 !
DL.hasUnstableRepresentation(AS)) {
3410 VN.lookupPtrToInt(PTA->getPointerOperand(), PTA->getType());
3411 if (
Value *PTI = findLeader(
I->getParent(), PTINum)) {
3422 if (Num >= NextNum) {
3423 LeaderTable.insert(Num,
I,
I->getParent());
3429 Value *Repl = findLeader(
I->getParent(), Num);
3432 LeaderTable.insert(Num,
I,
I->getParent());
3445 MD->invalidateCachedPointerInfo(Repl);
3451bool GVNPass::runImpl(Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3452 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3453 MemoryDependenceResults *RunMD, LoopInfo &LI,
3454 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3460 VN.setAliasAnalysis(&RunAA);
3462 ImplicitControlFlowTracking ImplicitCFT;
3471 InvalidBlockRPONumbers =
true;
3472 MemorySSAUpdater Updater(MSSA);
3473 MSSAU = MSSA ? &Updater :
nullptr;
3476 bool ShouldContinue =
true;
3478 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3490 unsigned Iteration = 0;
3491 while (ShouldContinue) {
3494 ShouldContinue = iterateOnFunction(
F);
3502 assignValNumForDeadCode();
3503 bool PREChanged =
true;
3504 while (PREChanged) {
3505 PREChanged = performPRE(
F);
3515 cleanupGlobalSets();
3526bool GVNPass::processBlock(BasicBlock *BB) {
3527 if (DeadBlocks.count(BB))
3530 bool ChangedFunction =
false;
3536 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3538 for (PHINode *PN : PHINodesToRemove) {
3539 removeInstruction(PN);
3542 ChangedFunction |= processInstruction(&Inst);
3543 return ChangedFunction;
3547bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3548 BasicBlock *Curr,
unsigned int ValNo) {
3554 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3562 if (!VN.exists(
Op)) {
3567 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3568 if (
Value *V = findLeader(Pred, TValNo)) {
3586 ICF->insertInstructionTo(Instr, Pred);
3588 unsigned Num = VN.lookupOrAdd(Instr);
3592 LeaderTable.insert(Num, Instr, Pred);
3596bool GVNPass::performScalarPRE(Instruction *CurInst) {
3622 if (CallB->isInlineAsm())
3626 uint32_t ValNo = VN.lookup(CurInst);
3634 unsigned NumWith = 0;
3635 unsigned NumWithout = 0;
3640 if (InvalidBlockRPONumbers)
3641 assignBlockRPONumber(*CurrentBlock->
getParent());
3647 if (!DT->isReachableFromEntry(
P)) {
3652 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3653 "Invalid BlockRPONumber map.");
3654 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3659 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3660 Value *PredV = findLeader(
P, TValNo);
3665 }
else if (PredV == CurInst) {
3677 if (NumWithout > 1 || NumWith == 0)
3685 if (NumWithout != 0) {
3691 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3704 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3708 PREInstr = CurInst->
clone();
3709 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3712 verifyRemoved(PREInstr);
3721 assert(PREInstr !=
nullptr || NumWithout == 0);
3727 CurInst->
getName() +
".pre-phi");
3728 Phi->insertBefore(CurrentBlock->begin());
3729 for (
auto &[V, BB] : PredMap) {
3734 Phi->addIncoming(V, BB);
3736 Phi->addIncoming(PREInstr, PREPred);
3742 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3743 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3746 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3747 MD->invalidateCachedPointerInfo(Phi);
3748 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3751 removeInstruction(CurInst);
3758bool GVNPass::performPRE(Function &
F) {
3760 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3762 if (CurrentBlock == &
F.getEntryBlock())
3766 if (CurrentBlock->isEHPad())
3770 BE = CurrentBlock->end();
3773 Changed |= performScalarPRE(CurInst);
3777 if (splitCriticalEdges())
3785BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3790 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3793 MD->invalidateCachedPredecessors();
3794 InvalidBlockRPONumbers =
true;
3801bool GVNPass::splitCriticalEdges() {
3802 if (ToSplit.empty())
3807 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3809 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3811 }
while (!ToSplit.empty());
3814 MD->invalidateCachedPredecessors();
3815 InvalidBlockRPONumbers =
true;
3821bool GVNPass::iterateOnFunction(Function &
F) {
3822 cleanupGlobalSets();
3829 ReversePostOrderTraversal<Function *> RPOT(&
F);
3831 for (BasicBlock *BB : RPOT)
3837void GVNPass::cleanupGlobalSets() {
3839 LeaderTable.clear();
3840 BlockRPONumber.clear();
3842 InvalidBlockRPONumbers =
true;
3845void GVNPass::removeInstruction(Instruction *
I) {
3847 if (MD) MD->removeInstruction(
I);
3849 MSSAU->removeMemoryAccess(
I);
3853 ICF->removeInstruction(
I);
3854 I->eraseFromParent();
3860void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3861 VN.verifyRemoved(Inst);
3868void GVNPass::addDeadBlock(BasicBlock *BB) {
3870 SmallSetVector<BasicBlock *, 4>
DF;
3873 while (!NewDead.
empty()) {
3875 if (DeadBlocks.count(
D))
3879 SmallVector<BasicBlock *, 8> Dom;
3880 DT->getDescendants(
D, Dom);
3881 DeadBlocks.insert_range(Dom);
3884 for (BasicBlock *
B : Dom) {
3886 if (DeadBlocks.count(S))
3889 bool AllPredDead =
true;
3891 if (!DeadBlocks.count(
P)) {
3892 AllPredDead =
false;
3912 for (BasicBlock *
B :
DF) {
3913 if (DeadBlocks.count(
B))
3919 for (BasicBlock *
P : Preds) {
3920 if (!DeadBlocks.count(
P))
3925 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3926 DeadBlocks.insert(
P = S);
3932 if (!DeadBlocks.count(
P))
3934 for (PHINode &Phi :
B->phis()) {
3937 MD->invalidateCachedPointerInfo(&Phi);
3956bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
3967 if (DeadBlocks.count(DeadRoot))
3971 DeadRoot = splitCriticalEdges(BI->getParent(), DeadRoot);
3973 addDeadBlock(DeadRoot);
3981void GVNPass::assignValNumForDeadCode() {
3982 for (BasicBlock *BB : DeadBlocks) {
3983 for (Instruction &Inst : *BB) {
3984 unsigned ValNum = VN.lookupOrAdd(&Inst);
3985 LeaderTable.insert(ValNum, &Inst, BB);
3996 bool ScalarPRE =
true)
3998 .setMemDep(MemDepAnalysis)
3999 .setMemorySSA(MemSSAAnalysis)
4000 .setScalarPRE(ScalarPRE)) {
4009 if (Impl.isMemorySSAEnabled() && !MSSAWP)
4012 return Impl.runImpl(
4017 Impl.isMemDepEnabled()
4022 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
4030 if (Impl.isMemDepEnabled())
4039 if (Impl.isMemorySSAEnabled())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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< 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(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Helper class for SSA formation on a set of values defined in multiple blocks.
LLVM_ABI void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
LLVM_ABI Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
LLVM_ABI bool HasValueForBlock(BasicBlock *BB) const
Return true if the SSAUpdater already has a value for the specified block.
LLVM_ABI void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
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.
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.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
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)
A CRTP mix-in to automatically provide informational APIs needed for passes.