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())
2131 AvailValInBlkVect ValuesPerBlock;
2132 UnavailBlkVect UnavailableBlocks;
2133 analyzeLoadAvailability(
Load, Deps, ValuesPerBlock, UnavailableBlocks);
2137 if (ValuesPerBlock.empty())
2145 if (UnavailableBlocks.empty()) {
2151 ICF->removeUsersOf(
Load);
2152 Load->replaceAllUsesWith(V);
2160 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2161 I->setDebugLoc(
Load->getDebugLoc());
2162 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2163 MD->invalidateCachedPointerInfo(V);
2176 if (performLoopLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks) ||
2177 performLoadPRE(
Load, ValuesPerBlock, UnavailableBlocks))
2183bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2187 if (
Cond->isZero()) {
2197 const MemoryUseOrDef *FirstNonDom =
nullptr;
2199 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2206 for (
const auto &Acc : *AL) {
2208 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2209 FirstNonDom = Current;
2216 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2218 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2219 : MSSAU->createMemoryAccessInBB(
2241 return propagateEquality(V, True, IntrinsicI);
2246 I->replaceAllUsesWith(Repl);
2253 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2264 PointerUsesQueue.
push_back(PointerOperand);
2269 while (!PointerUsesQueue.
empty()) {
2272 "Null or GlobalValue should not be inserted");
2276 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2291 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2293 MostDominatingInstruction =
I;
2297 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2303static std::optional<MemoryLocation>
2310 switch (
II->getIntrinsicID()) {
2311 case Intrinsic::masked_load:
2313 case Intrinsic::masked_store:
2316 return std::nullopt;
2323 return std::nullopt;
2327 return std::nullopt;
2333std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2334 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2335 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2336 BatchAAResults &AA, LoadInst *L) {
2339 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2343 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2345 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2353 Choice->Kind = DepKind::Clobber;
2354 Choice->Offset = AR.getOffset();
2356 Choice->Kind = DepKind::Def;
2357 Choice->Offset = -1;
2360 Choice->Inst = Candidate;
2361 Choice->Block = Candidate->getParent();
2364 std::optional<ReachingMemVal> ReachingVal;
2365 for (MemoryAccess *MA : ClobbersList) {
2367 for (User *U : MA->
users()) {
2369 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2372 if (!UseOrDef || UseOrDef->getBlock() != BB)
2381 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2395 UpdateChoice(ReachingVal, AR, MemI);
2407std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2408 MemoryAccess *ClobberMA,
const MemoryLocation &Loc,
bool IsInvariantLoad,
2409 BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2417 if (
Alloc->getParent() == BB)
2418 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2419 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2423 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2424 return std::nullopt;
2428 return L->getOrdering();
2435 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2437 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2448 return std::nullopt;
2449 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2454 return std::nullopt;
2459 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2464 "Must be the superset/partial overlap case with positive offset");
2465 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2470 return std::nullopt;
2471 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2473 if (AA.isMustAlias(IIObjLoc, Loc))
2474 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2475 return std::nullopt;
2483 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2484 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2490 return std::nullopt;
2494 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2498 return std::nullopt;
2502 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2508bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2509 MemoryAccess *ClobberMA,
2510 DependencyBlockSet &Blocks,
2511 SmallVectorImpl<BasicBlock *> &Worklist) {
2521 if (!DT->isReachableFromEntry(Pred))
2525 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2528 PHITransAddr TransAddr = Addr;
2532 auto It = Blocks.find(Pred);
2533 if (It != Blocks.end()) {
2537 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2544 Pred, DependencyBlockInfo(TransAddr,
2545 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2552 for (
auto &
P : Preds) {
2553 [[maybe_unused]]
auto It =
2554 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2566void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2568 const DependencyBlockInfo &StartInfo,
2569 const DependencyBlockSet &Blocks,
2571 MemoryAccess *MA = StartInfo.InitialClobberMA;
2572 MemoryAccess *LastMA = StartInfo.ClobberMA;
2575 while (MA != LastMA) {
2589 BB = DT->getNode(BB)->getIDom()->getBlock();
2593 auto It = Blocks.find(BB);
2594 if (It == Blocks.end())
2597 MA = It->second.InitialClobberMA;
2598 LastMA = It->second.ClobberMA;
2599 if (MA == Clobbers.
back())
2616bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2617 SmallVectorImpl<ReachingMemVal> &
Values,
2619 EarliestEscapeAnalysis EA(*DT, LI);
2620 BatchAAResults AA(AAR, &EA);
2622 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2628 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2641 if (
auto RMV = scanMemoryAccessesUsers(
2642 Loc, IsInvariantLoad, StartBlock,
2644 Values.emplace_back(*RMV);
2654 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2655 StartBlock, MSSA, AA)) {
2656 Values.emplace_back(*RMV);
2663 }
while (ClobberMA->
getBlock() == StartBlock);
2666 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2667 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2676 DependencyBlockSet Blocks;
2677 SmallVector<BasicBlock *, 16> InitialWorklist;
2678 const DataLayout &
DL =
L->getModule()->getDataLayout();
2679 if (!collectPredecessors(StartBlock,
2680 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2681 ClobberMA, Blocks, InitialWorklist))
2685 auto Worklist = InitialWorklist;
2686 while (!Worklist.
empty()) {
2691 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2694 if (!
Info.Addr.getAddr())
2702 if (
auto RMV = accessMayModifyLocation(
2704 IsInvariantLoad, BB, MSSA, AA)) {
2709 "LiveOnEntry aliases everything");
2725 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2726 Info.ForceUnknown =
true;
2729 if (BB != StartBlock &&
2730 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2731 Info.ForceUnknown =
true;
2741 Worklist = InitialWorklist;
2742 for (BasicBlock *BB : Worklist) {
2743 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2744 Info.Visited =
true;
2748 while (!Worklist.empty()) {
2749 auto *BB = Worklist.pop_back_val();
2750 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2754 if (!
Info.Addr.getAddr()) {
2755 Values.push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2760 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2763 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2775 if (
Info.ForceUnknown) {
2776 Values.push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2782 auto It = Blocks.find(Pred);
2783 if (It == Blocks.end())
2785 DependencyBlockInfo &PredInfo = It->second;
2786 if (PredInfo.Visited)
2788 PredInfo.Visited =
true;
2789 Worklist.push_back(Pred);
2798bool GVNPass::processLoad(LoadInst *L) {
2803 if (!
L->isUnordered())
2806 if (
L->getType()->isTokenLikeTy())
2809 if (
L->use_empty()) {
2814 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2817 MemDepResult Dep = MD->getDependency(L);
2821 return processNonLocalLoad(L);
2825 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2828 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2831 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2833 assert(MemVals.
size() &&
"Expected at least an unknown value");
2834 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2835 return processNonLocalLoad(L, MemVals);
2837 MemVal = MemVals[0];
2840 if (MemVal.Kind == DepKind::Other) {
2844 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2845 dbgs() <<
" has unknown dependence\n";);
2849 auto AV = analyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2856 ICF->removeUsersOf(L);
2859 MSSAU->removeMemoryAccess(L);
2872bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2875 MemDepResult Dep = MD->getDependency(
I);
2881 Value *Passthrough =
I->getOperand(2);
2885 StoreVal->
getType() !=
I->getType())
2892 ICF->removeUsersOf(
I);
2893 I->replaceAllUsesWith(OpToForward);
2901std::pair<uint32_t, bool>
2902GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2903 uint32_t &
E = ExpressionNumbering[
Exp];
2904 bool CreateNewValNum = !
E;
2905 if (CreateNewValNum) {
2906 Expressions.push_back(Exp);
2907 if (ExprIdx.size() < NextValueNumber + 1)
2908 ExprIdx.resize(NextValueNumber * 2);
2909 E = NextValueNumber;
2910 ExprIdx[NextValueNumber++] = NextExprNumber++;
2912 return {
E, CreateNewValNum};
2917bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2920 GVN.LeaderTable.getLeaders(Num),
2928 auto FindRes = PhiTranslateTable.find({Num, Pred});
2929 if (FindRes != PhiTranslateTable.end())
2930 return FindRes->second;
2931 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2932 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2943 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2944 for (
const auto &Entry : Leaders) {
2946 if (
Call &&
Call->getParent() == PhiBlock)
2950 if (
AA->doesNotAccessMemory(
Call))
2953 if (!MD || !
AA->onlyReadsMemory(
Call))
2965 if (
D.getResult().isNonFuncLocal())
2973uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2974 const BasicBlock *PhiBlock,
2978 if (PHINode *PN = NumberingPhi[Num]) {
2979 if (PN->getParent() != PhiBlock)
2981 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2982 if (PN->getIncomingBlock(
I) != Pred)
2984 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2990 if (BasicBlock *BB = NumberingBB[Num]) {
2991 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
3003 return lookupOrAdd(PredPhi->getBlock());
3009 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
3015 if (!areAllValsInBB(Num, PhiBlock, GVN))
3018 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
3022 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
3026 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
3027 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
3028 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
3030 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
3033 if (
Exp.Commutative) {
3034 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
3035 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
3037 uint32_t Opcode =
Exp.Opcode >> 8;
3038 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
3039 Exp.Opcode = (Opcode << 8) |
3045 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
3046 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
3047 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3055void GVNPass::ValueTable::eraseTranslateCacheEntry(
3058 PhiTranslateTable.erase({Num, Pred});
3067 auto Leaders = LeaderTable.getLeaders(Num);
3068 if (Leaders.empty())
3071 Value *Val =
nullptr;
3072 for (
const auto &Entry : Leaders) {
3073 if (DT->dominates(Entry.BB, BB)) {
3093 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3094 assert((!Pred || Pred ==
E.getStart()) &&
3095 "No edge between these basic blocks!");
3096 return Pred !=
nullptr;
3099void GVNPass::assignBlockRPONumber(
Function &
F) {
3100 BlockRPONumber.clear();
3101 uint32_t NextBlockNumber = 1;
3102 ReversePostOrderTraversal<Function *> RPOT(&
F);
3103 for (BasicBlock *BB : RPOT)
3104 BlockRPONumber[BB] = NextBlockNumber++;
3105 InvalidBlockRPONumbers =
false;
3113bool GVNPass::propagateEquality(
3115 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3117 SmallDenseSet<std::pair<Value *, Value *>, 4> Visited;
3121 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3128 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3132 while (!Worklist.
empty()) {
3133 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3134 LHS = Item.first;
RHS = Item.second;
3148 const DataLayout &
DL =
3157 uint32_t LVN = VN.lookupOrAdd(
LHS);
3162 uint32_t RVN = VN.lookupOrAdd(
RHS);
3169 if (!Visited.
insert({LHS, RHS}).second)
3182 for (
const BasicBlock *BB : DominatedBlocks)
3183 LeaderTable.insert(LVN,
RHS, BB);
3190 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3193 unsigned NumReplacements;
3194 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3196 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3199 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3200 CanReplacePointersCallBack);
3202 if (NumReplacements > 0) {
3204 NumGVNEqProp += NumReplacements;
3207 MD->invalidateCachedPointerInfo(
LHS);
3224 bool IsKnownFalse = !IsKnownTrue;
3240 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3245 if (
Cmp->isEquivalence(IsKnownFalse))
3246 Worklist.
push_back(std::make_pair(Op0, Op1));
3250 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3254 uint32_t NextNum = VN.getNextUnusedValueNumber();
3255 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3258 if (Num < NextNum) {
3259 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3264 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3265 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3266 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3269 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3270 if (!DT->dominates(
Entry.BB, InstBB) &&
3271 !DT->dominates(InstBB,
Entry.BB))
3277 unsigned NumReplacements;
3278 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3283 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3284 Changed |= NumReplacements > 0;
3285 NumGVNEqProp += NumReplacements;
3288 MD->invalidateCachedPointerInfo(NotCmp);
3296 for (
const BasicBlock *BB : DominatedBlocks)
3297 LeaderTable.insert(Num, NotVal, BB);
3306 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3311 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3321bool GVNPass::processInstruction(Instruction *
I) {
3326 const DataLayout &
DL =
I->getDataLayout();
3329 if (!
I->use_empty()) {
3332 ICF->removeUsersOf(
I);
3333 I->replaceAllUsesWith(V);
3341 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3342 MD->invalidateCachedPointerInfo(V);
3349 return processAssumeIntrinsic(Assume);
3352 if (processLoad(
Load))
3355 unsigned Num = VN.lookupOrAdd(
Load);
3356 LeaderTable.insert(Num,
Load,
Load->getParent());
3368 return processFoldableCondBr(BI);
3370 Value *BranchCond = BI->getCondition();
3374 if (TrueSucc == FalseSucc)
3381 BasicBlockEdge TrueE(Parent, TrueSucc);
3382 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3385 BasicBlockEdge FalseE(Parent, FalseSucc);
3386 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3393 Value *SwitchCond =
SI->getCondition();
3398 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3400 ++SwitchEdges[Succ];
3402 for (
const auto &Case :
SI->cases()) {
3405 if (SwitchEdges.
lookup(Dst) == 1) {
3406 BasicBlockEdge
E(Parent, Dst);
3407 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3415 if (
I->getType()->isVoidTy())
3418 uint32_t NextNum = VN.getNextUnusedValueNumber();
3419 unsigned Num = VN.lookupOrAdd(
I);
3424 LeaderTable.insert(Num,
I,
I->getParent());
3431 const DataLayout &
DL =
I->getDataLayout();
3432 unsigned AS = PTA->getPointerAddressSpace();
3433 if (
DL.getAddressSizeInBits(AS) ==
DL.getPointerSizeInBits(AS) &&
3434 !
DL.hasUnstableRepresentation(AS)) {
3436 VN.lookupPtrToInt(PTA->getPointerOperand(), PTA->getType());
3437 if (
Value *PTI = findLeader(
I->getParent(), PTINum)) {
3448 if (Num >= NextNum) {
3449 LeaderTable.insert(Num,
I,
I->getParent());
3455 Value *Repl = findLeader(
I->getParent(), Num);
3458 LeaderTable.insert(Num,
I,
I->getParent());
3471 MD->invalidateCachedPointerInfo(Repl);
3477bool GVNPass::runImpl(
Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3478 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3479 MemoryDependenceResults *RunMD, LoopInfo &LI,
3480 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3488 "mutually exclusive",
3495 VN.setAliasAnalysis(&RunAA);
3497 ImplicitControlFlowTracking ImplicitCFT;
3506 InvalidBlockRPONumbers =
true;
3507 MemorySSAUpdater Updater(MSSA);
3508 MSSAU = MSSA ? &Updater :
nullptr;
3511 bool ShouldContinue =
true;
3513 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3525 unsigned Iteration = 0;
3526 while (ShouldContinue) {
3529 ShouldContinue = iterateOnFunction(
F);
3537 assignValNumForDeadCode();
3538 bool PREChanged =
true;
3539 while (PREChanged) {
3540 PREChanged = performPRE(
F);
3550 cleanupGlobalSets();
3561bool GVNPass::processBlock(BasicBlock *BB) {
3562 if (DeadBlocks.count(BB))
3565 bool ChangedFunction =
false;
3571 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3573 for (PHINode *PN : PHINodesToRemove) {
3574 removeInstruction(PN);
3577 ChangedFunction |= processInstruction(&Inst);
3578 return ChangedFunction;
3582bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3583 BasicBlock *Curr,
unsigned int ValNo) {
3589 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3597 if (!VN.exists(
Op)) {
3602 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3603 if (
Value *V = findLeader(Pred, TValNo)) {
3621 ICF->insertInstructionTo(Instr, Pred);
3623 unsigned Num = VN.lookupOrAdd(Instr);
3627 LeaderTable.insert(Num, Instr, Pred);
3631bool GVNPass::performScalarPRE(Instruction *CurInst) {
3657 if (CallB->isInlineAsm())
3661 uint32_t ValNo = VN.lookup(CurInst);
3669 unsigned NumWith = 0;
3670 unsigned NumWithout = 0;
3675 if (InvalidBlockRPONumbers)
3676 assignBlockRPONumber(*CurrentBlock->
getParent());
3682 if (!DT->isReachableFromEntry(
P)) {
3687 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3688 "Invalid BlockRPONumber map.");
3689 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3694 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3695 Value *PredV = findLeader(
P, TValNo);
3700 }
else if (PredV == CurInst) {
3712 if (NumWithout > 1 || NumWith == 0)
3720 if (NumWithout != 0) {
3726 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3739 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3743 PREInstr = CurInst->
clone();
3744 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3747 verifyRemoved(PREInstr);
3756 assert(PREInstr !=
nullptr || NumWithout == 0);
3762 CurInst->
getName() +
".pre-phi");
3763 Phi->insertBefore(CurrentBlock->begin());
3764 for (
auto &[V, BB] : PredMap) {
3769 Phi->addIncoming(V, BB);
3771 Phi->addIncoming(PREInstr, PREPred);
3777 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3778 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3781 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3782 MD->invalidateCachedPointerInfo(Phi);
3783 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3786 removeInstruction(CurInst);
3795 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3797 if (CurrentBlock == &
F.getEntryBlock())
3801 if (CurrentBlock->isEHPad())
3805 BE = CurrentBlock->end();
3808 Changed |= performScalarPRE(CurInst);
3812 if (splitCriticalEdges())
3820BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3825 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3828 MD->invalidateCachedPredecessors();
3829 InvalidBlockRPONumbers =
true;
3836bool GVNPass::splitCriticalEdges() {
3837 if (ToSplit.empty())
3842 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3844 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3846 }
while (!ToSplit.empty());
3849 MD->invalidateCachedPredecessors();
3850 InvalidBlockRPONumbers =
true;
3856bool GVNPass::iterateOnFunction(
Function &
F) {
3857 cleanupGlobalSets();
3864 ReversePostOrderTraversal<Function *> RPOT(&
F);
3866 for (BasicBlock *BB : RPOT)
3872void GVNPass::cleanupGlobalSets() {
3874 LeaderTable.clear();
3875 BlockRPONumber.clear();
3877 InvalidBlockRPONumbers =
true;
3880void GVNPass::removeInstruction(Instruction *
I) {
3882 if (MD) MD->removeInstruction(
I);
3884 MSSAU->removeMemoryAccess(
I);
3888 ICF->removeInstruction(
I);
3889 I->eraseFromParent();
3895void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3896 VN.verifyRemoved(Inst);
3903void GVNPass::addDeadBlock(BasicBlock *BB) {
3905 SmallSetVector<BasicBlock *, 4>
DF;
3908 while (!NewDead.
empty()) {
3910 if (DeadBlocks.count(
D))
3914 SmallVector<BasicBlock *, 8> Dom;
3915 DT->getDescendants(
D, Dom);
3916 DeadBlocks.insert_range(Dom);
3919 for (BasicBlock *
B : Dom) {
3921 if (DeadBlocks.count(S))
3924 bool AllPredDead =
true;
3926 if (!DeadBlocks.count(
P)) {
3927 AllPredDead =
false;
3947 for (BasicBlock *
B :
DF) {
3948 if (DeadBlocks.count(
B))
3954 for (BasicBlock *
P : Preds) {
3955 if (!DeadBlocks.count(
P))
3960 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3961 DeadBlocks.insert(
P = S);
3967 if (!DeadBlocks.count(
P))
3969 for (PHINode &Phi :
B->phis()) {
3972 MD->invalidateCachedPointerInfo(&Phi);
3991bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
4002 if (DeadBlocks.count(DeadRoot))
4006 DeadRoot = splitCriticalEdges(BI->
getParent(), DeadRoot);
4008 addDeadBlock(DeadRoot);
4016void GVNPass::assignValNumForDeadCode() {
4017 for (BasicBlock *BB : DeadBlocks) {
4018 for (Instruction &Inst : *BB) {
4019 unsigned ValNum = VN.lookupOrAdd(&Inst);
4020 LeaderTable.insert(ValNum, &Inst, BB);
4031 bool ScalarPRE =
true)
4033 .setMemDep(MemDepAnalysis)
4034 .setMemorySSA(MemSSAAnalysis)
4035 .setScalarPRE(ScalarPRE)) {
4044 if (Impl.isMemorySSAEnabled() && !MSSAWP)
4047 return Impl.runImpl(
4052 Impl.isMemDepEnabled()
4057 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
4065 if (Impl.isMemDepEnabled())
4074 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)