91#define DEBUG_TYPE "gvn"
93STATISTIC(NumGVNInstr,
"Number of instructions deleted");
95STATISTIC(NumGVNPRE,
"Number of instructions PRE'd");
97STATISTIC(NumGVNSimpl,
"Number of instructions simplified");
98STATISTIC(NumGVNEqProp,
"Number of equalities propagated");
102 "Number of loads moved to predecessor of a critical edge in PRE");
104STATISTIC(IsValueFullyAvailableInBlockNumSpeculationsMax,
105 "Number of blocks speculated as available in "
106 "IsValueFullyAvailableInBlock(), max");
108 "Number of times we we reached gvn-max-block-speculations cut-off "
109 "preventing further exploration");
125 cl::desc(
"The number of memory accesses to scan in a block in reaching "
126 "memory values analysis (default = 100)"));
130 cl::desc(
"Max number of dependences to attempt Load PRE (default = 100)"));
134 cl::desc(
"Max number of blocks scanned per load in the MemorySSA "
135 "reaching-value analysis (default = 200)"));
140 cl::desc(
"Max number of blocks we're willing to speculate on (and recurse "
141 "into) when deducing if a value is fully available or not in GVN "
146 cl::desc(
"Max number of visited instructions when trying to find "
147 "dominating value of select dependency (default = 100)"));
151 cl::desc(
"Max number of instructions to scan in each basic block in GVN "
167 if (
Opcode != Other.Opcode)
175 if ((!
Attrs.isEmpty() || !Other.Attrs.isEmpty()) &&
176 !
Attrs.intersectWith(
Ty->getContext(), Other.Attrs).has_value())
310 Res.
AV = std::move(
AV);
326 return AV.MaterializeAdjustedValue(
Load,
BB->getTerminator());
337 E.Opcode =
I->getOpcode();
342 E.VarArgs.push_back(
lookupOrAdd(GCR->getOperand(0)));
343 E.VarArgs.push_back(
lookupOrAdd(GCR->getBasePtr()));
344 E.VarArgs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
346 for (
Use &
Op :
I->operands())
349 if (
I->isCommutative()) {
354 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
355 if (
E.VarArgs[0] >
E.VarArgs[1])
357 E.Commutative =
true;
363 if (
E.VarArgs[0] >
E.VarArgs[1]) {
368 E.Commutative =
true;
370 E.VarArgs.append(IVI->idx_begin(), IVI->idx_end());
372 ArrayRef<int> ShuffleMask = SVI->getShuffleMask();
373 E.VarArgs.append(ShuffleMask.
begin(), ShuffleMask.
end());
375 E.Attrs = CB->getAttributes();
381GVNPass::Expression GVNPass::ValueTable::createCmpExpr(
383 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
384 "Not a comparison!");
387 E.VarArgs.push_back(lookupOrAdd(
LHS));
388 E.VarArgs.push_back(lookupOrAdd(
RHS));
391 if (
E.VarArgs[0] >
E.VarArgs[1]) {
395 E.Opcode = (Opcode << 8) | Predicate;
396 E.Commutative =
true;
401GVNPass::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) {
402 assert(EI &&
"Not an ExtractValueInst?");
413 E.VarArgs.push_back(lookupOrAdd(WO->
getLHS()));
414 E.VarArgs.push_back(lookupOrAdd(WO->
getRHS()));
422 E.VarArgs.push_back(lookupOrAdd(
Op));
429GVNPass::Expression GVNPass::ValueTable::createGEPExpr(GetElementPtrInst *
GEP) {
431 Type *PtrTy =
GEP->getType()->getScalarType();
432 const DataLayout &
DL =
GEP->getDataLayout();
433 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
434 SmallMapVector<Value *, APInt, 4> VariableOffsets;
436 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
440 E.Opcode =
GEP->getOpcode();
442 E.VarArgs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
443 for (
const auto &[V, Scale] : VariableOffsets) {
444 E.VarArgs.push_back(lookupOrAdd(V));
445 E.VarArgs.push_back(lookupOrAdd(ConstantInt::get(
Context, Scale)));
447 if (!ConstantOffset.isZero())
449 lookupOrAdd(ConstantInt::get(
Context, ConstantOffset)));
453 E.Opcode =
GEP->getOpcode();
454 E.Ty =
GEP->getSourceElementType();
455 for (Use &
Op :
GEP->operands())
456 E.VarArgs.push_back(lookupOrAdd(
Op));
465GVNPass::ValueTable::ValueTable() =
default;
466GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
467GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
468GVNPass::ValueTable::~ValueTable() =
default;
474 ValueNumbering.
insert(std::make_pair(V, Num));
476 NumberingPhi[Num] = PN;
486 assert(MSSA &&
"addMemoryStateToExp should not be called without MemorySSA");
487 assert(MSSA->getMemoryAccess(
I) &&
"Instruction does not access memory");
488 MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(
I);
489 Exp.VarArgs.push_back(lookupOrAdd(MA));
500 if (
C->getFunction()->isPresplitCoroutine()) {
501 ValueNumbering[
C] = NextValueNumber;
502 return NextValueNumber++;
508 if (
C->isConvergent()) {
509 ValueNumbering[
C] = NextValueNumber;
510 return NextValueNumber++;
516 if (
C->hasOperandBundles()) {
517 ValueNumbering[
C] = NextValueNumber;
518 return NextValueNumber++;
521 if (AA->doesNotAccessMemory(
C)) {
523 uint32_t
E = assignExpNewValueNum(Exp).first;
524 ValueNumbering[
C] =
E;
528 if (MD && AA->onlyReadsMemory(
C)) {
530 auto [
E, IsValNumNew] = assignExpNewValueNum(Exp);
532 ValueNumbering[
C] =
E;
536 MemDepResult LocalDep = MD->getDependency(
C);
539 ValueNumbering[
C] = NextValueNumber;
540 return NextValueNumber++;
543 if (LocalDep.
isDef()) {
548 if (!LocalDepCall || LocalDepCall->
arg_size() !=
C->arg_size()) {
549 ValueNumbering[
C] = NextValueNumber;
550 return NextValueNumber++;
553 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
554 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
555 uint32_t LocalDepCallVN = lookupOrAdd(LocalDepCall->
getArgOperand(
I));
556 if (CVN != LocalDepCallVN) {
557 ValueNumbering[
C] = NextValueNumber;
558 return NextValueNumber++;
562 uint32_t
V = lookupOrAdd(LocalDepCall);
563 ValueNumbering[
C] =
V;
569 MD->getNonLocalCallDependency(
C);
571 CallInst *CDep =
nullptr;
575 for (
const NonLocalDepEntry &
I : Deps) {
576 if (
I.getResult().isNonLocal())
581 if (!
I.getResult().isDef() || CDep !=
nullptr) {
588 if (NonLocalDepCall && DT->properlyDominates(
I.getBB(),
C->getParent())) {
589 CDep = NonLocalDepCall;
598 ValueNumbering[
C] = NextValueNumber;
599 return NextValueNumber++;
603 ValueNumbering[
C] = NextValueNumber;
604 return NextValueNumber++;
606 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
607 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
610 ValueNumbering[
C] = NextValueNumber;
611 return NextValueNumber++;
615 uint32_t
V = lookupOrAdd(CDep);
616 ValueNumbering[
C] =
V;
620 if (MSSA && IsMSSAEnabled && AA->onlyReadsMemory(
C)) {
622 addMemoryStateToExp(
C, Exp);
623 auto [
V,
_] = assignExpNewValueNum(Exp);
624 ValueNumbering[
C] =
V;
628 ValueNumbering[
C] = NextValueNumber;
629 return NextValueNumber++;
633uint32_t GVNPass::ValueTable::computeLoadStoreVN(Instruction *
I) {
634 if (!MSSA || !IsMSSAEnabled) {
635 ValueNumbering[
I] = NextValueNumber;
636 return NextValueNumber++;
640 Exp.Ty =
I->getType();
641 Exp.Opcode =
I->getOpcode();
642 for (Use &
Op :
I->operands())
643 Exp.VarArgs.push_back(lookupOrAdd(
Op));
644 addMemoryStateToExp(
I, Exp);
646 auto [
V,
_] = assignExpNewValueNum(Exp);
647 ValueNumbering[
I] =
V;
652bool GVNPass::ValueTable::exists(
Value *V)
const {
653 return ValueNumbering.contains(V);
665 auto VI = ValueNumbering.find(V);
666 if (VI != ValueNumbering.end())
671 ValueNumbering[V] = NextValueNumber;
674 return NextValueNumber++;
678 switch (
I->getOpcode()) {
679 case Instruction::Call:
681 case Instruction::FNeg:
682 case Instruction::Add:
683 case Instruction::FAdd:
684 case Instruction::Sub:
685 case Instruction::FSub:
686 case Instruction::Mul:
687 case Instruction::FMul:
688 case Instruction::UDiv:
689 case Instruction::SDiv:
690 case Instruction::FDiv:
691 case Instruction::URem:
692 case Instruction::SRem:
693 case Instruction::FRem:
694 case Instruction::Shl:
695 case Instruction::LShr:
696 case Instruction::AShr:
697 case Instruction::And:
698 case Instruction::Or:
699 case Instruction::Xor:
700 case Instruction::ICmp:
701 case Instruction::FCmp:
702 case Instruction::Trunc:
703 case Instruction::ZExt:
704 case Instruction::SExt:
705 case Instruction::FPToUI:
706 case Instruction::FPToSI:
707 case Instruction::UIToFP:
708 case Instruction::SIToFP:
709 case Instruction::FPTrunc:
710 case Instruction::FPExt:
711 case Instruction::PtrToInt:
712 case Instruction::PtrToAddr:
713 case Instruction::IntToPtr:
714 case Instruction::AddrSpaceCast:
715 case Instruction::BitCast:
716 case Instruction::Select:
717 case Instruction::Freeze:
718 case Instruction::ExtractElement:
719 case Instruction::InsertElement:
720 case Instruction::ShuffleVector:
721 case Instruction::InsertValue:
724 case Instruction::GetElementPtr:
727 case Instruction::ExtractValue:
730 case Instruction::PHI:
731 ValueNumbering[V] = NextValueNumber;
733 return NextValueNumber++;
734 case Instruction::Load:
735 case Instruction::Store:
736 return computeLoadStoreVN(
I);
738 ValueNumbering[V] = NextValueNumber;
739 return NextValueNumber++;
742 uint32_t E = assignExpNewValueNum(Exp).first;
743 ValueNumbering[V] = E;
750 auto VI = ValueNumbering.find(V);
752 assert(VI != ValueNumbering.end() &&
"Value not numbered?");
755 return (VI != ValueNumbering.end()) ? VI->second : 0;
762uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
765 Expression Exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
766 return assignExpNewValueNum(Exp).first;
774 return ExpressionNumbering.lookup(Exp);
779 ValueNumbering.clear();
780 ExpressionNumbering.clear();
781 NumberingPhi.clear();
783 PhiTranslateTable.clear();
792 uint32_t Num = ValueNumbering.lookup(V);
793 ValueNumbering.erase(V);
796 NumberingPhi.erase(Num);
798 NumberingBB.erase(Num);
803void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
804 assert(!ValueNumbering.contains(V) &&
805 "Inst still occurs in value numbering map!");
814 const auto &[It, Inserted] = NumToLeaders.try_emplace(
N, V, BB,
nullptr);
817 auto *NewSlot = TableAllocator.Allocate<LeaderListNode>();
818 new (NewSlot) LeaderListNode(V, BB, It->second.Next);
819 It->second.Next = NewSlot;
827 auto It = NumToLeaders.find(
N);
828 if (It == NumToLeaders.end())
831 LeaderListNode *Prev =
nullptr;
832 LeaderListNode *Curr = &It->second;
834 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
844 Prev->Next = Curr->Next;
845 Curr->~LeaderListNode();
846 TableAllocator.Deallocate<LeaderListNode>(Curr);
851 NumToLeaders.erase(It);
854 LeaderListNode *
Next = Curr->Next;
855 Curr->Entry.Val = std::move(
Next->Entry.Val);
856 Curr->Entry.BB =
Next->Entry.BB;
857 Curr->Next =
Next->Next;
858 Next->~LeaderListNode();
859 TableAllocator.Deallocate<LeaderListNode>(
Next);
881 return Options.AllowLoadPRESplitBackedge.value_or(
890 return Options.AllowMemDep.value_or(
false);
913 "On-demand computation of MemSSA implies that MemDep is disabled!");
917 bool Changed = runImpl(
F, AC, DT, TLI, AA, MemDep, LI, &ORE,
918 MSSA ? &MSSA->getMSSA() :
nullptr);
933 OS, MapClassName2PassName);
936 if (Options.AllowScalarPRE != std::nullopt)
937 OS << (*Options.AllowScalarPRE ?
"" :
"no-") <<
"scalar-pre;";
938 if (Options.AllowLoadPRE != std::nullopt)
939 OS << (*Options.AllowLoadPRE ?
"" :
"no-") <<
"load-pre;";
940 if (Options.AllowLoadPRESplitBackedge != std::nullopt)
941 OS << (*Options.AllowLoadPRESplitBackedge ?
"" :
"no-")
942 <<
"split-backedge-load-pre;";
943 if (Options.AllowMemDep != std::nullopt)
944 OS << (*Options.AllowMemDep ?
"" :
"no-") <<
"memdep;";
945 if (Options.AllowMemorySSA != std::nullopt)
946 OS << (*Options.AllowMemorySSA ?
"" :
"no-") <<
"memoryssa";
953 removeInstruction(
I);
980 std::optional<BasicBlock *> UnavailableBB;
984 unsigned NumNewNewSpeculativelyAvailableBBs = 0;
992 while (!Worklist.
empty()) {
996 std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator,
bool>
IV =
1004 UnavailableBB = CurrBB;
1015 ++NumNewNewSpeculativelyAvailableBBs;
1021 MaxBBSpeculationCutoffReachedTimes += (int)OutOfBudget;
1023 UnavailableBB = CurrBB;
1029 NewSpeculativelyAvailableBBs.
insert(CurrBB);
1035#if LLVM_ENABLE_STATS
1036 IsValueFullyAvailableInBlockNumSpeculationsMax.updateMax(
1037 NumNewNewSpeculativelyAvailableBBs);
1042 auto MarkAsFixpointAndEnqueueSuccessors =
1044 auto It = FullyAvailableBlocks.
find(BB);
1045 if (It == FullyAvailableBlocks.
end())
1052 State = FixpointState;
1055 "Found a speculatively available successor leftover?");
1063 if (UnavailableBB) {
1070 while (!Worklist.
empty())
1071 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1079 while (!Worklist.
empty())
1080 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1084 "Must have fixed all the new speculatively available blocks.");
1087 return !UnavailableBB;
1096 if (V.AV.Val == OldValue)
1097 V.AV.Val = NewValue;
1098 if (V.AV.isSelectValue()) {
1099 if (V.AV.V1 == OldValue)
1101 if (V.AV.V2 == OldValue)
1116 if (ValuesPerBlock.
size() == 1 &&
1118 Load->getParent())) {
1119 assert(!ValuesPerBlock[0].AV.isUndefValue() &&
1120 "Dead BB dominate this block");
1121 return ValuesPerBlock[0].MaterializeAdjustedValue(
Load);
1132 if (AV.AV.isUndefValue())
1142 if (BB ==
Load->getParent() &&
1143 ((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() ==
Load) ||
1144 (AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() ==
Load)))
1161 if (Res->
getType() != LoadTy) {
1176 Load->getFunction());
1187 if (!CoercedLoad->
hasMetadata(LLVMContext::MD_noundef))
1189 {LLVMContext::MD_dereferenceable,
1190 LLVMContext::MD_dereferenceable_or_null,
1191 LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group,
1192 LLVMContext::MD_alias_scope, LLVMContext::MD_noalias});
1208 assert(
V1 &&
V2 &&
"both value operands of the select must be present");
1216 assert(Res &&
"failed to materialize?");
1222 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1239 Value *PtrOp =
Load->getPointerOperand();
1245 for (
auto *U : PtrOp->
users()) {
1266 for (
auto *U : PtrOp->
users()) {
1269 if (
I->getFunction() ==
Load->getFunction() &&
1277 OtherAccess =
nullptr;
1296 using namespace ore;
1299 R <<
"load of type " << NV(
"Type",
Load->getType()) <<
" not eliminated"
1304 R <<
" in favor of " << NV(
"OtherAccess", OtherAccess);
1306 R <<
" because it is clobbered by " << NV(
"ClobberedBy", DepInst);
1320 for (
auto *Inst = BB == FromBB ? From : BB->
getTerminator();
1328 if (
SI->isSimple() &&
SI->getPointerOperand() ==
Loc.Ptr &&
1329 SI->getValueOperand()->getType() == LoadTy)
1330 return SI->getValueOperand();
1334 if (LI->getPointerOperand() ==
Loc.Ptr && LI->getType() == LoadTy)
1340std::optional<AvailableValue>
1342 Value *FalseAddr, Instruction *From) {
1344 "Invalid address type of true side of select dependency");
1346 "Invalid address type of false side of select dependency");
1354 return std::nullopt;
1358 return std::nullopt;
1362std::optional<AvailableValue>
1363GVNPass::analyzeLoadAvailability(LoadInst *
Load,
const ReachingMemVal &Dep,
1365 assert(
Load->isUnordered() &&
"rules below are incorrect for ordered access");
1366 assert((Dep.Kind == DepKind::Def || Dep.Kind == DepKind::Clobber) &&
1367 "expected a local dependence");
1371 const DataLayout &
DL =
Load->getDataLayout();
1372 if (Dep.Kind == DepKind::Clobber) {
1378 if (
Address &&
Load->isAtomic() <= DepSI->isAtomic()) {
1395 Load->isAtomic() <= DepLoad->isAtomic()) {
1402 DepLoad->getFunction())) {
1403 const auto ClobberOff = MD->getClobberOffset(DepLoad);
1405 Offset = (ClobberOff == std::nullopt || *ClobberOff < 0)
1411 DepLoad->getFunction()) ||
1438 dbgs() <<
" is clobbered by " << *DepInst <<
'\n';);
1442 return std::nullopt;
1444 assert(Dep.Kind == DepKind::Def &&
"follows from above");
1451 if (Constant *InitVal =
1461 return std::nullopt;
1464 if (S->isAtomic() <
Load->isAtomic())
1465 return std::nullopt;
1476 return std::nullopt;
1479 if (
LD->isAtomic() <
Load->isAtomic())
1480 return std::nullopt;
1489 assert(Sel->getType() ==
Load->getPointerOperandType());
1490 if (
auto AV = analyzeSelectAvailability(
Load, Sel->getCondition(),
1491 Sel->getTrueValue(),
1492 Sel->getFalseValue(), DepInst))
1494 return std::nullopt;
1501 dbgs() <<
" has unknown def " << *DepInst <<
'\n';);
1502 return std::nullopt;
1505void GVNPass::analyzeLoadAvailability(LoadInst *
Load,
1506 SmallVectorImpl<ReachingMemVal> &Deps,
1507 AvailValInBlkVect &ValuesPerBlock,
1508 UnavailBlkVect &UnavailableBlocks) {
1513 for (
const auto &Dep : Deps) {
1516 if (DeadBlocks.count(DepBB)) {
1523 if (Dep.Kind == DepKind::Other) {
1524 UnavailableBlocks.push_back(DepBB);
1531 if (Dep.Kind == DepKind::Select) {
1532 if (
auto AV = analyzeSelectAvailability(
1534 const_cast<Value *
>(Dep.SelTrueAddr),
1536 ValuesPerBlock.push_back(
1539 UnavailableBlocks.push_back(DepBB);
1548 analyzeLoadAvailability(
Load, Dep,
const_cast<Value *
>(Dep.Addr))) {
1552 ValuesPerBlock.push_back(
1555 UnavailableBlocks.push_back(DepBB);
1559 assert(Deps.size() == ValuesPerBlock.size() + UnavailableBlocks.size() &&
1560 "post condition violation");
1582LoadInst *GVNPass::findLoadToHoistIntoPred(BasicBlock *Pred, BasicBlock *LoadBB,
1586 if (
Term->getNumSuccessors() != 2 ||
Term->isSpecialTerminator())
1588 auto *SuccBB =
Term->getSuccessor(0);
1589 if (SuccBB == LoadBB)
1590 SuccBB =
Term->getSuccessor(1);
1591 if (!SuccBB->getSinglePredecessor())
1595 for (Instruction &Inst : *SuccBB) {
1596 if (Inst.isDebugOrPseudoInst())
1598 if (--NumInsts == 0)
1601 if (!Inst.isIdenticalTo(
Load))
1604 bool HasLocalDep =
true;
1606 MemDepResult Dep = MD->getDependency(&Inst);
1609 auto *MSSA = MSSAU->getMemorySSA();
1611 if (
auto *MA = MSSA->getMemoryAccess(&Inst); MA &&
isa<MemoryUse>(MA)) {
1612 auto *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(MA);
1613 HasLocalDep = Clobber->getBlock() == SuccBB;
1621 if (!HasLocalDep && !ICF->isDominatedByICFIFromSameBlock(&Inst))
1632void GVNPass::eliminatePartiallyRedundantLoad(
1633 LoadInst *
Load, AvailValInBlkVect &ValuesPerBlock,
1634 MapVector<BasicBlock *, Value *> &AvailableLoads,
1635 MapVector<BasicBlock *, LoadInst *> *CriticalEdgePredAndLoad) {
1636 for (
const auto &AvailableLoad : AvailableLoads) {
1637 BasicBlock *UnavailableBlock = AvailableLoad.first;
1638 Value *LoadPtr = AvailableLoad.second;
1641 new LoadInst(
Load->getType(), LoadPtr,
Load->getName() +
".pre",
1642 Load->getProperties(),
1644 NewLoad->setDebugLoc(
Load->getDebugLoc());
1646 auto *NewAccess = MSSAU->createMemoryAccessInBB(
1649 MSSAU->insertDef(NewDef,
true);
1655 AAMDNodes Tags =
Load->getAAMetadata();
1657 NewLoad->setAAMetadata(Tags);
1659 if (
auto *MD =
Load->getMetadata(LLVMContext::MD_invariant_load))
1660 NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
1661 if (
auto *InvGroupMD =
Load->getMetadata(LLVMContext::MD_invariant_group))
1662 NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
1663 if (
auto *RangeMD =
Load->getMetadata(LLVMContext::MD_range))
1664 NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
1665 if (
auto *NoFPClassMD =
Load->getMetadata(LLVMContext::MD_nofpclass))
1666 NewLoad->setMetadata(LLVMContext::MD_nofpclass, NoFPClassMD);
1668 if (
auto *AccessMD =
Load->getMetadata(LLVMContext::MD_access_group))
1669 if (LI->getLoopFor(
Load->getParent()) == LI->getLoopFor(UnavailableBlock))
1670 NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
1679 ValuesPerBlock.push_back(
1682 MD->invalidateCachedPointerInfo(LoadPtr);
1687 if (CriticalEdgePredAndLoad) {
1688 auto It = CriticalEdgePredAndLoad->
find(UnavailableBlock);
1689 if (It != CriticalEdgePredAndLoad->
end()) {
1690 ++NumPRELoadMoved2CEPred;
1691 ICF->insertInstructionTo(NewLoad, UnavailableBlock);
1692 LoadInst *OldLoad = It->second;
1696 if (uint32_t ValNo = VN.lookup(OldLoad,
false))
1697 LeaderTable.erase(ValNo, OldLoad, OldLoad->
getParent());
1698 removeInstruction(OldLoad);
1706 ICF->removeUsersOf(
Load);
1707 Load->replaceAllUsesWith(V);
1711 I->setDebugLoc(
Load->getDebugLoc());
1712 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
1713 MD->invalidateCachedPointerInfo(V);
1716 <<
"load eliminated by PRE";
1721bool GVNPass::performLoadPRE(LoadInst *
Load, AvailValInBlkVect &ValuesPerBlock,
1722 UnavailBlkVect &UnavailableBlocks) {
1731 SmallPtrSet<BasicBlock *, 4> Blockers(
llvm::from_range, UnavailableBlocks);
1753 bool MustEnsureSafetyOfSpeculativeExecution =
1754 ICF->isDominatedByICFIFromSameBlock(
Load);
1758 if (TmpBB == LoadBB)
1760 if (Blockers.count(TmpBB))
1772 MustEnsureSafetyOfSpeculativeExecution =
1773 MustEnsureSafetyOfSpeculativeExecution || ICF->hasICF(TmpBB);
1781 MapVector<BasicBlock *, Value *> PredLoads;
1782 DenseMap<BasicBlock *, AvailabilityState> FullyAvailableBlocks;
1785 for (BasicBlock *UnavailableBB : UnavailableBlocks)
1793 MapVector<BasicBlock *, LoadInst *> CriticalEdgePredAndLoad;
1799 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
1811 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
1818 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
1825 if (DT->dominates(LoadBB, Pred)) {
1828 <<
"COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
1833 if (LoadInst *LI = findLoadToHoistIntoPred(Pred, LoadBB,
Load))
1834 CriticalEdgePredAndLoad[Pred] = LI;
1839 PredLoads[Pred] =
nullptr;
1844 unsigned NumInsertPreds = PredLoads.
size() + CriticalEdgePredSplit.
size();
1845 unsigned NumUnavailablePreds = NumInsertPreds +
1846 CriticalEdgePredAndLoad.
size();
1847 assert(NumUnavailablePreds != 0 &&
1848 "Fully available value should already be eliminated!");
1849 (void)NumUnavailablePreds;
1855 if (NumInsertPreds > 1)
1860 if (MustEnsureSafetyOfSpeculativeExecution) {
1861 if (CriticalEdgePredSplit.
size())
1865 for (
auto &PL : PredLoads)
1869 for (
auto &CEP : CriticalEdgePredAndLoad)
1876 for (BasicBlock *OrigPred : CriticalEdgePredSplit) {
1877 BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
1878 assert(!PredLoads.count(OrigPred) &&
"Split edges shouldn't be in map!");
1879 PredLoads[NewPred] =
nullptr;
1880 LLVM_DEBUG(
dbgs() <<
"Split critical edge " << OrigPred->getName() <<
"->"
1881 << LoadBB->
getName() <<
'\n');
1884 for (
auto &CEP : CriticalEdgePredAndLoad)
1885 PredLoads[CEP.first] =
nullptr;
1888 bool CanDoPRE =
true;
1889 const DataLayout &
DL =
Load->getDataLayout();
1890 SmallVector<Instruction*, 8> NewInsts;
1891 for (
auto &PredLoad : PredLoads) {
1892 BasicBlock *UnavailablePred = PredLoad.first;
1902 Value *LoadPtr =
Load->getPointerOperand();
1904 while (Cur != LoadBB) {
1917 LoadPtr =
Address.translateWithInsertion(LoadBB, UnavailablePred, *DT,
1924 << *
Load->getPointerOperand() <<
"\n");
1929 PredLoad.second = LoadPtr;
1933 while (!NewInsts.
empty()) {
1943 return !CriticalEdgePredSplit.empty();
1951 <<
" INSTS: " << *NewInsts.
back()
1955 for (Instruction *
I : NewInsts) {
1959 I->updateLocationAfterHoist();
1968 eliminatePartiallyRedundantLoad(
Load, ValuesPerBlock, PredLoads,
1969 &CriticalEdgePredAndLoad);
1974bool GVNPass::performLoopLoadPRE(LoadInst *
Load,
1975 AvailValInBlkVect &ValuesPerBlock,
1976 UnavailBlkVect &UnavailableBlocks) {
1977 const Loop *
L = LI->getLoopFor(
Load->getParent());
1979 if (!L ||
L->getHeader() !=
Load->getParent())
1984 if (!Preheader || !Latch)
1987 Value *LoadPtr =
Load->getPointerOperand();
1989 if (!
L->isLoopInvariant(LoadPtr))
1995 if (ICF->isDominatedByICFIFromSameBlock(
Load))
1999 for (
auto *Blocker : UnavailableBlocks) {
2001 if (!
L->contains(Blocker))
2013 if (L != LI->getLoopFor(Blocker))
2021 if (DT->dominates(Blocker, Latch))
2025 if (Blocker->getTerminator()->mayWriteToMemory())
2028 LoopBlock = Blocker;
2040 MapVector<BasicBlock *, Value *> AvailableLoads;
2041 AvailableLoads[LoopBlock] = LoadPtr;
2042 AvailableLoads[Preheader] = LoadPtr;
2045 eliminatePartiallyRedundantLoad(
Load, ValuesPerBlock, AvailableLoads,
2053 using namespace ore;
2057 <<
"load of type " << NV(
"Type",
Load->getType()) <<
" eliminated"
2058 << setExtraArgs() <<
" in favor of "
2065bool GVNPass::processNonLocalLoad(LoadInst *
Load) {
2067 if (
Load->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2068 Load->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2073 MD->getNonLocalPointerDependency(
Load, Deps);
2078 unsigned NumDeps = Deps.size();
2085 for (
const NonLocalDepResult &Dep : Deps) {
2086 const auto &
R = Dep.getResult();
2087 SelectAddr SelAddr = Dep.getAddress();
2093 ReachingMemVal::getSelect(BB,
Cond, Addrs.first, Addrs.second));
2105 return processNonLocalLoad(
Load, MemVals);
2108bool GVNPass::processNonLocalLoad(LoadInst *
Load,
2109 SmallVectorImpl<ReachingMemVal> &Deps) {
2112 if (Deps.
size() == 1 && Deps[0].Kind == DepKind::Other) {
2114 dbgs() <<
" has unknown dependencies\n";);
2122 if (GetElementPtrInst *
GEP =
2124 for (Use &U :
GEP->indices())
2134 AvailValInBlkVect ValuesPerBlock;
2135 UnavailBlkVect UnavailableBlocks;
2136 analyzeLoadAvailability(
Load, Deps, ValuesPerBlock, UnavailableBlocks);
2140 if (ValuesPerBlock.empty())
2148 if (UnavailableBlocks.empty()) {
2154 ICF->removeUsersOf(
Load);
2155 Load->replaceAllUsesWith(V);
2163 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2164 I->setDebugLoc(
Load->getDebugLoc());
2165 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2166 MD->invalidateCachedPointerInfo(V);
2179 if (performLoopLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks) ||
2180 performLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks))
2186bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2190 if (
Cond->isZero()) {
2200 const MemoryUseOrDef *FirstNonDom =
nullptr;
2202 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2209 for (
const auto &Acc : *AL) {
2211 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2212 FirstNonDom = Current;
2219 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2221 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2222 : MSSAU->createMemoryAccessInBB(
2244 return propagateEquality(V, True, IntrinsicI);
2249 I->replaceAllUsesWith(Repl);
2256 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2267 PointerUsesQueue.
push_back(PointerOperand);
2272 while (!PointerUsesQueue.
empty()) {
2275 "Null or GlobalValue should not be inserted");
2279 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2294 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2296 MostDominatingInstruction =
I;
2300 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2306static std::optional<MemoryLocation>
2313 switch (
II->getIntrinsicID()) {
2314 case Intrinsic::masked_load:
2316 case Intrinsic::masked_store:
2319 return std::nullopt;
2326 return std::nullopt;
2330 return std::nullopt;
2336std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2337 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2338 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2339 BatchAAResults &AA, LoadInst *L) {
2342 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2346 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2348 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2356 Choice->Kind = DepKind::Clobber;
2357 Choice->Offset = AR.getOffset();
2359 Choice->Kind = DepKind::Def;
2360 Choice->Offset = -1;
2363 Choice->Inst = Candidate;
2364 Choice->Block = Candidate->getParent();
2367 std::optional<ReachingMemVal> ReachingVal;
2368 for (MemoryAccess *MA : ClobbersList) {
2370 for (User *U : MA->
users()) {
2372 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2375 if (!UseOrDef || UseOrDef->getBlock() != BB)
2384 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2398 UpdateChoice(ReachingVal, AR, MemI);
2410std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2411 MemoryAccess *ClobberMA,
const MemoryLocation &Loc,
bool IsInvariantLoad,
2412 BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2420 if (
Alloc->getParent() == BB)
2421 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2422 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2426 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2427 return std::nullopt;
2431 return L->getOrdering();
2438 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2440 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2451 return std::nullopt;
2452 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2457 return std::nullopt;
2462 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2467 "Must be the superset/partial overlap case with positive offset");
2468 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2473 return std::nullopt;
2474 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2476 if (AA.isMustAlias(IIObjLoc, Loc))
2477 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2478 return std::nullopt;
2486 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2487 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2493 return std::nullopt;
2497 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2501 return std::nullopt;
2505 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2511bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2512 MemoryAccess *ClobberMA,
2513 DependencyBlockSet &Blocks,
2514 SmallVectorImpl<BasicBlock *> &Worklist) {
2524 if (!DT->isReachableFromEntry(Pred))
2528 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2531 PHITransAddr TransAddr = Addr;
2535 auto It = Blocks.find(Pred);
2536 if (It != Blocks.end()) {
2540 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2547 Pred, DependencyBlockInfo(TransAddr,
2548 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2555 for (
auto &
P : Preds) {
2556 [[maybe_unused]]
auto It =
2557 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2569void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2571 const DependencyBlockInfo &StartInfo,
2572 const DependencyBlockSet &Blocks,
2574 MemoryAccess *MA = StartInfo.InitialClobberMA;
2575 MemoryAccess *LastMA = StartInfo.ClobberMA;
2578 while (MA != LastMA) {
2592 BB = DT->getNode(BB)->getIDom()->getBlock();
2596 auto It = Blocks.find(BB);
2597 if (It == Blocks.end())
2600 MA = It->second.InitialClobberMA;
2601 LastMA = It->second.ClobberMA;
2602 if (MA == Clobbers.
back())
2619bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2620 SmallVectorImpl<ReachingMemVal> &
Values,
2622 EarliestEscapeAnalysis EA(*DT, LI);
2623 BatchAAResults AA(AAR, &EA);
2625 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2631 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2644 if (
auto RMV = scanMemoryAccessesUsers(
2645 Loc, IsInvariantLoad, StartBlock,
2647 Values.emplace_back(*RMV);
2657 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2658 StartBlock, MSSA, AA)) {
2659 Values.emplace_back(*RMV);
2666 }
while (ClobberMA->
getBlock() == StartBlock);
2669 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2670 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2679 DependencyBlockSet Blocks;
2680 SmallVector<BasicBlock *, 16> InitialWorklist;
2681 const DataLayout &
DL =
L->getModule()->getDataLayout();
2682 if (!collectPredecessors(StartBlock,
2683 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2684 ClobberMA, Blocks, InitialWorklist))
2688 auto Worklist = InitialWorklist;
2689 while (!Worklist.
empty()) {
2694 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2697 if (!
Info.Addr.getAddr())
2705 if (
auto RMV = accessMayModifyLocation(
2707 IsInvariantLoad, BB, MSSA, AA)) {
2712 "LiveOnEntry aliases everything");
2728 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2729 Info.ForceUnknown =
true;
2732 if (BB != StartBlock &&
2733 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2734 Info.ForceUnknown =
true;
2744 Worklist = InitialWorklist;
2745 for (BasicBlock *BB : Worklist) {
2746 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2747 Info.Visited =
true;
2751 while (!Worklist.empty()) {
2752 auto *BB = Worklist.pop_back_val();
2753 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2757 if (!
Info.Addr.getAddr()) {
2758 Values.push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2763 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2766 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2778 if (
Info.ForceUnknown) {
2779 Values.push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2785 auto It = Blocks.find(Pred);
2786 if (It == Blocks.end())
2788 DependencyBlockInfo &PredInfo = It->second;
2789 if (PredInfo.Visited)
2791 PredInfo.Visited =
true;
2792 Worklist.push_back(Pred);
2801bool GVNPass::processLoad(LoadInst *L) {
2806 if (!
L->isUnordered())
2809 if (
L->getType()->isTokenLikeTy())
2812 if (
L->use_empty()) {
2817 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2820 MemDepResult Dep = MD->getDependency(L);
2824 return processNonLocalLoad(L);
2828 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2831 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2834 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2836 assert(MemVals.
size() &&
"Expected at least an unknown value");
2837 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2838 return processNonLocalLoad(L, MemVals);
2840 MemVal = MemVals[0];
2843 if (MemVal.Kind == DepKind::Other) {
2847 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2848 dbgs() <<
" has unknown dependence\n";);
2852 auto AV = analyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2859 ICF->removeUsersOf(L);
2862 MSSAU->removeMemoryAccess(L);
2875bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2878 MemDepResult Dep = MD->getDependency(
I);
2884 Value *Passthrough =
I->getOperand(2);
2888 StoreVal->
getType() !=
I->getType())
2895 ICF->removeUsersOf(
I);
2896 I->replaceAllUsesWith(OpToForward);
2904std::pair<uint32_t, bool>
2905GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2906 uint32_t &
E = ExpressionNumbering[
Exp];
2907 bool CreateNewValNum = !
E;
2908 if (CreateNewValNum) {
2909 Expressions.push_back(Exp);
2910 if (ExprIdx.size() < NextValueNumber + 1)
2911 ExprIdx.resize(NextValueNumber * 2);
2912 E = NextValueNumber;
2913 ExprIdx[NextValueNumber++] = NextExprNumber++;
2915 return {
E, CreateNewValNum};
2920bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2923 GVN.LeaderTable.getLeaders(Num),
2931 auto FindRes = PhiTranslateTable.find({Num, Pred});
2932 if (FindRes != PhiTranslateTable.end())
2933 return FindRes->second;
2934 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2935 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2946 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2947 for (
const auto &Entry : Leaders) {
2949 if (
Call &&
Call->getParent() == PhiBlock)
2953 if (
AA->doesNotAccessMemory(
Call))
2956 if (!MD || !
AA->onlyReadsMemory(
Call))
2968 if (
D.getResult().isNonFuncLocal())
2976uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2977 const BasicBlock *PhiBlock,
2981 if (PHINode *PN = NumberingPhi[Num]) {
2982 if (PN->getParent() != PhiBlock)
2984 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2985 if (PN->getIncomingBlock(
I) != Pred)
2987 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2993 if (BasicBlock *BB = NumberingBB[Num]) {
2994 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
3006 return lookupOrAdd(PredPhi->getBlock());
3012 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
3018 if (!areAllValsInBB(Num, PhiBlock, GVN))
3021 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
3025 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
3029 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
3030 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
3031 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
3033 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
3036 if (
Exp.Commutative) {
3037 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
3038 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
3040 uint32_t Opcode =
Exp.Opcode >> 8;
3041 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
3042 Exp.Opcode = (Opcode << 8) |
3048 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
3049 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
3050 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3058void GVNPass::ValueTable::eraseTranslateCacheEntry(
3061 PhiTranslateTable.erase({Num, Pred});
3070 auto Leaders = LeaderTable.getLeaders(Num);
3071 if (Leaders.empty())
3074 Value *Val =
nullptr;
3075 for (
const auto &Entry : Leaders) {
3076 if (DT->dominates(Entry.BB, BB)) {
3096 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3097 assert((!Pred || Pred ==
E.getStart()) &&
3098 "No edge between these basic blocks!");
3099 return Pred !=
nullptr;
3102void GVNPass::assignBlockRPONumber(
Function &
F) {
3103 BlockRPONumber.clear();
3104 uint32_t NextBlockNumber = 1;
3105 ReversePostOrderTraversal<Function *> RPOT(&
F);
3106 for (BasicBlock *BB : RPOT)
3107 BlockRPONumber[BB] = NextBlockNumber++;
3108 InvalidBlockRPONumbers =
false;
3116bool GVNPass::propagateEquality(
3118 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3120 SmallDenseSet<std::pair<Value *, Value *>, 4> Visited;
3124 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3131 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3135 while (!Worklist.
empty()) {
3136 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3137 LHS = Item.first;
RHS = Item.second;
3151 const DataLayout &
DL =
3160 uint32_t LVN = VN.lookupOrAdd(
LHS);
3165 uint32_t RVN = VN.lookupOrAdd(
RHS);
3172 if (!Visited.
insert({LHS, RHS}).second)
3185 for (
const BasicBlock *BB : DominatedBlocks)
3186 LeaderTable.insert(LVN,
RHS, BB);
3193 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3196 unsigned NumReplacements;
3197 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3199 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3202 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3203 CanReplacePointersCallBack);
3205 if (NumReplacements > 0) {
3207 NumGVNEqProp += NumReplacements;
3210 MD->invalidateCachedPointerInfo(
LHS);
3227 bool IsKnownFalse = !IsKnownTrue;
3243 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3248 if (
Cmp->isEquivalence(IsKnownFalse))
3249 Worklist.
push_back(std::make_pair(Op0, Op1));
3253 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3257 uint32_t NextNum = VN.getNextUnusedValueNumber();
3258 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3261 if (Num < NextNum) {
3262 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3267 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3268 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3269 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3272 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3273 if (!DT->dominates(
Entry.BB, InstBB) &&
3274 !DT->dominates(InstBB,
Entry.BB))
3280 unsigned NumReplacements;
3281 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3286 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3287 Changed |= NumReplacements > 0;
3288 NumGVNEqProp += NumReplacements;
3291 MD->invalidateCachedPointerInfo(NotCmp);
3299 for (
const BasicBlock *BB : DominatedBlocks)
3300 LeaderTable.insert(Num, NotVal, BB);
3309 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3314 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3324bool GVNPass::processInstruction(Instruction *
I) {
3329 const DataLayout &
DL =
I->getDataLayout();
3332 if (!
I->use_empty()) {
3335 ICF->removeUsersOf(
I);
3336 I->replaceAllUsesWith(V);
3344 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3345 MD->invalidateCachedPointerInfo(V);
3352 return processAssumeIntrinsic(Assume);
3355 if (processLoad(
Load))
3358 unsigned Num = VN.lookupOrAdd(
Load);
3359 LeaderTable.insert(Num,
Load,
Load->getParent());
3371 return processFoldableCondBr(BI);
3373 Value *BranchCond = BI->getCondition();
3377 if (TrueSucc == FalseSucc)
3384 BasicBlockEdge TrueE(Parent, TrueSucc);
3385 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3388 BasicBlockEdge FalseE(Parent, FalseSucc);
3389 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3396 Value *SwitchCond =
SI->getCondition();
3401 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3403 ++SwitchEdges[Succ];
3405 for (
const auto &Case :
SI->cases()) {
3408 if (SwitchEdges.
lookup(Dst) == 1) {
3409 BasicBlockEdge
E(Parent, Dst);
3410 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3418 if (
I->getType()->isVoidTy())
3421 uint32_t NextNum = VN.getNextUnusedValueNumber();
3422 unsigned Num = VN.lookupOrAdd(
I);
3427 LeaderTable.insert(Num,
I,
I->getParent());
3434 const DataLayout &
DL =
I->getDataLayout();
3435 unsigned AS = PTA->getPointerAddressSpace();
3436 if (
DL.getAddressSizeInBits(AS) ==
DL.getPointerSizeInBits(AS) &&
3437 !
DL.hasUnstableRepresentation(AS)) {
3439 VN.lookupPtrToInt(PTA->getPointerOperand(), PTA->getType());
3440 if (
Value *PTI = findLeader(
I->getParent(), PTINum)) {
3451 if (Num >= NextNum) {
3452 LeaderTable.insert(Num,
I,
I->getParent());
3458 Value *Repl = findLeader(
I->getParent(), Num);
3461 LeaderTable.insert(Num,
I,
I->getParent());
3474 MD->invalidateCachedPointerInfo(Repl);
3480bool GVNPass::runImpl(
Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3481 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3482 MemoryDependenceResults *RunMD, LoopInfo &LI,
3483 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3491 "mutually exclusive",
3498 VN.setAliasAnalysis(&RunAA);
3500 ImplicitControlFlowTracking ImplicitCFT;
3509 InvalidBlockRPONumbers =
true;
3510 MemorySSAUpdater Updater(MSSA);
3511 MSSAU = MSSA ? &Updater :
nullptr;
3514 bool ShouldContinue =
true;
3516 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3528 unsigned Iteration = 0;
3529 while (ShouldContinue) {
3532 ShouldContinue = iterateOnFunction(
F);
3540 assignValNumForDeadCode();
3541 bool PREChanged =
true;
3542 while (PREChanged) {
3543 PREChanged = performPRE(
F);
3553 cleanupGlobalSets();
3564bool GVNPass::processBlock(BasicBlock *BB) {
3565 if (DeadBlocks.count(BB))
3568 bool ChangedFunction =
false;
3574 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3576 for (PHINode *PN : PHINodesToRemove) {
3577 removeInstruction(PN);
3580 ChangedFunction |= processInstruction(&Inst);
3581 return ChangedFunction;
3585bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3586 BasicBlock *Curr,
unsigned int ValNo) {
3592 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3600 if (!VN.exists(
Op)) {
3605 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3606 if (
Value *V = findLeader(Pred, TValNo)) {
3624 ICF->insertInstructionTo(Instr, Pred);
3626 unsigned Num = VN.lookupOrAdd(Instr);
3630 LeaderTable.insert(Num, Instr, Pred);
3634bool GVNPass::performScalarPRE(Instruction *CurInst) {
3660 if (CallB->isInlineAsm())
3664 uint32_t ValNo = VN.lookup(CurInst);
3672 unsigned NumWith = 0;
3673 unsigned NumWithout = 0;
3678 if (InvalidBlockRPONumbers)
3679 assignBlockRPONumber(*CurrentBlock->
getParent());
3685 if (!DT->isReachableFromEntry(
P)) {
3690 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3691 "Invalid BlockRPONumber map.");
3692 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3697 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3698 Value *PredV = findLeader(
P, TValNo);
3703 }
else if (PredV == CurInst) {
3715 if (NumWithout > 1 || NumWith == 0)
3723 if (NumWithout != 0) {
3729 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3742 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3746 PREInstr = CurInst->
clone();
3747 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3750 verifyRemoved(PREInstr);
3759 assert(PREInstr !=
nullptr || NumWithout == 0);
3765 CurInst->
getName() +
".pre-phi");
3766 Phi->insertBefore(CurrentBlock->begin());
3767 for (
auto &[V, BB] : PredMap) {
3772 Phi->addIncoming(V, BB);
3774 Phi->addIncoming(PREInstr, PREPred);
3780 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3781 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3784 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3785 MD->invalidateCachedPointerInfo(Phi);
3786 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3789 removeInstruction(CurInst);
3798 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3800 if (CurrentBlock == &
F.getEntryBlock())
3804 if (CurrentBlock->isEHPad())
3808 BE = CurrentBlock->end();
3811 Changed |= performScalarPRE(CurInst);
3815 if (splitCriticalEdges())
3823BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3828 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3831 MD->invalidateCachedPredecessors();
3832 InvalidBlockRPONumbers =
true;
3839bool GVNPass::splitCriticalEdges() {
3840 if (ToSplit.empty())
3845 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3847 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3849 }
while (!ToSplit.empty());
3852 MD->invalidateCachedPredecessors();
3853 InvalidBlockRPONumbers =
true;
3859bool GVNPass::iterateOnFunction(
Function &
F) {
3860 cleanupGlobalSets();
3867 ReversePostOrderTraversal<Function *> RPOT(&
F);
3869 for (BasicBlock *BB : RPOT)
3875void GVNPass::cleanupGlobalSets() {
3877 LeaderTable.clear();
3878 BlockRPONumber.clear();
3880 InvalidBlockRPONumbers =
true;
3883void GVNPass::removeInstruction(Instruction *
I) {
3885 if (MD) MD->removeInstruction(
I);
3887 MSSAU->removeMemoryAccess(
I);
3891 ICF->removeInstruction(
I);
3892 I->eraseFromParent();
3898void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3899 VN.verifyRemoved(Inst);
3906void GVNPass::addDeadBlock(BasicBlock *BB) {
3908 SmallSetVector<BasicBlock *, 4>
DF;
3911 while (!NewDead.
empty()) {
3913 if (DeadBlocks.count(
D))
3917 SmallVector<BasicBlock *, 8> Dom;
3918 DT->getDescendants(
D, Dom);
3919 DeadBlocks.insert_range(Dom);
3922 for (BasicBlock *
B : Dom) {
3924 if (DeadBlocks.count(S))
3927 bool AllPredDead =
true;
3929 if (!DeadBlocks.count(
P)) {
3930 AllPredDead =
false;
3950 for (BasicBlock *
B :
DF) {
3951 if (DeadBlocks.count(
B))
3957 for (BasicBlock *
P : Preds) {
3958 if (!DeadBlocks.count(
P))
3963 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3964 DeadBlocks.insert(
P = S);
3970 if (!DeadBlocks.count(
P))
3972 for (PHINode &Phi :
B->phis()) {
3975 MD->invalidateCachedPointerInfo(&Phi);
3994bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
4005 if (DeadBlocks.count(DeadRoot))
4009 DeadRoot = splitCriticalEdges(BI->
getParent(), DeadRoot);
4011 addDeadBlock(DeadRoot);
4019void GVNPass::assignValNumForDeadCode() {
4020 for (BasicBlock *BB : DeadBlocks) {
4021 for (Instruction &Inst : *BB) {
4022 unsigned ValNum = VN.lookupOrAdd(&Inst);
4023 LeaderTable.insert(ValNum, &Inst, BB);
4034 bool ScalarPRE =
true)
4036 .setMemDep(MemDepAnalysis)
4037 .setMemorySSA(MemSSAAnalysis)
4038 .setScalarPRE(ScalarPRE)) {
4047 if (Impl.isMemorySSAEnabled() && !MSSAWP)
4050 return Impl.runImpl(
4055 Impl.isMemDepEnabled()
4060 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
4068 if (Impl.isMemDepEnabled())
4077 if (Impl.isMemorySSAEnabled())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
early cse Early CSE w MemorySSA
static void reportMayClobberedLoad(LoadInst *Load, Instruction *DepInst, const DominatorTree *DT, OptimizationRemarkEmitter *ORE)
Try to locate the three instruction involved in a missed load-elimination case that is due to an inte...
static bool isValueFullyAvailableInBlock(BasicBlock *BB, DenseMap< BasicBlock *, AvailabilityState > &FullyAvailableBlocks)
Return true if we can prove that the value we're analyzing is fully available in the specified block.
static Instruction * findInvariantGroupValue(LoadInst *L, DominatorTree &DT)
If a load has !invariant.group, try to find the most-dominating instruction with the same metadata an...
static void reportLoadElim(LoadInst *Load, Value *AvailableValue, OptimizationRemarkEmitter *ORE)
GVNPass::AvailableValue AvailableValue
static cl::opt< uint32_t > MaxNumInsnsPerBlock("gvn-max-num-insns", cl::Hidden, cl::init(100), cl::desc("Max number of instructions to scan in each basic block in GVN " "(default = 100)"))
static cl::opt< bool > GVNEnableMemDep("enable-gvn-memdep", cl::init(true))
static cl::opt< bool > GVNEnableLoadInLoopPRE("enable-load-in-loop-pre", cl::init(true))
static const Instruction * findMayClobberedPtrAccess(LoadInst *Load, const DominatorTree *DT)
static cl::opt< uint32_t > MaxNumDeps("gvn-max-num-deps", cl::Hidden, cl::init(100), cl::desc("Max number of dependences to attempt Load PRE (default = 100)"))
static std::optional< MemoryLocation > maybeLoadStoreLocation(Instruction *I, bool AllowStores, const TargetLibraryInfo *TLI)
Return the memory location accessed by the (masked) load/store instruction I, if the instruction coul...
static cl::opt< uint32_t > MaxNumReachingBlocks("gvn-max-num-reaching-blocks", cl::Hidden, cl::init(200), cl::desc("Max number of blocks scanned per load in the MemorySSA " "reaching-value analysis (default = 200)"))
static cl::opt< bool > GVNEnableMemorySSA("enable-gvn-memoryssa", cl::init(false))
static bool isOnlyReachableViaThisEdge(const BasicBlockEdge &E, DominatorTree *DT)
There is an edge from 'Src' to 'Dst'.
static cl::opt< bool > GVNEnableScalarPRE("enable-scalar-pre", cl::init(true), cl::Hidden)
static Value * findDominatingValue(const MemoryLocation &Loc, Type *LoadTy, Instruction *From, AAResults *AA)
static bool liesBetween(const Instruction *From, Instruction *Between, const Instruction *To, const DominatorTree *DT)
Assuming To can be reached from both From and Between, does Between lie on every path from From to To...
static bool isLifetimeStart(const Instruction *Inst)
static cl::opt< bool > GVNEnableSplitBackedgeInLoadPRE("enable-split-backedge-in-load-pre", cl::init(false))
static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl)
static void replaceValuesPerBlockEntry(SmallVectorImpl< AvailableValueInBlock > &ValuesPerBlock, Value *OldValue, Value *NewValue)
If the specified OldValue exists in ValuesPerBlock, replace its value with NewValue.
static cl::opt< unsigned > ScanUsersLimit("gvn-scan-users-limit", cl::Hidden, cl::init(100), cl::desc("The number of memory accesses to scan in a block in reaching " "memory values analysis (default = 100)"))
@ Unavailable
We know the block is not fully available. This is a fixpoint.
@ Available
We know the block is fully available. This is a fixpoint.
@ SpeculativelyAvailable
We do not know whether the block is fully available or not, but we are currently speculating that it ...
static cl::opt< uint32_t > MaxNumVisitedInsts("gvn-max-num-visited-insts", cl::Hidden, cl::init(100), cl::desc("Max number of visited instructions when trying to find " "dominating value of select dependency (default = 100)"))
static cl::opt< uint32_t > MaxBBSpeculations("gvn-max-block-speculations", cl::Hidden, cl::init(600), cl::desc("Max number of blocks we're willing to speculate on (and recurse " "into) when deducing if a value is fully available or not in GVN " "(default = 600)"))
static cl::opt< bool > GVNEnableLoadPRE("enable-load-pre", cl::init(true))
GVNPass::AvailableValueInBlock AvailableValueInBlock
static Value * constructSSAForLoadSet(LoadInst *Load, SmallVectorImpl< AvailableValueInBlock > &ValuesPerBlock, GVNPass &GVN)
Given a set of loads specified by ValuesPerBlock, construct SSA form, allowing us to eliminate Load.
This file provides the interface for LLVM's Global Value Numbering pass which eliminates fully redund...
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static bool lookup(const GsymReader &GR, GsymDataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
This file implements a map that provides insertion order iteration.
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
uint64_t IntrinsicInst * II
ppc ctr loops PowerPC CTR Loops Verify
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
static DominatorTree getDomTree(Function &F)
std::pair< BasicBlock *, BasicBlock * > Edge
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static const uint32_t IV[8]
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
constexpr int32_t getOffset() const
constexpr bool hasOffset() const
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
bool isEHPad() const
Return true if this basic block is an exception handling block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
LLVM_ABI Instruction::BinaryOps getBinaryOp() const
Returns the binary operation underlying the intrinsic.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Analysis pass which computes a DominatorTree.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class representing an expression and its matching format.
FunctionPass class - This class is used to implement most global optimizations.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
const BasicBlock & getEntryBlock() const
Represents calls to the gc.relocate intrinsic.
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
GVNLegacyPass(bool MemDepAnalysis=GVNEnableMemDep, bool MemSSAAnalysis=GVNEnableMemorySSA, bool ScalarPRE=true)
This class holds the mapping between values and value numbers.
LLVM_ABI uint32_t lookupOrAdd(MemoryAccess *MA)
The core GVN pass object.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI void salvageAndRemoveInstruction(Instruction *I)
This removes the specified instruction from our various maps and marks it for deletion.
AAResults * getAliasAnalysis() const
LLVM_ABI bool isLoadPREEnabled() const
GVNPass(GVNOptions Options={})
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI bool isMemorySSAEnabled() const
DominatorTree & getDominatorTree() const
LLVM_ABI bool isLoadInLoopPREEnabled() const
LLVM_ABI bool isScalarPREEnabled() const
LLVM_ABI bool isLoadPRESplitBackedgeEnabled() const
friend class GVNLegacyPass
LLVM_ABI bool isMemDepEnabled() const
Legacy wrapper pass to provide the GlobalsAAResult object.
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
LLVM_ABI void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})
Drop all unknown metadata except for debug locations.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
The legacy pass manager's analysis pass to compute loop information.
iterator find(const KeyT &Key)
A memory dependence query can return one of three different answers.
bool isClobber() const
Tests if this MemDepResult represents a query that is an instruction clobber dependency.
bool isNonLocal() const
Tests if this MemDepResult represents a query that is transparent to the start of the block,...
bool isDef() const
Tests if this MemDepResult represents a query that is an instruction definition dependency.
bool isLocal() const
Tests if this MemDepResult represents a valid local query (Clobber/Def).
Instruction * getInst() const
If this is a normal dependency, returns the instruction that is depended on.
This is the common base class for memset/memcpy/memmove.
BasicBlock * getBlock() const
An analysis that produces MemoryDependenceResults for a function.
std::vector< NonLocalDepEntry > NonLocalDepInfo
LLVM_ABI MemDepResult getDependency(Instruction *QueryInst)
Returns the instruction on which a memory operation depends.
LLVM_ABI const NonLocalDepInfo & getNonLocalCallDependency(CallBase *QueryCall)
Perform a full dependency query for the specified call, returning the set of blocks that the value is...
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
MemoryLocation getWithNewPtr(const Value *NewPtr) const
const Value * Ptr
The address of the start of the location.
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
BasicBlock * getIncomingBlock(unsigned I) const
Return incoming basic block number i.
MemoryAccess * getIncomingValue(unsigned I) const
Return incoming value number x.
An analysis that produces MemorySSA for a function.
Legacy analysis pass which computes MemorySSA.
LLVM_ABI void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
LLVM_ABI bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in the same basic block, determine whether MemoryAccess A dominates MemoryA...
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
This is an entry in the NonLocalDepInfo cache.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
LLVM_ABI Value * translateValue(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree *DT, bool MustDominate)
translateValue - PHI translate the current address up the CFG from CurBB to Pred, updating our state ...
LLVM_ABI bool isPotentiallyPHITranslatable() const
isPotentiallyPHITranslatable - If this needs PHI translation, return true if we have some hope of doi...
bool needsPHITranslationFromBlock(BasicBlock *BB) const
needsPHITranslationFromBlock - Return true if moving from the specified BasicBlock to its predecessor...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
AnalysisType * getAnalysisIfAvailable() const
getAnalysisIfAvailable<AnalysisType>() - Subclasses use this function to get analysis information tha...
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Helper class for SSA formation on a set of values defined in multiple blocks.
LLVM_ABI void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
LLVM_ABI Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
LLVM_ABI bool HasValueForBlock(BasicBlock *BB) const
Return true if the SSAUpdater already has a value for the specified block.
LLVM_ABI void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
std::pair< Value *, SelectAddrs > getSelectCondAndAddrs() const
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
SmallVector & operator=(const SmallVector &RHS)
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI bool isTokenLikeTy() const
Returns true if this is 'token' or a token-like target type.s.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
bool hasUseList() const
Check if this Value has a use-list.
LLVM_ABI bool canBeFreed() const
Return true if the memory object referred to by V can by freed in the scope for which the SSA value d...
LLVM_ABI void deleteValue()
Delete a pointer to a generic Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
int getNumOccurrences() const
std::pair< iterator, bool > insert(const ValueT &V)
An efficient, type-erasing, non-owning reference to a callable.
An opaque object representing a hash code.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
auto m_Value()
Match an arbitrary value and ignore it.
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
NoWrapTrunc_match< OpTy, TruncInst::NoUnsignedWrap > m_NUWTrunc(const OpTy &Op)
Matches trunc nuw.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_MaskedStore(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedStore Intrinsic.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
LLVM_ABI int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr, StoreInst *DepSI, const DataLayout &DL)
This function determines whether a value for the pointer LoadPtr can be extracted from the store at D...
LLVM_ABI Value * getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, Type *LoadTy, Instruction *InsertPt, const DataLayout &DL)
If analyzeLoadFromClobberingMemInst returned an offset, this function can be used to actually perform...
LLVM_ABI int analyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr, LoadInst *DepLI, const DataLayout &DL)
This function determines whether a value for the pointer LoadPtr can be extracted from the load at De...
LLVM_ABI Value * getValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy, Instruction *InsertPt, Function *F)
If analyzeLoadFromClobberingStore/Load returned an offset, this function can be used to actually perf...
LLVM_ABI int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr, MemIntrinsic *DepMI, const DataLayout &DL)
This function determines whether a value for the pointer LoadPtr can be extracted from the memory int...
LLVM_ABI bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy, Function *F)
Return true if CoerceAvailableValueToLoadType would succeed if it was called.
initializer< Ty > init(const Ty &Val)
Add a small namespace to avoid name clashes with the classes used in the streaming interface.
NodeAddr< InstrNode * > Instr
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
LLVM_ABI unsigned replaceDominatedUsesWithIf(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge, function_ref< bool(const Use &U, const Value *To)> ShouldReplace)
Replace each use of 'From' with 'To' if that use is dominated by the given edge and the callback Shou...
RelativeUniformCounterPtr Values
LLVM_ABI unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ)
Search for the specified successor of basic block BB and return its position in the terminator instru...
auto pred_end(const MachineBasicBlock *BB)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI FunctionPass * createGVNPass(bool ScalarPRE)
Create a legacy GVN pass.
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
auto successors(const MachineBasicBlock *BB)
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
constexpr from_range_t from_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
LLVM_ABI bool isAssumeWithEmptyBundle(const AssumeInst &Assume)
Return true iff the operand bundles of the provided llvm.assume doesn't contain any valuable informat...
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI bool canReplacePointersInUseIfEqual(const Use &U, const Value *To, const DataLayout &DL)
LLVM_ABI bool canReplacePointersIfEqual(const Value *From, const Value *To, const DataLayout &DL)
Returns true if a pointer value From can be replaced with another pointer value \To if they are deeme...
bool isModSet(const ModRefInfo MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI void patchReplacementInstruction(Instruction *I, Value *Repl)
Patch the replacement so that it is not more restrictive than the value being replaced.
LLVM_ABI void initializeGVNLegacyPassPass(PassRegistry &)
LLVM_ABI unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge)
Replace each use of 'From' with 'To' if that use is dominated by the given edge.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
LLVM_ABI void combineMetadataForCSE(Instruction *K, const Instruction *J, bool DoesKMove)
Combine the metadata of two instructions so that K can replace J.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ Ref
The access may reference the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
LLVM_ABI bool VerifyMemorySSA
Enables verification of MemorySSA.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
LLVM_ABI bool salvageKnowledge(Instruction *I, AssumptionCache *AC=nullptr, DominatorTree *DT=nullptr)
Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert if before I.
LLVM_ABI bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, MemoryDependenceResults *MemDep=nullptr, bool PredecessorWithTwoSuccessors=false, DominatorTree *DT=nullptr)
Attempts to merge a block into its predecessor, if possible.
LLVM_ABI FunctionPass * createGVNPass()
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
DWARFExpression::Operation Op
LLVM_ABI BasicBlock * SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")
If this edge is a critical edge, insert a new node to split the critical edge.
LLVM_ABI bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges=false)
Return true if the specified edge is a critical edge.
constexpr unsigned BitWidth
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool pred_empty(const BasicBlock *BB)
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool EliminateDuplicatePHINodes(BasicBlock *BB)
Check for and eliminate duplicate PHI nodes in this block.
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static bool isEqual(const GVNPass::Expression &LHS, const GVNPass::Expression &RHS)
static unsigned getHashValue(const GVNPass::Expression &E)
An information struct used to provide DenseMap with the various necessary components for a given valu...
A set of parameters to control various transforms performed by GVN pass.
Represents an AvailableValue which can be rematerialized at the end of the associated BasicBlock.
Value * MaterializeAdjustedValue(LoadInst *Load) const
Emit code at the end of this block to adjust the value defined here to the specified type.
static AvailableValueInBlock get(BasicBlock *BB, Value *V, unsigned Offset=0)
AvailableValue AV
AV - The actual available value.
static AvailableValueInBlock getUndef(BasicBlock *BB)
BasicBlock * BB
BB - The basic block in question.
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV)
Represents a particular available value that we know how to materialize.
static AvailableValue getUndef()
unsigned Offset
Offset - The byte offset in Val that is interesting for the load query.
ValType Kind
Kind of the live-out value.
bool isCoercedLoadValue() const
Value * getSimpleValue() const
LoadInst * getCoercedLoadValue() const
bool isSelectValue() const
Value * Val
Val - The value that is live out of the block.
static AvailableValue getSelect(Value *Cond, Value *V1, Value *V2)
static AvailableValue get(Value *V, unsigned Offset=0)
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset=0)
bool isSimpleValue() const
bool isUndefValue() const
Value * getSelectCondition() const
static AvailableValue getLoad(LoadInst *Load, unsigned Offset=0)
MemIntrinsic * getMemIntrinValue() const
Value * MaterializeAdjustedValue(LoadInst *Load, Instruction *InsertPt) const
Emit code at the specified insertion point to adjust the value defined here to the specified type.
bool isMemIntrinValue() const
Value * V1
V1, V2 - The dominating non-clobbered values of SelectVal.
bool operator==(const Expression &Other) const
friend hash_code hash_value(const Expression &Value)
SmallVector< uint32_t, 4 > VarArgs
Expression(uint32_t Op=~2U)