83#define DEBUG_TYPE "gvn-hoist"
85STATISTIC(NumHoisted,
"Number of instructions hoisted");
86STATISTIC(NumRemoved,
"Number of instructions removed");
87STATISTIC(NumLoadsHoisted,
"Number of loads hoisted");
88STATISTIC(NumLoadsRemoved,
"Number of loads removed");
89STATISTIC(NumStoresHoisted,
"Number of stores hoisted");
90STATISTIC(NumStoresRemoved,
"Number of stores removed");
91STATISTIC(NumCallsHoisted,
"Number of calls hoisted");
92STATISTIC(NumCallsRemoved,
"Number of calls removed");
96 cl::desc(
"Max number of instructions to hoist "
97 "(default unlimited = -1)"));
101 cl::desc(
"Max number of basic blocks on the path between "
102 "hoisting locations (default = 4, unlimited = -1)"));
106 cl::desc(
"Hoist instructions from the beginning of the BB up to the "
107 "maximum specified depth (default = 100, unlimited = -1)"));
111 cl::desc(
"Maximum length of dependent chains to hoist "
112 "(default = 10, unlimited = -1)"));
127using VNType = std::pair<unsigned, uintptr_t>;
186 if (Load->isSimple()) {
187 unsigned V = VN.
lookupOrAdd(Load->getPointerOperand());
190 VNtoLoads[{V, (uintptr_t)Load->getType()}].push_back(Load);
205 if (!Store->isSimple())
208 Value *
Ptr = Store->getPointerOperand();
209 Value *Val = Store->getValueOperand();
229 auto Entry = std::make_pair(V,
InvalidVN);
231 if (Call->doesNotAccessMemory())
232 VNtoCallsScalars[Entry].push_back(Call);
233 else if (Call->onlyReadsMemory())
234 VNtoCallsLoads[Entry].push_back(Call);
236 VNtoCallsStores[Entry].push_back(Call);
245 static const unsigned KnownIDs[] = {LLVMContext::MD_tbaa,
246 LLVMContext::MD_alias_scope,
247 LLVMContext::MD_noalias,
248 LLVMContext::MD_range,
249 LLVMContext::MD_fpmath,
250 LLVMContext::MD_invariant_load,
251 LLVMContext::MD_invariant_group,
252 LLVMContext::MD_access_group};
263 : DT(DT), PDT(PDT), AA(AA), MD(MD), MSSA(MSSA),
285 std::unique_ptr<MemorySSAUpdater> MSSAUpdater;
290 unsigned NumFuncArgs;
291 const bool HoistingGeps =
false;
293 enum InsKind { Unknown, Scalar, Load, Store };
301 unsigned I1DFS = DFSNumber.
lookup(I1);
302 unsigned I2DFS = DFSNumber.
lookup(I2);
304 return I1DFS < I2DFS;
312 int &NBBsOnAllPaths);
322 int &NBBsOnAllPaths);
329 int &NBBsOnAllPaths);
339 int &NBBsOnAllPaths) {
340 return !hasEHOnPath(HoistBB, BB, NBBsOnAllPaths);
368 RenameStackType &RenameStack);
371 RenameStackType &RenameStack);
378 auto Root = PDT->
getNode(
nullptr);
387 RenameStackType RenameStack;
389 fillRenameStack(BB, ValueBBs, RenameStack);
392 fillChiArgs(BB, CHIBBs, RenameStack);
400 void findHoistableCandidates(
OutValuesType &CHIBBs, InsKind K,
408 std::vector<VNType> Ranks;
409 for (
const auto &Entry : Map) {
410 Ranks.push_back(Entry.first);
432 for (
const auto &R : Ranks) {
438 for (
const auto &
I : V) {
449 IDFs.setDefiningBlocks(VNBlocks);
451 IDFs.calculate(IDFBlocks);
454 for (
unsigned i = 0; i <
V.size(); ++i) {
455 InValue[
V[i]->getParent()].push_back(std::make_pair(VN, V[i]));
459 CHIArg EmptyChi = {VN,
nullptr,
nullptr};
460 for (
auto *IDFBB : IDFBlocks) {
461 for (
unsigned i = 0; i <
V.size(); ++i) {
464 OutValue[IDFBB].push_back(EmptyChi);
466 << IDFBB->getName() <<
", for Insn: " << *V[i]);
474 insertCHI(InValue, OutValue);
476 findHoistableCandidates(OutValue, K, HPL);
519 std::pair<unsigned, unsigned> hoistExpressions(
Function &
F);
523 NumFuncArgs =
F.arg_size();
525 VN.setAliasAnalysis(AA);
531 DFSNumber[BB] = ++BBI;
533 for (
const auto &Inst : *BB)
534 DFSNumber[&Inst] = ++
I;
544 auto HoistStat = hoistExpressions(
F);
545 if (HoistStat.first + HoistStat.second == 0)
548 if (HoistStat.second > 0)
564 if (isa<ConstantExpr>(V))
566 if (isa<UndefValue>(V))
568 if (isa<Constant>(V))
570 else if (
auto *
A = dyn_cast<Argument>(V))
571 return 3 +
A->getArgNo();
575 auto Result = DFSNumber.
lookup(V);
577 return 4 + NumFuncArgs + Result;
583 auto It = BBSideEffects.
find(BB);
584 if (It != BBSideEffects.
end())
588 BBSideEffects[BB] =
true;
593 BBSideEffects[BB] =
true;
597 BBSideEffects[BB] =
false;
610 bool ReachedNewPt =
false;
613 if (
const MemoryUse *MU = dyn_cast<MemoryUse>(&MA)) {
617 if (BB == OldBB && firstInBB(OldPt,
Insn))
623 if (firstInBB(
Insn, NewPt))
636 int &NBBsOnAllPaths) {
638 if (NBBsOnAllPaths == 0)
648 if ((BB != SrcBB) && HoistBarrier.
count(BB))
655 int &NBBsOnAllPaths) {
660 "def does not dominate new hoisting point");
674 if (hasEHhelper(BB, OldBB, NBBsOnAllPaths))
678 if (hasMemoryUse(NewPt, Def, BB))
682 if (NBBsOnAllPaths != -1)
692 int &NBBsOnAllPaths) {
708 if (hasEHhelper(BB, SrcBB, NBBsOnAllPaths))
712 if (NBBsOnAllPaths != -1)
721bool GVNHoist::safeToHoistLdSt(
const Instruction *NewPt,
723 GVNHoist::InsKind K,
int &NBBsOnAllPaths) {
740 if (
auto *UD = dyn_cast<MemoryUseOrDef>(
D))
741 if (!firstInBB(UD->getMemoryInst(), NewPt))
746 if (K == InsKind::Store) {
747 if (hasEHOrLoadsOnPath(NewPt, cast<MemoryDef>(U), NBBsOnAllPaths))
749 }
else if (hasEHOnPath(NewBB, OldBB, NBBsOnAllPaths))
788 if (K == InsKind::Scalar) {
789 if (safeToHoistScalar(BB,
Insn->getParent(), NumBBsOnAllPaths))
793 if (safeToHoistLdSt(
T,
Insn, UD, K, NumBBsOnAllPaths))
801 auto it1 = ValueBBs.
find(BB);
802 if (it1 != ValueBBs.
end()) {
805 <<
" for pushing instructions on stack";);
806 for (std::pair<VNType, Instruction *> &VI :
reverse(it1->second)) {
809 RenameStack[
VI.first].push_back(
VI.second);
818 auto P = CHIBBs.
find(Pred);
819 if (
P == CHIBBs.
end()) {
822 LLVM_DEBUG(
dbgs() <<
"\nLooking at CHIs in: " << Pred->getName(););
825 auto &VCHI =
P->second;
826 for (
auto It = VCHI.begin(),
E = VCHI.end(); It !=
E;) {
829 auto si = RenameStack.
find(
C.VN);
833 if (si != RenameStack.
end() && si->second.size() &&
836 C.I = si->second.pop_back_val();
838 <<
"\nCHI Inserted in BB: " <<
C.Dest->getName() << *
C.I
839 <<
", VN: " <<
C.VN.first <<
", " <<
C.VN.second);
842 It = std::find_if(It, VCHI.end(), [It](
CHIArg &
A) { return A != *It; });
867 auto PrevIt = CHIs.
begin();
868 while (PrevIt != PHIIt) {
875 checkSafety(
make_range(PrevIt, PHIIt), BB, K, Safe);
887 PHIIt = std::find_if(PrevIt, CHIs.
end(),
888 [PrevIt](
CHIArg &
A) { return A != *PrevIt; });
893bool GVNHoist::allOperandsAvailable(
const Instruction *
I,
895 for (
const Use &Op :
I->operands())
896 if (
const auto *Inst = dyn_cast<Instruction>(&Op))
897 if (!DT->
dominates(Inst->getParent(), HoistPt))
903bool GVNHoist::allGepOperandsAvailable(
const Instruction *
I,
905 for (
const Use &Op :
I->operands())
906 if (
const auto *Inst = dyn_cast<Instruction>(&Op))
907 if (!DT->
dominates(Inst->getParent(), HoistPt)) {
909 dyn_cast<GetElementPtrInst>(Inst)) {
910 if (!allGepOperandsAvailable(GepOp, HoistPt))
925 assert(allGepOperandsAvailable(Gep, HoistPt) &&
"GEP operands not available");
937 makeGepsAvailable(ClonedGep, HoistPt, InstructionsToHoist, GepOp);
949 for (
const Instruction *OtherInst : InstructionsToHoist) {
951 if (
auto *OtherLd = dyn_cast<LoadInst>(OtherInst))
952 OtherGep = cast<GetElementPtrInst>(OtherLd->getPointerOperand());
954 OtherGep = cast<GetElementPtrInst>(
964 if (
auto *ReplacementLoad = dyn_cast<LoadInst>(Repl)) {
965 ReplacementLoad->setAlignment(
966 std::min(ReplacementLoad->getAlign(), cast<LoadInst>(
I)->getAlign()));
968 }
else if (
auto *ReplacementStore = dyn_cast<StoreInst>(Repl)) {
969 ReplacementStore->setAlignment(
970 std::min(ReplacementStore->getAlign(), cast<StoreInst>(
I)->getAlign()));
972 }
else if (
auto *ReplacementAlloca = dyn_cast<AllocaInst>(Repl)) {
973 ReplacementAlloca->setAlignment(std::max(ReplacementAlloca->getAlign(),
974 cast<AllocaInst>(
I)->getAlign()));
975 }
else if (isa<CallInst>(Repl)) {
986 updateAlignment(
I, Repl);
991 MSSAUpdater->removeMemoryAccess(OldMA);
996 I->replaceAllUsesWith(Repl);
999 I->eraseFromParent();
1008 if (
MemoryPhi *Phi = dyn_cast<MemoryPhi>(U))
1012 auto In = Phi->incoming_values();
1014 Phi->replaceAllUsesWith(NewMemAcc);
1015 MSSAUpdater->removeMemoryAccess(Phi);
1020unsigned GVNHoist::removeAndReplace(
const SmallVecInsn &Candidates,
1024 if (MoveAccess && NewMemAcc) {
1031 unsigned NR = rauw(Candidates, Repl, NewMemAcc);
1035 raMPHIuw(NewMemAcc);
1039bool GVNHoist::makeGepOperandsAvailable(
1045 if (
auto *Ld = dyn_cast<LoadInst>(Repl)) {
1046 Gep = dyn_cast<GetElementPtrInst>(Ld->getPointerOperand());
1047 }
else if (
auto *St = dyn_cast<StoreInst>(Repl)) {
1048 Gep = dyn_cast<GetElementPtrInst>(St->getPointerOperand());
1049 Val = dyn_cast<Instruction>(St->getValueOperand());
1052 if (isa<GetElementPtrInst>(Val)) {
1054 if (!allGepOperandsAvailable(Val, HoistPt))
1062 if (!Gep || !allGepOperandsAvailable(Gep, HoistPt))
1065 makeGepsAvailable(Repl, HoistPt, InstructionsToHoist, Gep);
1067 if (Val && isa<GetElementPtrInst>(Val))
1068 makeGepsAvailable(Repl, HoistPt, InstructionsToHoist, Val);
1074 unsigned NI = 0,
NL = 0, NS = 0,
NC = 0, NR = 0;
1082 if (
I->getParent() == DestBB)
1086 if (!Repl || firstInBB(
I, Repl))
1091 bool MoveAccess =
true;
1094 assert(allOperandsAvailable(Repl, DestBB) &&
1095 "instruction depends on operands that are not available");
1100 Repl = InstructionsToHoist.front();
1105 if (!allOperandsAvailable(Repl, DestBB)) {
1112 if (!makeGepOperandsAvailable(Repl, DestBB, InstructionsToHoist))
1121 DFSNumber[Repl] = DFSNumber[
Last]++;
1126 NR += removeAndReplace(InstructionsToHoist, Repl, DestBB, MoveAccess);
1128 if (isa<LoadInst>(Repl))
1130 else if (isa<StoreInst>(Repl))
1132 else if (isa<CallInst>(Repl))
1141 NumHoisted +=
NL + NS +
NC + NI;
1143 NumLoadsHoisted +=
NL;
1144 NumStoresHoisted += NS;
1145 NumCallsHoisted +=
NC;
1146 return {NI,
NL +
NC + NS};
1149std::pair<unsigned, unsigned> GVNHoist::hoistExpressions(
Function &
F) {
1155 int InstructionNb = 0;
1169 if (
I1.isTerminator())
1172 if (
auto *Load = dyn_cast<LoadInst>(&I1))
1174 else if (
auto *Store = dyn_cast<StoreInst>(&I1))
1175 SI.insert(Store, VN);
1176 else if (
auto *Call = dyn_cast<CallInst>(&I1)) {
1177 if (
auto *
Intr = dyn_cast<IntrinsicInst>(Call)) {
1178 if (isa<DbgInfoIntrinsic>(
Intr) ||
1179 Intr->getIntrinsicID() == Intrinsic::assume ||
1180 Intr->getIntrinsicID() == Intrinsic::sideeffect)
1183 if (
Call->mayHaveSideEffects())
1186 if (
Call->isConvergent())
1190 }
else if (HoistingGeps || !isa<GetElementPtrInst>(&I1))
1200 computeInsertionPoints(II.
getVNTable(), HPL, InsKind::Scalar);
1201 computeInsertionPoints(LI.
getVNTable(), HPL, InsKind::Load);
1202 computeInsertionPoints(
SI.getVNTable(), HPL, InsKind::Store);
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static cl::opt< int > MaxHoistedThreshold("gvn-max-hoisted", cl::Hidden, cl::init(-1), cl::desc("Max number of instructions to hoist " "(default unlimited = -1)"))
static cl::opt< int > MaxChainLength("gvn-hoist-max-chain-length", cl::Hidden, cl::init(10), cl::desc("Maximum length of dependent chains to hoist " "(default = 10, unlimited = -1)"))
static cl::opt< int > MaxDepthInBB("gvn-hoist-max-depth", cl::Hidden, cl::init(100), cl::desc("Hoist instructions from the beginning of the BB up to the " "maximum specified depth (default = 100, unlimited = -1)"))
static cl::opt< int > MaxNumberOfBBSInPath("gvn-hoist-max-bbs", cl::Hidden, cl::init(4), cl::desc("Max number of basic blocks on the path between " "hoisting locations (default = 4, unlimited = -1)"))
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.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
return ToRemove size() > 0
This header defines various interfaces for pass management in LLVM.
static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E, int I, uint32_t *Buf)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
This defines the Use class.
A manager for alias analyses.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
bool hasAddressTaken() const
Returns true if there are any uses of this basic block other than direct branches,...
bool isEHPad() const
Return true if this basic block is an exception handling block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
void insert(CallInst *Call, GVNPass::ValueTable &VN)
const VNtoInsns & getLoadVNTable() const
const VNtoInsns & getScalarVNTable() const
const VNtoInsns & getStoreVNTable() const
This class represents a function call, abstracting a target machine's calling convention.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
GVNHoist(DominatorTree *DT, PostDominatorTree *PDT, AliasAnalysis *AA, MemoryDependenceResults *MD, MemorySSA *MSSA)
unsigned int rank(const Value *V) const
This class holds the mapping between values and value numbers.
uint32_t lookupOrAdd(Value *V)
lookup_or_add - Returns the value number for the specified value, assigning it a new number if it did...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
const VNtoInsns & getVNTable() const
void insert(Instruction *I, GVNPass::ValueTable &VN)
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
void dropLocation()
Drop the instruction's debug location.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
const BasicBlock * getParent() const
bool mayThrow() const LLVM_READONLY
Return true if this instruction may throw an exception.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs)
Drop all unknown metadata except for debug locations.
const VNtoInsns & getVNTable() const
void insert(LoadInst *Load, GVNPass::ValueTable &VN)
An instruction for reading from memory.
Represents a read-write access to memory, whether it is a must-alias, or a may-alias.
An analysis that produces MemoryDependenceResults for a function.
Provides a lazy, caching interface for making common memory aliasing information queries,...
void removeInstruction(Instruction *InstToRemove)
Removes an instruction from the dependence analysis, updating the dependence of instructions that pre...
Represents phi nodes for memory accesses.
An analysis that produces MemorySSA for a function.
static bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU, AliasAnalysis &AA)
Encapsulates MemorySSA, including all data associated with memory accesses.
const AccessList * getBlockAccesses(const BasicBlock *BB) const
Return the list of MemoryAccess's for a given basic block.
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.
void ensureOptimizedUses()
By default, uses are not optimized during MemorySSA construction.
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.
Class that has the common methods + fields of memory uses/defs.
Represents read-only accesses to memory.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
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.
void preserve()
Mark an analysis as preserved.
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.
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void insert(StoreInst *Store, GVNPass::ValueTable &VN)
const VNtoInsns & getVNTable() const
An instruction for storing to memory.
A Use represents the edge between a Value definition and its users.
bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An intrusive list with ownership and callbacks specified/controlled by ilist_traits,...
A range adaptor for a pair of iterators.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto successors(const MachineBasicBlock *BB)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static void combineKnownMetadata(Instruction *ReplInst, Instruction *I)
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
std::pair< BasicBlock *, SmallVecInsn > HoistingPointInfo
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
SmallVectorImpl< CHIArg >::iterator CHIIt
idf_iterator< T > idf_end(const T &G)
void combineMetadata(Instruction *K, const Instruction *J, ArrayRef< unsigned > KnownIDs, bool DoesKMove)
Combine the metadata of two instructions so that K can replace J.
bool VerifyMemorySSA
Enables verification of MemorySSA.
idf_iterator< T > idf_begin(const T &G)
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
SmallVector< Instruction *, 4 > SmallVecInsn
iterator_range< df_iterator< T > > depth_first(const T &G)
std::pair< unsigned, uintptr_t > VNType
bool operator!=(const CHIArg &A) const
bool operator==(const CHIArg &A) const
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
Utility type to build an inheritance chain that makes it easy to rank overload candidates.