88#define DEBUG_TYPE "gvn"
90STATISTIC(NumGVNInstr,
"Number of instructions deleted");
92STATISTIC(NumGVNPRE,
"Number of instructions PRE'd");
94STATISTIC(NumGVNSimpl,
"Number of instructions simplified");
95STATISTIC(NumGVNEqProp,
"Number of equalities propagated");
97STATISTIC(NumPRELoopLoad,
"Number of loop loads PRE'd");
99 "Number of loads moved to predecessor of a critical edge in PRE");
101STATISTIC(IsValueFullyAvailableInBlockNumSpeculationsMax,
102 "Number of blocks speculated as available in "
103 "IsValueFullyAvailableInBlock(), max");
105 "Number of times we we reached gvn-max-block-speculations cut-off "
106 "preventing further exploration");
122 cl::desc(
"The number of memory accesses to scan in a block in reaching "
123 "memory values analysis (default = 100)"));
127 cl::desc(
"Max number of dependences to attempt Load PRE (default = 100)"));
132 cl::desc(
"Max number of blocks we're willing to speculate on (and recurse "
133 "into) when deducing if a value is fully available or not in GVN "
138 cl::desc(
"Max number of visited instructions when trying to find "
139 "dominating value of select dependency (default = 100)"));
143 cl::desc(
"Max number of instructions to scan in each basic block in GVN "
159 if (
Opcode != Other.Opcode)
167 if ((!
Attrs.isEmpty() || !Other.Attrs.isEmpty()) &&
168 !
Attrs.intersectWith(
Ty->getContext(), Other.Attrs).has_value())
302 Res.
AV = std::move(
AV);
318 return AV.MaterializeAdjustedValue(Load,
BB->getTerminator());
329 E.Opcode =
I->getOpcode();
334 E.VarArgs.push_back(
lookupOrAdd(GCR->getOperand(0)));
335 E.VarArgs.push_back(
lookupOrAdd(GCR->getBasePtr()));
336 E.VarArgs.push_back(
lookupOrAdd(GCR->getDerivedPtr()));
338 for (
Use &
Op :
I->operands())
341 if (
I->isCommutative()) {
346 assert(
I->getNumOperands() >= 2 &&
"Unsupported commutative instruction!");
347 if (
E.VarArgs[0] >
E.VarArgs[1])
349 E.Commutative =
true;
355 if (
E.VarArgs[0] >
E.VarArgs[1]) {
360 E.Commutative =
true;
362 E.VarArgs.append(IVI->idx_begin(), IVI->idx_end());
364 ArrayRef<int> ShuffleMask = SVI->getShuffleMask();
365 E.VarArgs.append(ShuffleMask.
begin(), ShuffleMask.
end());
367 E.Attrs = CB->getAttributes();
373GVNPass::Expression GVNPass::ValueTable::createCmpExpr(
375 assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
376 "Not a comparison!");
379 E.VarArgs.push_back(lookupOrAdd(
LHS));
380 E.VarArgs.push_back(lookupOrAdd(
RHS));
383 if (
E.VarArgs[0] >
E.VarArgs[1]) {
387 E.Opcode = (Opcode << 8) | Predicate;
388 E.Commutative =
true;
393GVNPass::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) {
394 assert(EI &&
"Not an ExtractValueInst?");
405 E.VarArgs.push_back(lookupOrAdd(WO->
getLHS()));
406 E.VarArgs.push_back(lookupOrAdd(WO->
getRHS()));
414 E.VarArgs.push_back(lookupOrAdd(
Op));
421GVNPass::Expression GVNPass::ValueTable::createGEPExpr(GetElementPtrInst *
GEP) {
423 Type *PtrTy =
GEP->getType()->getScalarType();
424 const DataLayout &
DL =
GEP->getDataLayout();
425 unsigned BitWidth =
DL.getIndexTypeSizeInBits(PtrTy);
426 SmallMapVector<Value *, APInt, 4> VariableOffsets;
428 if (
GEP->collectOffset(
DL,
BitWidth, VariableOffsets, ConstantOffset)) {
432 E.Opcode =
GEP->getOpcode();
434 E.VarArgs.push_back(lookupOrAdd(
GEP->getPointerOperand()));
435 for (
const auto &[V, Scale] : VariableOffsets) {
436 E.VarArgs.push_back(lookupOrAdd(V));
437 E.VarArgs.push_back(lookupOrAdd(ConstantInt::get(
Context, Scale)));
439 if (!ConstantOffset.isZero())
441 lookupOrAdd(ConstantInt::get(
Context, ConstantOffset)));
445 E.Opcode =
GEP->getOpcode();
446 E.Ty =
GEP->getSourceElementType();
447 for (Use &
Op :
GEP->operands())
448 E.VarArgs.push_back(lookupOrAdd(
Op));
457GVNPass::ValueTable::ValueTable() =
default;
458GVNPass::ValueTable::ValueTable(
const ValueTable &) =
default;
459GVNPass::ValueTable::ValueTable(
ValueTable &&) =
default;
460GVNPass::ValueTable::~ValueTable() =
default;
466 ValueNumbering.
insert(std::make_pair(V, Num));
468 NumberingPhi[Num] = PN;
478 assert(MSSA &&
"addMemoryStateToExp should not be called without MemorySSA");
479 assert(MSSA->getMemoryAccess(
I) &&
"Instruction does not access memory");
480 MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(
I);
481 Exp.VarArgs.push_back(lookupOrAdd(MA));
492 if (
C->getFunction()->isPresplitCoroutine()) {
493 ValueNumbering[
C] = NextValueNumber;
494 return NextValueNumber++;
500 if (
C->isConvergent()) {
501 ValueNumbering[
C] = NextValueNumber;
502 return NextValueNumber++;
505 if (AA->doesNotAccessMemory(
C)) {
507 uint32_t
E = assignExpNewValueNum(Exp).first;
508 ValueNumbering[
C] =
E;
512 if (MD && AA->onlyReadsMemory(
C)) {
514 auto [
E, IsValNumNew] = assignExpNewValueNum(Exp);
516 ValueNumbering[
C] =
E;
520 MemDepResult LocalDep = MD->getDependency(
C);
523 ValueNumbering[
C] = NextValueNumber;
524 return NextValueNumber++;
527 if (LocalDep.
isDef()) {
532 if (!LocalDepCall || LocalDepCall->
arg_size() !=
C->arg_size()) {
533 ValueNumbering[
C] = NextValueNumber;
534 return NextValueNumber++;
537 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
538 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
539 uint32_t LocalDepCallVN = lookupOrAdd(LocalDepCall->
getArgOperand(
I));
540 if (CVN != LocalDepCallVN) {
541 ValueNumbering[
C] = NextValueNumber;
542 return NextValueNumber++;
546 uint32_t
V = lookupOrAdd(LocalDepCall);
547 ValueNumbering[
C] =
V;
553 MD->getNonLocalCallDependency(
C);
555 CallInst *CDep =
nullptr;
559 for (
const NonLocalDepEntry &
I : Deps) {
560 if (
I.getResult().isNonLocal())
565 if (!
I.getResult().isDef() || CDep !=
nullptr) {
572 if (NonLocalDepCall && DT->properlyDominates(
I.getBB(),
C->getParent())) {
573 CDep = NonLocalDepCall;
582 ValueNumbering[
C] = NextValueNumber;
583 return NextValueNumber++;
587 ValueNumbering[
C] = NextValueNumber;
588 return NextValueNumber++;
590 for (
unsigned I = 0,
E =
C->arg_size();
I <
E; ++
I) {
591 uint32_t CVN = lookupOrAdd(
C->getArgOperand(
I));
594 ValueNumbering[
C] = NextValueNumber;
595 return NextValueNumber++;
599 uint32_t
V = lookupOrAdd(CDep);
600 ValueNumbering[
C] =
V;
604 if (MSSA && IsMSSAEnabled && AA->onlyReadsMemory(
C)) {
606 addMemoryStateToExp(
C, Exp);
607 auto [
V,
_] = assignExpNewValueNum(Exp);
608 ValueNumbering[
C] =
V;
612 ValueNumbering[
C] = NextValueNumber;
613 return NextValueNumber++;
617uint32_t GVNPass::ValueTable::computeLoadStoreVN(Instruction *
I) {
618 if (!MSSA || !IsMSSAEnabled) {
619 ValueNumbering[
I] = NextValueNumber;
620 return NextValueNumber++;
624 Exp.Ty =
I->getType();
625 Exp.Opcode =
I->getOpcode();
626 for (Use &
Op :
I->operands())
627 Exp.VarArgs.push_back(lookupOrAdd(
Op));
628 addMemoryStateToExp(
I, Exp);
630 auto [
V,
_] = assignExpNewValueNum(Exp);
631 ValueNumbering[
I] =
V;
636bool GVNPass::ValueTable::exists(
Value *V)
const {
637 return ValueNumbering.contains(V);
649 auto VI = ValueNumbering.find(V);
650 if (VI != ValueNumbering.end())
655 ValueNumbering[V] = NextValueNumber;
658 return NextValueNumber++;
662 switch (
I->getOpcode()) {
663 case Instruction::Call:
665 case Instruction::FNeg:
666 case Instruction::Add:
667 case Instruction::FAdd:
668 case Instruction::Sub:
669 case Instruction::FSub:
670 case Instruction::Mul:
671 case Instruction::FMul:
672 case Instruction::UDiv:
673 case Instruction::SDiv:
674 case Instruction::FDiv:
675 case Instruction::URem:
676 case Instruction::SRem:
677 case Instruction::FRem:
678 case Instruction::Shl:
679 case Instruction::LShr:
680 case Instruction::AShr:
681 case Instruction::And:
682 case Instruction::Or:
683 case Instruction::Xor:
684 case Instruction::ICmp:
685 case Instruction::FCmp:
686 case Instruction::Trunc:
687 case Instruction::ZExt:
688 case Instruction::SExt:
689 case Instruction::FPToUI:
690 case Instruction::FPToSI:
691 case Instruction::UIToFP:
692 case Instruction::SIToFP:
693 case Instruction::FPTrunc:
694 case Instruction::FPExt:
695 case Instruction::PtrToInt:
696 case Instruction::PtrToAddr:
697 case Instruction::IntToPtr:
698 case Instruction::AddrSpaceCast:
699 case Instruction::BitCast:
700 case Instruction::Select:
701 case Instruction::Freeze:
702 case Instruction::ExtractElement:
703 case Instruction::InsertElement:
704 case Instruction::ShuffleVector:
705 case Instruction::InsertValue:
708 case Instruction::GetElementPtr:
711 case Instruction::ExtractValue:
714 case Instruction::PHI:
715 ValueNumbering[V] = NextValueNumber;
717 return NextValueNumber++;
718 case Instruction::Load:
719 case Instruction::Store:
720 return computeLoadStoreVN(
I);
722 ValueNumbering[V] = NextValueNumber;
723 return NextValueNumber++;
726 uint32_t E = assignExpNewValueNum(Exp).first;
727 ValueNumbering[V] = E;
734 auto VI = ValueNumbering.find(V);
736 assert(VI != ValueNumbering.end() &&
"Value not numbered?");
739 return (VI != ValueNumbering.end()) ? VI->second : 0;
746uint32_t GVNPass::ValueTable::lookupOrAddCmp(
unsigned Opcode,
749 Expression Exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
750 return assignExpNewValueNum(Exp).first;
755 ValueNumbering.clear();
756 ExpressionNumbering.clear();
757 NumberingPhi.clear();
759 PhiTranslateTable.clear();
768 uint32_t Num = ValueNumbering.lookup(V);
769 ValueNumbering.erase(V);
772 NumberingPhi.erase(Num);
774 NumberingBB.erase(Num);
779void GVNPass::ValueTable::verifyRemoved(
const Value *V)
const {
780 assert(!ValueNumbering.contains(V) &&
781 "Inst still occurs in value numbering map!");
790 const auto &[It, Inserted] = NumToLeaders.try_emplace(
N, V, BB,
nullptr);
793 auto *NewSlot = TableAllocator.Allocate<LeaderListNode>();
794 new (NewSlot) LeaderListNode(V, BB, It->second.Next);
795 It->second.Next = NewSlot;
803 auto It = NumToLeaders.find(
N);
804 if (It == NumToLeaders.end())
807 LeaderListNode *Prev =
nullptr;
808 LeaderListNode *Curr = &It->second;
810 while (Curr && (Curr->Entry.Val !=
I || Curr->Entry.BB != BB)) {
820 Prev->Next = Curr->Next;
821 Curr->~LeaderListNode();
822 TableAllocator.Deallocate<LeaderListNode>(Curr);
827 NumToLeaders.erase(It);
830 LeaderListNode *
Next = Curr->Next;
831 Curr->Entry.Val = std::move(
Next->Entry.Val);
832 Curr->Entry.BB =
Next->Entry.BB;
833 Curr->Next =
Next->Next;
834 Next->~LeaderListNode();
835 TableAllocator.Deallocate<LeaderListNode>(
Next);
857 return Options.AllowLoadPRESplitBackedge.value_or(
884 "On-demand computation of MemSSA implies that MemDep is disabled!");
888 bool Changed = runImpl(
F, AC, DT, TLI, AA, MemDep, LI, &ORE,
889 MSSA ? &MSSA->getMSSA() :
nullptr);
904 OS, MapClassName2PassName);
907 if (Options.AllowScalarPRE != std::nullopt)
908 OS << (*Options.AllowScalarPRE ?
"" :
"no-") <<
"scalar-pre;";
909 if (Options.AllowLoadPRE != std::nullopt)
910 OS << (*Options.AllowLoadPRE ?
"" :
"no-") <<
"load-pre;";
911 if (Options.AllowLoadPRESplitBackedge != std::nullopt)
912 OS << (*Options.AllowLoadPRESplitBackedge ?
"" :
"no-")
913 <<
"split-backedge-load-pre;";
914 if (Options.AllowMemDep != std::nullopt)
915 OS << (*Options.AllowMemDep ?
"" :
"no-") <<
"memdep;";
916 if (Options.AllowMemorySSA != std::nullopt)
917 OS << (*Options.AllowMemorySSA ?
"" :
"no-") <<
"memoryssa";
924 removeInstruction(
I);
927#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
930 for (
const auto &[Num, Exp] : Map) {
931 errs() << Num <<
"\n";
962 std::optional<BasicBlock *> UnavailableBB;
966 unsigned NumNewNewSpeculativelyAvailableBBs = 0;
974 while (!Worklist.
empty()) {
978 std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator,
bool>
IV =
986 UnavailableBB = CurrBB;
997 ++NumNewNewSpeculativelyAvailableBBs;
1003 MaxBBSpeculationCutoffReachedTimes += (int)OutOfBudget;
1005 UnavailableBB = CurrBB;
1011 NewSpeculativelyAvailableBBs.
insert(CurrBB);
1017#if LLVM_ENABLE_STATS
1018 IsValueFullyAvailableInBlockNumSpeculationsMax.updateMax(
1019 NumNewNewSpeculativelyAvailableBBs);
1024 auto MarkAsFixpointAndEnqueueSuccessors =
1026 auto It = FullyAvailableBlocks.
find(BB);
1027 if (It == FullyAvailableBlocks.
end())
1034 State = FixpointState;
1037 "Found a speculatively available successor leftover?");
1045 if (UnavailableBB) {
1052 while (!Worklist.
empty())
1053 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1061 while (!Worklist.
empty())
1062 MarkAsFixpointAndEnqueueSuccessors(Worklist.
pop_back_val(),
1066 "Must have fixed all the new speculatively available blocks.");
1069 return !UnavailableBB;
1078 if (V.AV.Val == OldValue)
1079 V.AV.Val = NewValue;
1080 if (V.AV.isSelectValue()) {
1081 if (V.AV.V1 == OldValue)
1083 if (V.AV.V2 == OldValue)
1098 if (ValuesPerBlock.
size() == 1 &&
1100 Load->getParent())) {
1101 assert(!ValuesPerBlock[0].AV.isUndefValue() &&
1102 "Dead BB dominate this block");
1103 return ValuesPerBlock[0].MaterializeAdjustedValue(Load);
1109 SSAUpdate.
Initialize(Load->getType(), Load->getName());
1114 if (AV.AV.isUndefValue())
1124 if (BB == Load->getParent() &&
1125 ((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() == Load) ||
1126 (AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() == Load)))
1139 Type *LoadTy = Load->getType();
1143 if (Res->
getType() != LoadTy) {
1158 Load->getFunction());
1169 if (!CoercedLoad->
hasMetadata(LLVMContext::MD_noundef))
1171 {LLVMContext::MD_dereferenceable,
1172 LLVMContext::MD_dereferenceable_or_null,
1173 LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group,
1174 LLVMContext::MD_alias_scope, LLVMContext::MD_noalias});
1190 assert(
V1 &&
V2 &&
"both value operands of the select must be present");
1198 assert(Res &&
"failed to materialize?");
1204 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1221 Value *PtrOp = Load->getPointerOperand();
1227 for (
auto *U : PtrOp->
users()) {
1230 if (
I->getFunction() == Load->getFunction() && DT->
dominates(
I, Load)) {
1248 for (
auto *U : PtrOp->
users()) {
1251 if (
I->getFunction() == Load->getFunction() &&
1259 OtherAccess =
nullptr;
1278 using namespace ore;
1281 R <<
"load of type " << NV(
"Type", Load->getType()) <<
" not eliminated"
1286 R <<
" in favor of " << NV(
"OtherAccess", OtherAccess);
1288 R <<
" because it is clobbered by " << NV(
"ClobberedBy", DepInst);
1302 for (
auto *Inst = BB == FromBB ? From : BB->
getTerminator();
1310 if (
SI->isSimple() &&
SI->getPointerOperand() ==
Loc.Ptr &&
1311 SI->getValueOperand()->getType() == LoadTy)
1312 return SI->getValueOperand();
1316 if (LI->getPointerOperand() ==
Loc.Ptr && LI->getType() == LoadTy)
1322std::optional<AvailableValue>
1323GVNPass::AnalyzeSelectAvailability(LoadInst *Load,
Value *
Cond,
Value *TrueAddr,
1324 Value *FalseAddr, Instruction *From) {
1326 "Invalid address type of true side of select dependency");
1328 "Invalid address type of false side of select dependency");
1336 return std::nullopt;
1340 return std::nullopt;
1344std::optional<AvailableValue>
1345GVNPass::AnalyzeLoadAvailability(LoadInst *Load,
const ReachingMemVal &Dep,
1347 assert(
Load->isUnordered() &&
"rules below are incorrect for ordered access");
1348 assert((Dep.Kind == DepKind::Def || Dep.Kind == DepKind::Clobber) &&
1349 "expected a local dependence");
1353 const DataLayout &
DL =
Load->getDataLayout();
1354 if (Dep.Kind == DepKind::Clobber) {
1360 if (
Address &&
Load->isAtomic() <= DepSI->isAtomic()) {
1376 if (DepLoad != Load &&
Address &&
1377 Load->isAtomic() <= DepLoad->isAtomic()) {
1384 DepLoad->getFunction())) {
1385 const auto ClobberOff = MD->getClobberOffset(DepLoad);
1387 Offset = (ClobberOff == std::nullopt || *ClobberOff < 0)
1393 DepLoad->getFunction()) ||
1420 dbgs() <<
" is clobbered by " << *DepInst <<
'\n';);
1424 return std::nullopt;
1426 assert(Dep.Kind == DepKind::Def &&
"follows from above");
1433 if (Constant *InitVal =
1443 return std::nullopt;
1446 if (S->isAtomic() <
Load->isAtomic())
1447 return std::nullopt;
1458 return std::nullopt;
1461 if (
LD->isAtomic() <
Load->isAtomic())
1462 return std::nullopt;
1471 assert(Sel->getType() ==
Load->getPointerOperandType());
1472 if (
auto AV = AnalyzeSelectAvailability(Load, Sel->getCondition(),
1473 Sel->getTrueValue(),
1474 Sel->getFalseValue(), DepInst))
1476 return std::nullopt;
1483 dbgs() <<
" has unknown def " << *DepInst <<
'\n';);
1484 return std::nullopt;
1487void GVNPass::AnalyzeLoadAvailability(LoadInst *Load,
1488 SmallVectorImpl<ReachingMemVal> &Deps,
1489 AvailValInBlkVect &ValuesPerBlock,
1490 UnavailBlkVect &UnavailableBlocks) {
1495 for (
const auto &Dep : Deps) {
1498 if (DeadBlocks.count(DepBB)) {
1505 if (Dep.Kind == DepKind::Other) {
1506 UnavailableBlocks.push_back(DepBB);
1513 if (Dep.Kind == DepKind::Select) {
1514 if (
auto AV = AnalyzeSelectAvailability(
1515 Load,
const_cast<Value *
>(Dep.SelCond),
1516 const_cast<Value *
>(Dep.SelTrueAddr),
1518 ValuesPerBlock.push_back(
1521 UnavailableBlocks.push_back(DepBB);
1530 AnalyzeLoadAvailability(Load, Dep,
const_cast<Value *
>(Dep.Addr))) {
1534 ValuesPerBlock.push_back(
1537 UnavailableBlocks.push_back(DepBB);
1541 assert(Deps.size() == ValuesPerBlock.size() + UnavailableBlocks.size() &&
1542 "post condition violation");
1564LoadInst *GVNPass::findLoadToHoistIntoPred(BasicBlock *Pred, BasicBlock *LoadBB,
1568 if (
Term->getNumSuccessors() != 2 ||
Term->isSpecialTerminator())
1570 auto *SuccBB =
Term->getSuccessor(0);
1571 if (SuccBB == LoadBB)
1572 SuccBB =
Term->getSuccessor(1);
1573 if (!SuccBB->getSinglePredecessor())
1577 for (Instruction &Inst : *SuccBB) {
1578 if (Inst.isDebugOrPseudoInst())
1580 if (--NumInsts == 0)
1583 if (!Inst.isIdenticalTo(Load))
1586 bool HasLocalDep =
true;
1588 MemDepResult Dep = MD->getDependency(&Inst);
1591 auto *MSSA = MSSAU->getMemorySSA();
1593 if (
auto *MA = MSSA->getMemoryAccess(&Inst); MA &&
isa<MemoryUse>(MA)) {
1594 auto *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(MA);
1595 HasLocalDep = Clobber->getBlock() == SuccBB;
1603 if (!HasLocalDep && !ICF->isDominatedByICFIFromSameBlock(&Inst))
1614void GVNPass::eliminatePartiallyRedundantLoad(
1615 LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1616 MapVector<BasicBlock *, Value *> &AvailableLoads,
1617 MapVector<BasicBlock *, LoadInst *> *CriticalEdgePredAndLoad) {
1618 for (
const auto &AvailableLoad : AvailableLoads) {
1619 BasicBlock *UnavailableBlock = AvailableLoad.first;
1620 Value *LoadPtr = AvailableLoad.second;
1622 auto *NewLoad =
new LoadInst(
1623 Load->getType(), LoadPtr,
Load->getName() +
".pre",
Load->isVolatile(),
1624 Load->getAlign(),
Load->getOrdering(),
Load->getSyncScopeID(),
1626 NewLoad->setDebugLoc(
Load->getDebugLoc());
1628 auto *NewAccess = MSSAU->createMemoryAccessInBB(
1631 MSSAU->insertDef(NewDef,
true);
1637 AAMDNodes Tags =
Load->getAAMetadata();
1639 NewLoad->setAAMetadata(Tags);
1641 if (
auto *MD =
Load->getMetadata(LLVMContext::MD_invariant_load))
1642 NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
1643 if (
auto *InvGroupMD =
Load->getMetadata(LLVMContext::MD_invariant_group))
1644 NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
1645 if (
auto *RangeMD =
Load->getMetadata(LLVMContext::MD_range))
1646 NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
1647 if (
auto *NoFPClassMD =
Load->getMetadata(LLVMContext::MD_nofpclass))
1648 NewLoad->setMetadata(LLVMContext::MD_nofpclass, NoFPClassMD);
1650 if (
auto *AccessMD =
Load->getMetadata(LLVMContext::MD_access_group))
1651 if (LI->getLoopFor(
Load->getParent()) == LI->getLoopFor(UnavailableBlock))
1652 NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
1661 ValuesPerBlock.push_back(
1664 MD->invalidateCachedPointerInfo(LoadPtr);
1669 if (CriticalEdgePredAndLoad) {
1670 auto It = CriticalEdgePredAndLoad->
find(UnavailableBlock);
1671 if (It != CriticalEdgePredAndLoad->
end()) {
1672 ++NumPRELoadMoved2CEPred;
1673 ICF->insertInstructionTo(NewLoad, UnavailableBlock);
1674 LoadInst *OldLoad = It->second;
1678 if (uint32_t ValNo = VN.lookup(OldLoad,
false))
1679 LeaderTable.erase(ValNo, OldLoad, OldLoad->
getParent());
1680 removeInstruction(OldLoad);
1688 ICF->removeUsersOf(Load);
1689 Load->replaceAllUsesWith(V);
1693 I->setDebugLoc(
Load->getDebugLoc());
1694 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
1695 MD->invalidateCachedPointerInfo(V);
1697 return OptimizationRemark(
DEBUG_TYPE,
"LoadPRE", Load)
1698 <<
"load eliminated by PRE";
1703bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
1704 UnavailBlkVect &UnavailableBlocks) {
1713 SmallPtrSet<BasicBlock *, 4> Blockers(
llvm::from_range, UnavailableBlocks);
1735 bool MustEnsureSafetyOfSpeculativeExecution =
1736 ICF->isDominatedByICFIFromSameBlock(Load);
1740 if (TmpBB == LoadBB)
1742 if (Blockers.count(TmpBB))
1754 MustEnsureSafetyOfSpeculativeExecution =
1755 MustEnsureSafetyOfSpeculativeExecution || ICF->hasICF(TmpBB);
1763 MapVector<BasicBlock *, Value *> PredLoads;
1764 DenseMap<BasicBlock *, AvailabilityState> FullyAvailableBlocks;
1765 for (
const AvailableValueInBlock &AV : ValuesPerBlock)
1767 for (BasicBlock *UnavailableBB : UnavailableBlocks)
1775 MapVector<BasicBlock *, LoadInst *> CriticalEdgePredAndLoad;
1781 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
1782 << Pred->
getName() <<
"': " << *Load <<
'\n');
1793 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
1794 << Pred->
getName() <<
"': " << *Load <<
'\n');
1800 dbgs() <<
"COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
1801 << Pred->
getName() <<
"': " << *Load <<
'\n');
1807 if (DT->dominates(LoadBB, Pred)) {
1810 <<
"COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
1811 << Pred->
getName() <<
"': " << *Load <<
'\n');
1815 if (LoadInst *LI = findLoadToHoistIntoPred(Pred, LoadBB, Load))
1816 CriticalEdgePredAndLoad[Pred] = LI;
1821 PredLoads[Pred] =
nullptr;
1826 unsigned NumInsertPreds = PredLoads.
size() + CriticalEdgePredSplit.
size();
1827 unsigned NumUnavailablePreds = NumInsertPreds +
1828 CriticalEdgePredAndLoad.
size();
1829 assert(NumUnavailablePreds != 0 &&
1830 "Fully available value should already be eliminated!");
1831 (void)NumUnavailablePreds;
1837 if (NumInsertPreds > 1)
1842 if (MustEnsureSafetyOfSpeculativeExecution) {
1843 if (CriticalEdgePredSplit.
size())
1847 for (
auto &PL : PredLoads)
1851 for (
auto &CEP : CriticalEdgePredAndLoad)
1858 for (BasicBlock *OrigPred : CriticalEdgePredSplit) {
1859 BasicBlock *NewPred = splitCriticalEdges(OrigPred, LoadBB);
1860 assert(!PredLoads.count(OrigPred) &&
"Split edges shouldn't be in map!");
1861 PredLoads[NewPred] =
nullptr;
1862 LLVM_DEBUG(
dbgs() <<
"Split critical edge " << OrigPred->getName() <<
"->"
1863 << LoadBB->
getName() <<
'\n');
1866 for (
auto &CEP : CriticalEdgePredAndLoad)
1867 PredLoads[CEP.first] =
nullptr;
1870 bool CanDoPRE =
true;
1871 const DataLayout &
DL =
Load->getDataLayout();
1872 SmallVector<Instruction*, 8> NewInsts;
1873 for (
auto &PredLoad : PredLoads) {
1874 BasicBlock *UnavailablePred = PredLoad.first;
1884 Value *LoadPtr =
Load->getPointerOperand();
1886 while (Cur != LoadBB) {
1899 LoadPtr =
Address.translateWithInsertion(LoadBB, UnavailablePred, *DT,
1906 << *
Load->getPointerOperand() <<
"\n");
1911 PredLoad.second = LoadPtr;
1915 while (!NewInsts.
empty()) {
1925 return !CriticalEdgePredSplit.empty();
1931 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOAD: " << *Load <<
'\n');
1933 <<
" INSTS: " << *NewInsts.
back()
1937 for (Instruction *
I : NewInsts) {
1941 I->updateLocationAfterHoist();
1950 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, PredLoads,
1951 &CriticalEdgePredAndLoad);
1956bool GVNPass::performLoopLoadPRE(LoadInst *Load,
1957 AvailValInBlkVect &ValuesPerBlock,
1958 UnavailBlkVect &UnavailableBlocks) {
1959 const Loop *
L = LI->getLoopFor(
Load->getParent());
1961 if (!L ||
L->getHeader() !=
Load->getParent())
1966 if (!Preheader || !Latch)
1969 Value *LoadPtr =
Load->getPointerOperand();
1971 if (!
L->isLoopInvariant(LoadPtr))
1977 if (ICF->isDominatedByICFIFromSameBlock(Load))
1981 for (
auto *Blocker : UnavailableBlocks) {
1983 if (!
L->contains(Blocker))
1995 if (L != LI->getLoopFor(Blocker))
2003 if (DT->dominates(Blocker, Latch))
2007 if (Blocker->getTerminator()->mayWriteToMemory())
2010 LoopBlock = Blocker;
2022 MapVector<BasicBlock *, Value *> AvailableLoads;
2023 AvailableLoads[LoopBlock] = LoadPtr;
2024 AvailableLoads[Preheader] = LoadPtr;
2026 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING PRE LOOP LOAD: " << *Load <<
'\n');
2027 eliminatePartiallyRedundantLoad(Load, ValuesPerBlock, AvailableLoads,
2035 using namespace ore;
2039 <<
"load of type " << NV(
"Type", Load->getType()) <<
" eliminated"
2040 << setExtraArgs() <<
" in favor of "
2047bool GVNPass::processNonLocalLoad(LoadInst *Load) {
2049 if (
Load->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2050 Load->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2055 MD->getNonLocalPointerDependency(Load, Deps);
2060 unsigned NumDeps = Deps.size();
2067 for (
const NonLocalDepResult &Dep : Deps) {
2068 const auto &
R = Dep.getResult();
2069 SelectAddr SelAddr = Dep.getAddress();
2075 ReachingMemVal::getSelect(BB,
Cond, Addrs.first, Addrs.second));
2087 return processNonLocalLoad(Load, MemVals);
2090bool GVNPass::processNonLocalLoad(LoadInst *Load,
2091 SmallVectorImpl<ReachingMemVal> &Deps) {
2094 if (Deps.
size() == 1 && Deps[0].Kind == DepKind::Other) {
2096 dbgs() <<
" has unknown dependencies\n";);
2104 if (GetElementPtrInst *
GEP =
2106 for (Use &U :
GEP->indices())
2113 AvailValInBlkVect ValuesPerBlock;
2114 UnavailBlkVect UnavailableBlocks;
2115 AnalyzeLoadAvailability(Load, Deps, ValuesPerBlock, UnavailableBlocks);
2119 if (ValuesPerBlock.empty())
2127 if (UnavailableBlocks.empty()) {
2128 LLVM_DEBUG(
dbgs() <<
"GVN REMOVING NONLOCAL LOAD: " << *Load <<
'\n');
2133 ICF->removeUsersOf(Load);
2134 Load->replaceAllUsesWith(V);
2142 if (
Load->getDebugLoc() &&
Load->getParent() ==
I->getParent())
2143 I->setDebugLoc(
Load->getDebugLoc());
2144 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
2145 MD->invalidateCachedPointerInfo(V);
2158 if (performLoopLoadPRE(Load, ValuesPerBlock, UnavailableBlocks) ||
2159 PerformLoadPRE(Load, ValuesPerBlock, UnavailableBlocks))
2165bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2169 if (
Cond->isZero()) {
2179 const MemoryUseOrDef *FirstNonDom =
nullptr;
2181 MSSAU->getMemorySSA()->getBlockAccesses(IntrinsicI->
getParent());
2188 for (
const auto &Acc : *AL) {
2190 if (!Current->getMemoryInst()->comesBefore(NewS)) {
2191 FirstNonDom = Current;
2198 FirstNonDom ? MSSAU->createMemoryAccessBefore(
2200 const_cast<MemoryUseOrDef *
>(FirstNonDom))
2201 : MSSAU->createMemoryAccessInBB(
2223 return propagateEquality(V, True, IntrinsicI);
2228 I->replaceAllUsesWith(Repl);
2235 Value *PointerOperand = L->getPointerOperand()->stripPointerCasts();
2246 PointerUsesQueue.
push_back(PointerOperand);
2251 while (!PointerUsesQueue.
empty()) {
2254 "Null or GlobalValue should not be inserted");
2258 if (!
I ||
I == L || !DT.
dominates(
I, MostDominatingInstruction))
2273 if (
I->hasMetadata(LLVMContext::MD_invariant_group) &&
2275 MostDominatingInstruction =
I;
2279 return MostDominatingInstruction != L ? MostDominatingInstruction :
nullptr;
2285static std::optional<MemoryLocation>
2292 switch (
II->getIntrinsicID()) {
2293 case Intrinsic::masked_load:
2295 case Intrinsic::masked_store:
2298 return std::nullopt;
2305 return std::nullopt;
2309 return std::nullopt;
2315std::optional<GVNPass::ReachingMemVal> GVNPass::scanMemoryAccessesUsers(
2316 const MemoryLocation &Loc,
bool IsInvariantLoad, BasicBlock *BB,
2317 const SmallVectorImpl<MemoryAccess *> &ClobbersList,
MemorySSA &MSSA,
2318 BatchAAResults &AA, LoadInst *L) {
2321 auto UpdateChoice = [&](std::optional<ReachingMemVal> &Choice,
2325 Choice = ReachingMemVal::getClobber(Loc.
Ptr, Candidate, AR.getOffset());
2327 Choice = ReachingMemVal::getDef(Loc.
Ptr, Candidate);
2335 Choice->Kind = DepKind::Clobber;
2336 Choice->Offset = AR.getOffset();
2338 Choice->Kind = DepKind::Def;
2339 Choice->Offset = -1;
2342 Choice->Inst = Candidate;
2343 Choice->Block = Candidate->getParent();
2346 std::optional<ReachingMemVal> ReachingVal;
2347 for (MemoryAccess *MA : ClobbersList) {
2349 for (User *U : MA->
users()) {
2351 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2354 if (!UseOrDef || UseOrDef->getBlock() != BB)
2363 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2377 UpdateChoice(ReachingVal, AR, MemI);
2389std::optional<GVNPass::ReachingMemVal> GVNPass::accessMayModifyLocation(
2390 MemoryAccess *ClobberMA,
const MemoryLocation &Loc,
bool IsInvariantLoad,
2391 BasicBlock *BB,
MemorySSA &MSSA, BatchAAResults &AA) {
2399 if (
Alloc->getParent() == BB)
2400 return ReachingMemVal::getDef(Loc.
Ptr,
const_cast<AllocaInst *
>(
Alloc));
2401 return ReachingMemVal::getUnknown(BB, Loc.
Ptr);
2405 if (IsInvariantLoad || AA.pointsToConstantMemory(Loc))
2406 return std::nullopt;
2410 return L->getOrdering();
2417 AliasResult AR = AA.alias(*MaybeLoc, Loc);
2419 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2430 return std::nullopt;
2431 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2436 return std::nullopt;
2441 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2446 "Must be the superset/partial overlap case with positive offset");
2447 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI, AR.
getOffset());
2452 return std::nullopt;
2453 if (
II->getIntrinsicID() == Intrinsic::lifetime_start) {
2455 if (AA.isMustAlias(IIObjLoc, Loc))
2456 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2457 return std::nullopt;
2465 if (Obj == ClobberI || AA.isMustAlias(ClobberI, Loc.
Ptr))
2466 return ReachingMemVal::getDef(Loc.
Ptr, ClobberI);
2472 return std::nullopt;
2476 ModRefInfo MR = AA.getModRefInfo(ClobberI, Loc);
2480 return std::nullopt;
2484 return ReachingMemVal::getClobber(Loc.
Ptr, ClobberI);
2490bool GVNPass::collectPredecessors(BasicBlock *BB,
const PHITransAddr &Addr,
2491 MemoryAccess *ClobberMA,
2492 DependencyBlockSet &Blocks,
2493 SmallVectorImpl<BasicBlock *> &Worklist) {
2503 if (!DT->isReachableFromEntry(Pred))
2507 if (
llvm::any_of(Preds, [Pred](
const auto &
P) {
return P.first == Pred; }))
2510 PHITransAddr TransAddr = Addr;
2514 auto It = Blocks.find(Pred);
2515 if (It != Blocks.end()) {
2519 if (It->second.Addr.getAddr() != TransAddr.
getAddr())
2526 Pred, DependencyBlockInfo(TransAddr,
2527 MPhi ? MPhi->getIncomingValueForBlock(Pred)
2534 for (
auto &
P : Preds) {
2535 [[maybe_unused]]
auto It =
2536 Blocks.try_emplace(
P.first, std::move(
P.second)).first;
2548void GVNPass::collectClobberList(SmallVectorImpl<MemoryAccess *> &Clobbers,
2550 const DependencyBlockInfo &StartInfo,
2551 const DependencyBlockSet &Blocks,
2553 MemoryAccess *MA = StartInfo.InitialClobberMA;
2554 MemoryAccess *LastMA = StartInfo.ClobberMA;
2557 while (MA != LastMA) {
2571 BB = DT->getNode(BB)->getIDom()->getBlock();
2575 auto It = Blocks.find(BB);
2576 if (It == Blocks.end())
2579 MA = It->second.InitialClobberMA;
2580 LastMA = It->second.ClobberMA;
2581 if (MA == Clobbers.
back())
2598bool GVNPass::findReachingValuesForLoad(LoadInst *L,
2599 SmallVectorImpl<ReachingMemVal> &
Values,
2601 EarliestEscapeAnalysis EA(*DT, LI);
2602 BatchAAResults AA(AAR, &EA);
2604 bool IsInvariantLoad =
L->hasMetadata(LLVMContext::MD_invariant_load);
2610 if (
L->hasMetadata(LLVMContext::MD_invariant_group)) {
2623 if (
auto RMV = scanMemoryAccessesUsers(
2624 Loc, IsInvariantLoad, StartBlock,
2626 Values.emplace_back(*RMV);
2636 if (
auto RMV = accessMayModifyLocation(ClobberMA, Loc, IsInvariantLoad,
2637 StartBlock, MSSA, AA)) {
2638 Values.emplace_back(*RMV);
2645 }
while (ClobberMA->
getBlock() == StartBlock);
2648 if (
L->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) ||
2649 L->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress))
2658 DependencyBlockSet Blocks;
2659 SmallVector<BasicBlock *, 16> InitialWorklist;
2660 const DataLayout &
DL =
L->getModule()->getDataLayout();
2661 if (!collectPredecessors(StartBlock,
2662 PHITransAddr(
L->getPointerOperand(),
DL, AC),
2663 ClobberMA, Blocks, InitialWorklist))
2667 auto Worklist = InitialWorklist;
2668 while (!Worklist.
empty()) {
2670 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2673 if (!
Info.Addr.getAddr())
2681 if (
auto RMV = accessMayModifyLocation(
2683 IsInvariantLoad, BB, MSSA, AA)) {
2688 "LiveOnEntry aliases everything");
2704 if (BB == StartBlock &&
Info.Addr.getAddr() !=
L->getPointerOperand()) {
2705 Info.ForceUnknown =
true;
2708 if (BB != StartBlock &&
2709 !collectPredecessors(BB,
Info.Addr,
Info.ClobberMA, Blocks, Worklist))
2710 Info.ForceUnknown =
true;
2720 Worklist = InitialWorklist;
2721 for (BasicBlock *BB : Worklist) {
2722 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2723 Info.Visited =
true;
2727 while (!Worklist.empty()) {
2728 auto *BB = Worklist.pop_back_val();
2729 DependencyBlockInfo &
Info = Blocks.find(BB)->second;
2733 if (!
Info.Addr.getAddr()) {
2734 Values.push_back(ReachingMemVal::getUnknown(BB,
nullptr));
2739 collectClobberList(Clobbers, BB, Info, Blocks, MSSA);
2742 IsInvariantLoad, BB, Clobbers, MSSA, AA)) {
2754 if (
Info.ForceUnknown) {
2755 Values.push_back(ReachingMemVal::getUnknown(BB,
Info.Addr.getAddr()));
2761 auto It = Blocks.find(Pred);
2762 if (It == Blocks.end())
2764 DependencyBlockInfo &PredInfo = It->second;
2765 if (PredInfo.Visited)
2767 PredInfo.Visited =
true;
2768 Worklist.push_back(Pred);
2777bool GVNPass::processLoad(LoadInst *L) {
2782 if (!
L->isUnordered())
2785 if (
L->getType()->isTokenLikeTy())
2788 if (
L->use_empty()) {
2793 ReachingMemVal MemVal = ReachingMemVal::getUnknown(
nullptr,
nullptr);
2796 MemDepResult Dep = MD->getDependency(L);
2800 return processNonLocalLoad(L);
2804 MemVal = ReachingMemVal::getDef(
L->getPointerOperand(), Dep.
getInst());
2807 ReachingMemVal::getClobber(
L->getPointerOperand(), Dep.
getInst());
2810 if (!findReachingValuesForLoad(L, MemVals, *MSSAU->getMemorySSA(), *AA))
2812 assert(MemVals.
size() &&
"Expected at least an unknown value");
2813 if (MemVals.
size() > 1 || MemVals[0].Block !=
L->getParent())
2814 return processNonLocalLoad(L, MemVals);
2816 MemVal = MemVals[0];
2819 if (MemVal.Kind == DepKind::Other) {
2823 dbgs() <<
"GVN: load ";
L->printAsOperand(
dbgs());
2824 dbgs() <<
" has unknown dependence\n";);
2828 auto AV = AnalyzeLoadAvailability(L, MemVal,
L->getPointerOperand());
2832 Value *AvailableValue = AV->MaterializeAdjustedValue(L, L);
2835 ICF->removeUsersOf(L);
2836 L->replaceAllUsesWith(AvailableValue);
2838 MSSAU->removeMemoryAccess(L);
2845 MD->invalidateCachedPointerInfo(AvailableValue);
2851bool GVNPass::processMaskedLoad(IntrinsicInst *
I) {
2854 MemDepResult Dep = MD->getDependency(
I);
2860 Value *Passthrough =
I->getOperand(2);
2864 StoreVal->
getType() !=
I->getType())
2871 ICF->removeUsersOf(
I);
2872 I->replaceAllUsesWith(OpToForward);
2880std::pair<uint32_t, bool>
2881GVNPass::ValueTable::assignExpNewValueNum(
Expression &Exp) {
2882 uint32_t &
E = ExpressionNumbering[
Exp];
2883 bool CreateNewValNum = !
E;
2884 if (CreateNewValNum) {
2885 Expressions.push_back(Exp);
2886 if (ExprIdx.size() < NextValueNumber + 1)
2887 ExprIdx.resize(NextValueNumber * 2);
2888 E = NextValueNumber;
2889 ExprIdx[NextValueNumber++] = NextExprNumber++;
2891 return {
E, CreateNewValNum};
2896bool GVNPass::ValueTable::areAllValsInBB(uint32_t Num,
const BasicBlock *BB,
2899 GVN.LeaderTable.getLeaders(Num),
2907 auto FindRes = PhiTranslateTable.find({Num, Pred});
2908 if (FindRes != PhiTranslateTable.end())
2909 return FindRes->second;
2910 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, GVN);
2911 PhiTranslateTable.insert({{Num, Pred}, NewNum});
2922 auto Leaders = GVN.LeaderTable.getLeaders(Num);
2923 for (
const auto &Entry : Leaders) {
2925 if (
Call &&
Call->getParent() == PhiBlock)
2929 if (
AA->doesNotAccessMemory(
Call))
2932 if (!MD || !
AA->onlyReadsMemory(
Call))
2944 if (
D.getResult().isNonFuncLocal())
2952uint32_t GVNPass::ValueTable::phiTranslateImpl(
const BasicBlock *Pred,
2953 const BasicBlock *PhiBlock,
2957 if (PHINode *PN = NumberingPhi[Num]) {
2958 if (PN->getParent() != PhiBlock)
2960 for (
unsigned I = 0;
I != PN->getNumIncomingValues(); ++
I) {
2961 if (PN->getIncomingBlock(
I) != Pred)
2963 if (uint32_t TransVal =
lookup(PN->getIncomingValue(
I),
false))
2969 if (BasicBlock *BB = NumberingBB[Num]) {
2970 assert(MSSA &&
"NumberingBB is non-empty only when using MemorySSA");
2982 return lookupOrAdd(PredPhi->getBlock());
2988 "CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
2994 if (!areAllValsInBB(Num, PhiBlock, GVN))
2997 if (Num >= ExprIdx.size() || ExprIdx[Num] == 0)
3001 for (
unsigned I = 0;
I <
Exp.VarArgs.size();
I++) {
3005 if ((
I > 1 &&
Exp.Opcode == Instruction::InsertValue) ||
3006 (
I > 0 &&
Exp.Opcode == Instruction::ExtractValue) ||
3007 (
I > 1 &&
Exp.Opcode == Instruction::ShuffleVector))
3009 Exp.VarArgs[
I] = phiTranslate(Pred, PhiBlock,
Exp.VarArgs[
I], GVN);
3012 if (
Exp.Commutative) {
3013 assert(
Exp.VarArgs.size() >= 2 &&
"Unsupported commutative instruction!");
3014 if (
Exp.VarArgs[0] >
Exp.VarArgs[1]) {
3016 uint32_t Opcode =
Exp.Opcode >> 8;
3017 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
3018 Exp.Opcode = (Opcode << 8) |
3024 if (uint32_t NewNum = ExpressionNumbering[Exp]) {
3025 if (
Exp.Opcode == Instruction::Call && NewNum != Num)
3026 return areCallValsEqual(Num, NewNum, Pred, PhiBlock, GVN) ? NewNum : Num;
3034void GVNPass::ValueTable::eraseTranslateCacheEntry(
3037 PhiTranslateTable.erase({Num, Pred});
3046 auto Leaders = LeaderTable.getLeaders(Num);
3047 if (Leaders.empty())
3050 Value *Val =
nullptr;
3051 for (
const auto &Entry : Leaders) {
3052 if (DT->dominates(Entry.BB, BB)) {
3072 const BasicBlock *Pred =
E.getEnd()->getSinglePredecessor();
3073 assert((!Pred || Pred ==
E.getStart()) &&
3074 "No edge between these basic blocks!");
3075 return Pred !=
nullptr;
3078void GVNPass::assignBlockRPONumber(Function &
F) {
3079 BlockRPONumber.clear();
3080 uint32_t NextBlockNumber = 1;
3081 ReversePostOrderTraversal<Function *> RPOT(&
F);
3082 for (BasicBlock *BB : RPOT)
3083 BlockRPONumber[BB] = NextBlockNumber++;
3084 InvalidBlockRPONumbers =
false;
3092bool GVNPass::propagateEquality(
3094 const std::variant<BasicBlockEdge, Instruction *> &Root) {
3099 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3106 for (
const auto *Node : DT->getNode(
I->getParent())->children())
3110 while (!Worklist.
empty()) {
3111 std::pair<Value*, Value*> Item = Worklist.
pop_back_val();
3112 LHS = Item.first;
RHS = Item.second;
3126 const DataLayout &
DL =
3135 uint32_t LVN = VN.lookupOrAdd(
LHS);
3140 uint32_t RVN = VN.lookupOrAdd(
RHS);
3157 for (
const BasicBlock *BB : DominatedBlocks)
3158 LeaderTable.insert(LVN,
RHS, BB);
3165 auto CanReplacePointersCallBack = [&
DL](
const Use &
U,
const Value *To) {
3168 unsigned NumReplacements;
3169 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3171 LHS,
RHS, *DT, *
Edge, CanReplacePointersCallBack);
3174 LHS,
RHS, *DT, std::get<Instruction *>(Root),
3175 CanReplacePointersCallBack);
3177 if (NumReplacements > 0) {
3179 NumGVNEqProp += NumReplacements;
3182 MD->invalidateCachedPointerInfo(
LHS);
3199 bool IsKnownFalse = !IsKnownTrue;
3215 Value *Op0 =
Cmp->getOperand(0), *Op1 =
Cmp->getOperand(1);
3220 if (
Cmp->isEquivalence(IsKnownFalse))
3221 Worklist.
push_back(std::make_pair(Op0, Op1));
3225 Constant *NotVal = ConstantInt::get(
Cmp->getType(), IsKnownFalse);
3229 uint32_t NextNum = VN.getNextUnusedValueNumber();
3230 uint32_t Num = VN.lookupOrAddCmp(
Cmp->getOpcode(), NotPred, Op0, Op1);
3233 if (Num < NextNum) {
3234 for (
const auto &Entry : LeaderTable.getLeaders(Num)) {
3239 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root)) {
3240 if (!DT->dominates(
Entry.BB,
Edge->getStart()) &&
3241 !DT->dominates(
Edge->getEnd(),
Entry.BB))
3244 auto *InstBB = std::get<Instruction *>(Root)->getParent();
3245 if (!DT->dominates(
Entry.BB, InstBB) &&
3246 !DT->dominates(InstBB,
Entry.BB))
3252 unsigned NumReplacements;
3253 if (
const BasicBlockEdge *
Edge = std::get_if<BasicBlockEdge>(&Root))
3258 NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
3259 Changed |= NumReplacements > 0;
3260 NumGVNEqProp += NumReplacements;
3263 MD->invalidateCachedPointerInfo(NotCmp);
3271 for (
const BasicBlock *BB : DominatedBlocks)
3272 LeaderTable.insert(Num, NotVal, BB);
3281 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), IsKnownTrue));
3286 Worklist.
emplace_back(
A, ConstantInt::get(
A->getType(), !IsKnownTrue));
3296bool GVNPass::processInstruction(Instruction *
I) {
3301 const DataLayout &
DL =
I->getDataLayout();
3304 if (!
I->use_empty()) {
3307 ICF->removeUsersOf(
I);
3308 I->replaceAllUsesWith(V);
3316 if (MD &&
V->getType()->isPtrOrPtrVectorTy())
3317 MD->invalidateCachedPointerInfo(V);
3324 return processAssumeIntrinsic(Assume);
3327 if (processLoad(Load))
3330 unsigned Num = VN.lookupOrAdd(Load);
3331 LeaderTable.insert(Num, Load,
Load->getParent());
3343 return processFoldableCondBr(BI);
3345 Value *BranchCond = BI->getCondition();
3349 if (TrueSucc == FalseSucc)
3356 BasicBlockEdge TrueE(Parent, TrueSucc);
3357 Changed |= propagateEquality(BranchCond, TrueVal, TrueE);
3360 BasicBlockEdge FalseE(Parent, FalseSucc);
3361 Changed |= propagateEquality(BranchCond, FalseVal, FalseE);
3368 Value *SwitchCond =
SI->getCondition();
3373 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
3375 ++SwitchEdges[Succ];
3377 for (
const auto &Case :
SI->cases()) {
3380 if (SwitchEdges.
lookup(Dst) == 1) {
3381 BasicBlockEdge
E(Parent, Dst);
3382 Changed |= propagateEquality(SwitchCond, Case.getCaseValue(),
E);
3390 if (
I->getType()->isVoidTy())
3393 uint32_t NextNum = VN.getNextUnusedValueNumber();
3394 unsigned Num = VN.lookupOrAdd(
I);
3399 LeaderTable.insert(Num,
I,
I->getParent());
3406 if (Num >= NextNum) {
3407 LeaderTable.insert(Num,
I,
I->getParent());
3413 Value *Repl = findLeader(
I->getParent(), Num);
3416 LeaderTable.insert(Num,
I,
I->getParent());
3429 MD->invalidateCachedPointerInfo(Repl);
3435bool GVNPass::runImpl(Function &
F, AssumptionCache &RunAC, DominatorTree &RunDT,
3436 const TargetLibraryInfo &RunTLI, AAResults &RunAA,
3437 MemoryDependenceResults *RunMD, LoopInfo &LI,
3438 OptimizationRemarkEmitter *RunORE,
MemorySSA *MSSA) {
3444 VN.setAliasAnalysis(&RunAA);
3446 ImplicitControlFlowTracking ImplicitCFT;
3455 InvalidBlockRPONumbers =
true;
3456 MemorySSAUpdater Updater(MSSA);
3457 MSSAU = MSSA ? &Updater :
nullptr;
3460 bool ShouldContinue =
true;
3462 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
3474 unsigned Iteration = 0;
3475 while (ShouldContinue) {
3478 ShouldContinue = iterateOnFunction(
F);
3486 assignValNumForDeadCode();
3487 bool PREChanged =
true;
3488 while (PREChanged) {
3489 PREChanged = performPRE(
F);
3499 cleanupGlobalSets();
3510bool GVNPass::processBlock(BasicBlock *BB) {
3511 if (DeadBlocks.count(BB))
3514 bool ChangedFunction =
false;
3520 SmallPtrSet<PHINode *, 8> PHINodesToRemove;
3522 for (PHINode *PN : PHINodesToRemove) {
3523 removeInstruction(PN);
3526 ChangedFunction |= processInstruction(&Inst);
3527 return ChangedFunction;
3531bool GVNPass::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
3532 BasicBlock *Curr,
unsigned int ValNo) {
3538 for (
unsigned I = 0,
E =
Instr->getNumOperands();
I !=
E; ++
I) {
3546 if (!VN.exists(
Op)) {
3551 VN.phiTranslate(Pred, Curr, VN.lookup(
Op), *
this);
3552 if (
Value *V = findLeader(Pred, TValNo)) {
3570 ICF->insertInstructionTo(Instr, Pred);
3572 unsigned Num = VN.lookupOrAdd(Instr);
3576 LeaderTable.insert(Num, Instr, Pred);
3580bool GVNPass::performScalarPRE(Instruction *CurInst) {
3606 if (CallB->isInlineAsm())
3610 uint32_t ValNo = VN.lookup(CurInst);
3618 unsigned NumWith = 0;
3619 unsigned NumWithout = 0;
3624 if (InvalidBlockRPONumbers)
3625 assignBlockRPONumber(*CurrentBlock->
getParent());
3631 if (!DT->isReachableFromEntry(
P)) {
3636 assert(BlockRPONumber.count(
P) && BlockRPONumber.count(CurrentBlock) &&
3637 "Invalid BlockRPONumber map.");
3638 if (BlockRPONumber[
P] >= BlockRPONumber[CurrentBlock]) {
3643 uint32_t TValNo = VN.phiTranslate(
P, CurrentBlock, ValNo, *
this);
3644 Value *PredV = findLeader(
P, TValNo);
3649 }
else if (PredV == CurInst) {
3661 if (NumWithout > 1 || NumWith == 0)
3669 if (NumWithout != 0) {
3675 if (ICF->isDominatedByICFIFromSameBlock(CurInst))
3688 ToSplit.push_back(std::make_pair(PREPred->
getTerminator(), SuccNum));
3692 PREInstr = CurInst->
clone();
3693 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
3696 verifyRemoved(PREInstr);
3705 assert(PREInstr !=
nullptr || NumWithout == 0);
3711 CurInst->
getName() +
".pre-phi");
3712 Phi->insertBefore(CurrentBlock->begin());
3713 for (
auto &[V, BB] : PredMap) {
3718 Phi->addIncoming(V, BB);
3720 Phi->addIncoming(PREInstr, PREPred);
3726 VN.eraseTranslateCacheEntry(ValNo, *CurrentBlock);
3727 LeaderTable.insert(ValNo, Phi, CurrentBlock);
3730 if (MD &&
Phi->getType()->isPtrOrPtrVectorTy())
3731 MD->invalidateCachedPointerInfo(Phi);
3732 LeaderTable.erase(ValNo, CurInst, CurrentBlock);
3735 removeInstruction(CurInst);
3742bool GVNPass::performPRE(Function &
F) {
3744 for (BasicBlock *CurrentBlock :
depth_first(&
F.getEntryBlock())) {
3746 if (CurrentBlock == &
F.getEntryBlock())
3750 if (CurrentBlock->isEHPad())
3754 BE = CurrentBlock->end();
3757 Changed |= performScalarPRE(CurInst);
3761 if (splitCriticalEdges())
3769BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
3774 CriticalEdgeSplittingOptions(DT, LI, MSSAU).unsetPreserveLoopSimplify());
3777 MD->invalidateCachedPredecessors();
3778 InvalidBlockRPONumbers =
true;
3785bool GVNPass::splitCriticalEdges() {
3786 if (ToSplit.empty())
3791 std::pair<Instruction *, unsigned>
Edge = ToSplit.pop_back_val();
3793 CriticalEdgeSplittingOptions(DT, LI, MSSAU)) !=
3795 }
while (!ToSplit.empty());
3798 MD->invalidateCachedPredecessors();
3799 InvalidBlockRPONumbers =
true;
3805bool GVNPass::iterateOnFunction(Function &
F) {
3806 cleanupGlobalSets();
3813 ReversePostOrderTraversal<Function *> RPOT(&
F);
3815 for (BasicBlock *BB : RPOT)
3821void GVNPass::cleanupGlobalSets() {
3823 LeaderTable.clear();
3824 BlockRPONumber.clear();
3826 InvalidBlockRPONumbers =
true;
3829void GVNPass::removeInstruction(Instruction *
I) {
3831 if (MD) MD->removeInstruction(
I);
3833 MSSAU->removeMemoryAccess(
I);
3837 ICF->removeInstruction(
I);
3838 I->eraseFromParent();
3844void GVNPass::verifyRemoved(
const Instruction *Inst)
const {
3845 VN.verifyRemoved(Inst);
3852void GVNPass::addDeadBlock(BasicBlock *BB) {
3854 SmallSetVector<BasicBlock *, 4>
DF;
3857 while (!NewDead.
empty()) {
3859 if (DeadBlocks.count(
D))
3863 SmallVector<BasicBlock *, 8> Dom;
3864 DT->getDescendants(
D, Dom);
3865 DeadBlocks.insert_range(Dom);
3868 for (BasicBlock *
B : Dom) {
3870 if (DeadBlocks.count(S))
3873 bool AllPredDead =
true;
3875 if (!DeadBlocks.count(
P)) {
3876 AllPredDead =
false;
3896 for (BasicBlock *
B :
DF) {
3897 if (DeadBlocks.count(
B))
3903 for (BasicBlock *
P : Preds) {
3904 if (!DeadBlocks.count(
P))
3909 if (BasicBlock *S = splitCriticalEdges(
P,
B))
3910 DeadBlocks.insert(
P = S);
3916 if (!DeadBlocks.count(
P))
3918 for (PHINode &Phi :
B->phis()) {
3921 MD->invalidateCachedPointerInfo(&Phi);
3940bool GVNPass::processFoldableCondBr(CondBrInst *BI) {
3951 if (DeadBlocks.count(DeadRoot))
3955 DeadRoot = splitCriticalEdges(BI->getParent(), DeadRoot);
3957 addDeadBlock(DeadRoot);
3965void GVNPass::assignValNumForDeadCode() {
3966 for (BasicBlock *BB : DeadBlocks) {
3967 for (Instruction &Inst : *BB) {
3968 unsigned ValNum = VN.lookupOrAdd(&Inst);
3969 LeaderTable.insert(ValNum, &Inst, BB);
3980 bool ScalarPRE =
true)
3982 .setMemDep(MemDepAnalysis)
3983 .setMemorySSA(MemSSAAnalysis)
3984 .setScalarPRE(ScalarPRE)) {
3993 if (Impl.isMemorySSAEnabled() && !MSSAWP)
3996 return Impl.runImpl(
4001 Impl.isMemDepEnabled()
4006 MSSAWP ? &MSSAWP->getMSSA() :
nullptr);
4014 if (Impl.isMemDepEnabled())
4023 if (Impl.isMemorySSAEnabled())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
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 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)
static cl::opt< uint32_t > MaxNumInsnsPerBlock("gvn-max-num-insns", cl::Hidden, cl::init(100), cl::desc("Max number of instructions to scan in each basic block in GVN " "(default = 100)"))
static cl::opt< bool > GVNEnableMemDep("enable-gvn-memdep", cl::init(true))
static cl::opt< bool > GVNEnableLoadInLoopPRE("enable-load-in-loop-pre", cl::init(true))
static const Instruction * findMayClobberedPtrAccess(LoadInst *Load, const DominatorTree *DT)
static cl::opt< uint32_t > MaxNumDeps("gvn-max-num-deps", cl::Hidden, cl::init(100), cl::desc("Max number of dependences to attempt Load PRE (default = 100)"))
static std::optional< MemoryLocation > maybeLoadStoreLocation(Instruction *I, bool AllowStores, const TargetLibraryInfo *TLI)
Return the memory location accessed by the (masked) load/store instruction I, if the instruction coul...
static cl::opt< bool > GVNEnableMemorySSA("enable-gvn-memoryssa", cl::init(false))
static bool isOnlyReachableViaThisEdge(const BasicBlockEdge &E, DominatorTree *DT)
There is an edge from 'Src' to 'Dst'.
static 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 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)"))
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.
@ 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))
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.
This class holds the mapping between values and value numbers.
LLVM_ABI uint32_t lookupOrAdd(MemoryAccess *MA)
The core GVN pass object.
friend class gvn::GVNLegacyPass
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
LLVM_ABI bool isMemDepEnabled() const
Legacy wrapper pass to provide the GlobalsAAResult object.
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
LLVM_ABI void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})
Drop all unknown metadata except for debug locations.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
The legacy pass manager's analysis pass to compute loop information.
iterator find(const KeyT &Key)
A memory dependence query can return one of three different answers.
bool isClobber() const
Tests if this MemDepResult represents a query that is an instruction clobber dependency.
bool isNonLocal() const
Tests if this MemDepResult represents a query that is transparent to the start of the block,...
bool isDef() const
Tests if this MemDepResult represents a query that is an instruction definition dependency.
bool isLocal() const
Tests if this MemDepResult represents a valid local query (Clobber/Def).
Instruction * getInst() const
If this is a normal dependency, returns the instruction that is depended on.
This is the common base class for memset/memcpy/memmove.
BasicBlock * getBlock() const
An analysis that produces MemoryDependenceResults for a function.
std::vector< NonLocalDepEntry > NonLocalDepInfo
LLVM_ABI MemDepResult getDependency(Instruction *QueryInst)
Returns the instruction on which a memory operation depends.
LLVM_ABI const NonLocalDepInfo & getNonLocalCallDependency(CallBase *QueryCall)
Perform a full dependency query for the specified call, returning the set of blocks that the value is...
A wrapper analysis pass for the legacy pass manager that exposes a MemoryDepnedenceResults instance.
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
MemoryLocation getWithNewPtr(const Value *NewPtr) const
const Value * Ptr
The address of the start of the location.
static LLVM_ABI MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
BasicBlock * getIncomingBlock(unsigned I) const
Return incoming basic block number i.
MemoryAccess * getIncomingValue(unsigned I) const
Return incoming value number x.
An analysis that produces MemorySSA for a function.
Legacy analysis pass which computes MemorySSA.
LLVM_ABI void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const
Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...
MemoryUseOrDef * getMemoryAccess(const Instruction *I) const
Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.
LLVM_ABI bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const
Given two memory accesses in the same basic block, determine whether MemoryAccess A dominates MemoryA...
bool isLiveOnEntryDef(const MemoryAccess *MA) const
Return true if MA represents the live on entry value.
MemoryAccess * getDefiningAccess() const
Get the access that produces the memory state used by this Use.
This is an entry in the NonLocalDepInfo cache.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
LLVM_ABI Value * translateValue(BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree *DT, bool MustDominate)
translateValue - PHI translate the current address up the CFG from CurBB to Pred, updating our state ...
LLVM_ABI bool isPotentiallyPHITranslatable() const
isPotentiallyPHITranslatable - If this needs PHI translation, return true if we have some hope of doi...
bool needsPHITranslationFromBlock(BasicBlock *BB) const
needsPHITranslationFromBlock - Return true if moving from the specified BasicBlock to its predecessor...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
AnalysisType * getAnalysisIfAvailable() const
getAnalysisIfAvailable<AnalysisType>() - Subclasses use this function to get analysis information tha...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Helper class for SSA formation on a set of values defined in multiple blocks.
LLVM_ABI void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
LLVM_ABI Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
LLVM_ABI bool HasValueForBlock(BasicBlock *BB) const
Return true if the SSAUpdater already has a value for the specified block.
LLVM_ABI void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
std::pair< Value *, SelectAddrs > getSelectCondAndAddrs() const
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
SmallVector & operator=(const SmallVector &RHS)
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI bool isTokenLikeTy() const
Returns true if this is 'token' or a token-like target type.s.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
bool hasUseList() const
Check if this Value has a use-list.
LLVM_ABI bool canBeFreed() const
Return true if the memory object referred to by V can by freed in the scope for which the SSA value d...
LLVM_ABI void deleteValue()
Delete a pointer to a generic Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
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)
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
An opaque object representing a hash code.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
m_Intrinsic_Ty< Opnd0, Opnd1, Opnd2 >::Ty m_MaskedStore(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedStore Intrinsic.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
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_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)
A private "module" namespace for types and utilities used by GVN.
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.
constexpr from_range_t from_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
LLVM_ABI bool isAssumeWithEmptyBundle(const AssumeInst &Assume)
Return true iff the operand bundles of the provided llvm.assume doesn't contain any valuable informat...
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
LLVM_ABI bool canReplacePointersInUseIfEqual(const Use &U, const Value *To, const DataLayout &DL)
LLVM_ABI bool canReplacePointersIfEqual(const Value *From, const Value *To, const DataLayout &DL)
Returns true if a pointer value From can be replaced with another pointer value \To if they are deeme...
bool isModSet(const ModRefInfo MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void patchReplacementInstruction(Instruction *I, Value *Repl)
Patch the replacement so that it is not more restrictive than the value being replaced.
LLVM_ABI void initializeGVNLegacyPassPass(PassRegistry &)
LLVM_ABI unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlockEdge &Edge)
Replace each use of 'From' with 'To' if that use is dominated by the given edge.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
bool operator==(const Expression &Other) const
friend hash_code hash_value(const Expression &Value)
SmallVector< uint32_t, 4 > VarArgs
Expression(uint32_t Op=~2U)
A CRTP mix-in to automatically provide informational APIs needed for passes.
Represents an AvailableValue which can be rematerialized at the end of the associated BasicBlock.
static AvailableValueInBlock get(BasicBlock *BB, Value *V, unsigned Offset=0)
static AvailableValueInBlock getUndef(BasicBlock *BB)
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV)
AvailableValue AV
AV - The actual available value.
BasicBlock * BB
BB - The basic block in question.
Value * MaterializeAdjustedValue(LoadInst *Load) const
Emit code at the end of this block to adjust the value defined here to the specified type.
Represents a particular available value that we know how to materialize.
unsigned Offset
Offset - The byte offset in Val that is interesting for the load query.
bool isSimpleValue() const
bool isCoercedLoadValue() const
static AvailableValue get(Value *V, unsigned Offset=0)
ValType Kind
Kind of the live-out value.
static AvailableValue getSelect(Value *Cond, Value *V1, Value *V2)
LoadInst * getCoercedLoadValue() const
static AvailableValue getLoad(LoadInst *Load, unsigned Offset=0)
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset=0)
bool isUndefValue() const
bool isSelectValue() const
Value * Val
Val - The value that is live out of the block.
Value * V1
V1, V2 - The dominating non-clobbered values of SelectVal.
static AvailableValue getUndef()
Value * getSelectCondition() const
Value * getSimpleValue() const
bool isMemIntrinValue() const
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.