79#define DEBUG_TYPE "gvn-hoist"
81STATISTIC(NumHoisted,
"Number of instructions hoisted");
82STATISTIC(NumRemoved,
"Number of instructions removed");
83STATISTIC(NumLoadsHoisted,
"Number of loads hoisted");
84STATISTIC(NumLoadsRemoved,
"Number of loads removed");
85STATISTIC(NumStoresHoisted,
"Number of stores hoisted");
86STATISTIC(NumStoresRemoved,
"Number of stores removed");
87STATISTIC(NumCallsHoisted,
"Number of calls hoisted");
88STATISTIC(NumCallsRemoved,
"Number of calls removed");
102using VNType = std::pair<unsigned, uintptr_t>;
161 if (
Load->isSimple()) {
180 if (!
Store->isSimple())
204 auto Entry = std::make_pair(V,
InvalidVN);
206 if (
Call->doesNotAccessMemory())
207 VNtoCallsScalars[Entry].push_back(
Call);
208 else if (
Call->onlyReadsMemory())
209 VNtoCallsLoads[Entry].push_back(
Call);
211 VNtoCallsStores[Entry].push_back(
Call);
226 : Opts(Opts), DT(DT), PDT(PDT), AA(AA), MSSA(MSSA),
241 const ScalarOptions &Opts;
247 std::unique_ptr<MemorySSAUpdater> MSSAUpdater;
252 unsigned NumFuncArgs;
253 const bool HoistingGeps =
false;
263 unsigned I1DFS = DFSNumber.
lookup(I1);
264 unsigned I2DFS = DFSNumber.
lookup(I2);
266 return I1DFS < I2DFS;
270 bool hasMemoryUse(
const Instruction *NewPt, MemoryDef *Def,
271 const BasicBlock *BB);
273 bool hasEHhelper(
const BasicBlock *BB,
const BasicBlock *SrcBB,
274 int &NBBsOnAllPaths);
283 bool hasEHOrLoadsOnPath(
const Instruction *NewPt, MemoryDef *Def,
284 int &NBBsOnAllPaths);
290 bool hasEHOnPath(
const BasicBlock *HoistPt,
const BasicBlock *SrcBB,
291 int &NBBsOnAllPaths);
295 bool safeToHoistLdSt(
const Instruction *NewPt,
const Instruction *OldPt,
296 MemoryUseOrDef *U, InsKind K,
int &NBBsOnAllPaths);
300 bool safeToHoistScalar(
const BasicBlock *HoistBB,
const BasicBlock *BB,
301 int &NBBsOnAllPaths) {
302 return !hasEHOnPath(HoistBB, BB, NBBsOnAllPaths);
319 bool valueAnticipable(
CHIArgs C, Instruction *TI)
const;
323 void checkSafety(
CHIArgs C, BasicBlock *BB, InsKind K,
324 SmallVectorImpl<CHIArg> &Safe);
326 using RenameStackType = DenseMap<VNType, SmallVector<Instruction *, 2>>;
329 void fillRenameStack(BasicBlock *BB,
InValuesType &ValueBBs,
330 RenameStackType &RenameStack);
333 RenameStackType &RenameStack);
340 auto Root = PDT->getNode(
nullptr);
349 RenameStackType RenameStack;
351 fillRenameStack(BB, ValueBBs, RenameStack);
354 fillChiArgs(BB, CHIBBs, RenameStack);
362 void findHoistableCandidates(
OutValuesType &CHIBBs, InsKind K,
370 std::vector<VNType> Ranks;
371 for (
const auto &Entry : Map) {
372 Ranks.push_back(
Entry.first);
394 for (
const auto &R : Ranks) {
399 SmallPtrSet<BasicBlock *, 2> VNBlocks;
400 for (
const auto &
I :
V) {
411 IDFs.setDefiningBlocks(VNBlocks);
413 IDFs.calculate(IDFBlocks);
416 for (
unsigned i = 0; i <
V.size(); ++i) {
417 InValue[
V[i]->getParent()].push_back(std::make_pair(VN,
V[i]));
421 CHIArg EmptyChi = {VN,
nullptr,
nullptr};
422 for (
auto *IDFBB : IDFBlocks) {
423 for (
unsigned i = 0; i <
V.size(); ++i) {
425 if (DT->properlyDominates(IDFBB,
V[i]->getParent())) {
426 OutValue[IDFBB].push_back(EmptyChi);
428 << IDFBB->getName() <<
", for Insn: " << *
V[i]);
436 insertCHI(InValue, OutValue);
438 findHoistableCandidates(OutValue, K, HPL);
445 bool allOperandsAvailable(
const Instruction *
I,
446 const BasicBlock *HoistPt)
const;
449 bool allGepOperandsAvailable(
const Instruction *
I,
450 const BasicBlock *HoistPt)
const;
453 void makeGepsAvailable(Instruction *Repl, BasicBlock *HoistPt,
455 Instruction *Gep)
const;
457 void updateAlignment(Instruction *
I, Instruction *Repl);
461 unsigned rauw(
const SmallVecInsn &Candidates, Instruction *Repl);
464 void raMPHIuw(MemoryUseOrDef *NewMemAcc);
467 unsigned removeAndReplace(
const SmallVecInsn &Candidates, Instruction *Repl,
468 BasicBlock *DestBB,
bool MoveAccess);
473 bool makeGepOperandsAvailable(Instruction *Repl, BasicBlock *HoistPt,
480 std::pair<unsigned, unsigned> hoistExpressions(
Function &
F);
484 NumFuncArgs =
F.arg_size();
486 VN.setAliasAnalysis(AA);
488 VN.setMemorySSA(MSSA,
true);
493 DFSNumber[BB] = ++BBI;
495 for (
const auto &Inst : *BB)
496 DFSNumber[&Inst] = ++
I;
503 if (Opts.gvn_hoist_max_chain_length != -1 &&
504 ++ChainLength >= Opts.gvn_hoist_max_chain_length)
507 auto HoistStat = hoistExpressions(
F);
508 if (HoistStat.first + HoistStat.second == 0)
511 if (HoistStat.second > 0)
534 return 3 +
A->getArgNo();
538 auto Result = DFSNumber.lookup(V);
540 return 4 + NumFuncArgs + Result;
546 auto [It, Inserted] = BBSideEffects.
try_emplace(BB);
572 bool ReachedNewPt =
false;
574 for (
const MemoryAccess &MA : *Acc)
579 if (BB == OldBB && firstInBB(OldPt, Insn))
585 if (firstInBB(Insn, NewPt))
598 int &NBBsOnAllPaths) {
600 if (NBBsOnAllPaths == 0)
610 if ((BB != SrcBB) && HoistBarrier.count(BB))
617 int &NBBsOnAllPaths) {
620 assert(DT->dominates(NewBB, OldBB) &&
"invalid path");
634 if (hasEHhelper(BB, OldBB, NBBsOnAllPaths))
638 if (hasMemoryUse(NewPt, Def, BB))
642 if (NBBsOnAllPaths != -1)
652 int &NBBsOnAllPaths) {
653 assert(DT->dominates(HoistPt, SrcBB) &&
"Invalid path");
668 if (hasEHhelper(BB, SrcBB, NBBsOnAllPaths))
672 if (NBBsOnAllPaths != -1)
681bool GVNHoist::safeToHoistLdSt(
const Instruction *NewPt,
683 GVNHoist::InsKind K,
int &NBBsOnAllPaths) {
693 MemoryAccess *
D = MSSA->getWalker()->getClobberingMemoryAccess(U);
695 if (DT->properlyDominates(NewBB, DBB))
699 if (NewBB == DBB && !MSSA->isLiveOnEntryDef(
D))
701 if (!firstInBB(UD->getMemoryInst(), NewPt))
706 if (K == InsKind::Store) {
709 }
else if (hasEHOnPath(NewBB, OldBB, NBBsOnAllPaths))
713 if (DT->properlyDominates(DBB, NewBB))
716 assert(MSSA->locallyDominates(
D, U));
737 int NumBBsOnAllPaths = Opts.gvn_hoist_max_bbs;
748 if (K == InsKind::Scalar) {
749 if (safeToHoistScalar(BB, Insn->
getParent(), NumBBsOnAllPaths))
752 if (MemoryUseOrDef *UD = MSSA->getMemoryAccess(Insn))
753 if (safeToHoistLdSt(
T, Insn, UD, K, NumBBsOnAllPaths))
760 GVNHoist::RenameStackType &RenameStack) {
761 auto it1 = ValueBBs.find(BB);
762 if (it1 != ValueBBs.end()) {
765 <<
" for pushing instructions on stack";);
766 for (std::pair<VNType, Instruction *> &VI :
reverse(it1->second)) {
769 RenameStack[
VI.first].push_back(
VI.second);
775 GVNHoist::RenameStackType &RenameStack) {
778 auto P = CHIBBs.find(
Pred);
779 if (
P == CHIBBs.end()) {
785 auto &VCHI =
P->second;
786 for (
auto It = VCHI.begin(),
E = VCHI.end(); It !=
E;) {
789 auto si = RenameStack.find(
C.VN);
793 if (si != RenameStack.end() && si->second.size() &&
794 DT->properlyDominates(
Pred, si->second.back()->
getParent())) {
796 C.I = si->second.pop_back_val();
798 <<
"\nCHI Inserted in BB: " <<
C.Dest->getName() << *
C.I
799 <<
", VN: " <<
C.VN.first <<
", " <<
C.VN.second);
812 auto cmpVN = [](
const CHIArg &
A,
const CHIArg &
B) {
return A.VN <
B.VN; };
816 for (
auto &
A : CHIBBs) {
818 SmallVectorImpl<CHIArg> &CHIs =
A.second;
827 auto PrevIt = CHIs.
begin();
828 while (PrevIt != PHIIt) {
835 checkSafety(
make_range(PrevIt, PHIIt), BB, K, Safe);
847 PHIIt = std::find_if(PrevIt, CHIs.
end(),
848 [PrevIt](CHIArg &
A) { return A != *PrevIt; });
853bool GVNHoist::allOperandsAvailable(
const Instruction *
I,
855 for (
const Use &
Op :
I->operands())
857 if (!DT->dominates(Inst->getParent(), HoistPt))
863bool GVNHoist::allGepOperandsAvailable(
const Instruction *
I,
865 for (
const Use &
Op :
I->operands())
867 if (!DT->dominates(Inst->getParent(), HoistPt)) {
868 if (
const GetElementPtrInst *GepOp =
870 if (!allGepOperandsAvailable(GepOp, HoistPt))
885 assert(allGepOperandsAvailable(Gep, HoistPt) &&
"GEP operands not available");
891 if (DT->dominates(
Op->getParent(), HoistPt))
897 makeGepsAvailable(ClonedGep, HoistPt, InstructionsToHoist, GepOp);
909 for (
const Instruction *OtherInst : InstructionsToHoist) {
910 const GetElementPtrInst *OtherGep;
921 if (OtherGep != Gep) {
933 ReplacementLoad->setAlignment(
937 ReplacementStore->setAlignment(
941 ReplacementAlloca->setAlignment(std::max(ReplacementAlloca->getAlign(),
950 for (Instruction *
I : Candidates) {
953 updateAlignment(
I, Repl);
954 if (MemoryAccess *OldMA = MSSA->getMemoryAccess(
I))
955 MSSAUpdater->removeMemoryAccess(OldMA);
958 I->replaceAllUsesWith(Repl);
959 I->eraseFromParent();
966 SmallPtrSet<MemoryPhi *, 4> UsePhis;
967 for (User *U : NewMemAcc->
users())
971 for (MemoryPhi *Phi : UsePhis) {
972 auto In =
Phi->incoming_values();
974 Phi->replaceAllUsesWith(NewMemAcc);
975 MSSAUpdater->removeMemoryAccess(Phi);
980unsigned GVNHoist::removeAndReplace(
const SmallVecInsn &Candidates,
983 MemoryUseOrDef *NewMemAcc = MSSA->getMemoryAccess(Repl);
984 if (MoveAccess && NewMemAcc) {
991 unsigned NR = rauw(Candidates, Repl);
999bool GVNHoist::makeGepOperandsAvailable(
1003 GetElementPtrInst *Gep =
nullptr;
1014 if (!allGepOperandsAvailable(Val, HoistPt))
1016 }
else if (!DT->dominates(Val->
getParent(), HoistPt))
1022 if (!Gep || !allGepOperandsAvailable(Gep, HoistPt))
1025 makeGepsAvailable(Repl, HoistPt, InstructionsToHoist, Gep);
1028 makeGepsAvailable(Repl, HoistPt, InstructionsToHoist, Val);
1034 unsigned NI = 0, NL = 0, NS = 0,
NC = 0, NR = 0;
1041 for (Instruction *
I : InstructionsToHoist)
1042 if (
I->getParent() == DestBB)
1046 if (!Repl || firstInBB(
I, Repl))
1051 bool MoveAccess =
true;
1054 assert(allOperandsAvailable(Repl, DestBB) &&
1055 "instruction depends on operands that are not available");
1060 Repl = InstructionsToHoist.front();
1065 if (!allOperandsAvailable(Repl, DestBB)) {
1072 if (!makeGepOperandsAvailable(Repl, DestBB, InstructionsToHoist))
1078 if (
auto *MUD = MSSA->getMemoryAccess(Repl))
1082 DFSNumber[Repl] = DFSNumber[
Last]++;
1087 NR += removeAndReplace(InstructionsToHoist, Repl, DestBB, MoveAccess);
1100 MSSA->verifyMemorySSA();
1102 NumHoisted += NL + NS +
NC + NI;
1104 NumLoadsHoisted += NL;
1105 NumStoresHoisted += NS;
1106 NumCallsHoisted +=
NC;
1107 return {NI, NL +
NC + NS};
1110std::pair<unsigned, unsigned> GVNHoist::hoistExpressions(
Function &
F) {
1115 for (BasicBlock *BB :
depth_first(&
F.getEntryBlock())) {
1116 int InstructionNb = 0;
1117 for (Instruction &I1 : *BB) {
1121 HoistBarrier.insert(BB);
1126 if (Opts.gvn_hoist_max_depth != -1 &&
1127 InstructionNb++ >= Opts.gvn_hoist_max_depth)
1131 if (
I1.isTerminator())
1135 LI.insert(Load, VN);
1137 SI.insert(Store, VN);
1140 if (Intr->getIntrinsicID() == Intrinsic::assume ||
1141 Intr->getIntrinsicID() == Intrinsic::sideeffect)
1150 CI.insert(
Call, VN);
1161 computeInsertionPoints(
II.getVNTable(), HPL, InsKind::Scalar);
1162 computeInsertionPoints(LI.getVNTable(), HPL, InsKind::Load);
1163 computeInsertionPoints(
SI.getVNTable(), HPL, InsKind::Store);
1164 computeInsertionPoints(CI.getScalarVNTable(), HPL, InsKind::Scalar);
1165 computeInsertionPoints(CI.getLoadVNTable(), HPL, InsKind::Load);
1166 computeInsertionPoints(CI.getStoreVNTable(), HPL, InsKind::Store);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file provides the interface for the GVNHoist pass.
This file provides a data structure for mapping values and expressions to congruence class IDs.
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 header defines various interfaces for pass management in LLVM.
This defines the Use class.
This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...
uint64_t IntrinsicInst * II
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)
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)
A manager for alias analyses.
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; assumes that the block is well-formed.
bool isConvergent() const
Determine if the invoke is convergent.
void insert(CallInst *Call, GVNValueTable &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
Return the entry for the specified key, or a default constructed value if no such entry exists.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
GVNHoist(const ScalarOptions &Opts, DominatorTree *DT, PostDominatorTree *PDT, AliasAnalysis *AA, MemorySSA *MSSA)
unsigned int rank(const Value *V) const
This class holds the mapping between values and value numbers.
LLVM_ABI uint32_t lookupOrAdd(MemoryAccess *MA)
void insert(Instruction *I, GVNValueTable &VN)
const VNtoInsns & getVNTable() const
LLVM_ABI bool mayThrow(bool IncludePhaseOneUnwind=false) const LLVM_READONLY
Return true if this instruction may throw an exception.
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.
LLVM_ABI void dropLocation()
Drop the instruction's debug location.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})
Drop all unknown metadata except for debug locations.
LLVM_ABI void applyMergedLocation(DebugLoc LocA, DebugLoc LocB)
Merge 2 debug locations and apply it to the Instruction.
const VNtoInsns & getVNTable() const
void insert(LoadInst *Load, GVNValueTable &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 MemorySSA for a function.
static LLVM_ABI bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU, AliasAnalysis &AA)
Encapsulates MemorySSA, including all data associated with memory accesses.
iplist< MemoryAccess, ilist_tag< MSSAHelpers::AllAccessTag > > AccessList
Class that has the common methods + fields of memory uses/defs.
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.
PreservedAnalyses & 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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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, GVNValueTable &VN)
const VNtoInsns & getVNTable() const
An instruction for storing to memory.
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
self_iterator getIterator()
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.
Abstract Attribute helper functions.
@ BasicBlock
Various leaf nodes.
NodeAddr< DefNode * > Def
NodeAddr< PhiNode * > Phi
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
DenseMap< BasicBlock *, SmallVector< std::pair< VNType, Instruction * >, 2 > > InValuesType
constexpr auto not_equal_to(T &&Arg)
Functor variant of std::not_equal_to that can be used as a UnaryPredicate in functional algorithms li...
void stable_sort(R &&Range)
SmallVector< HoistingPointInfo, 4 > HoistingPointList
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 size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
@ Unknown
Not known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
const ScalarOptions & getScalarOptions(const LLVMContext &C)
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
SmallVector< Instruction *, 4 > SmallVecInsn
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
SmallVectorImpl< CHIArg >::iterator CHIIt
DenseMap< VNType, SmallVector< Instruction *, 4 > > VNtoInsns
auto reverse(ContainerTy &&C)
std::pair< unsigned, uintptr_t > VNType
IDFCalculator< true > ReverseIDFCalculator
void sort(IteratorTy Start, IteratorTy End)
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, bool DoesKMove=false)
Patch the replacement so that it is not more restrictive than the value being replaced.
std::pair< BasicBlock *, SmallVecInsn > HoistingPointInfo
LLVM_ABI bool VerifyMemorySSA
Enables verification of MemorySSA.
idf_iterator< T > idf_end(const T &G)
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...
DWARFExpression::Operation Op
idf_iterator< T > idf_begin(const T &G)
DenseMap< BasicBlock *, SmallVector< CHIArg, 2 > > OutValuesType
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
iterator_range< CHIIt > CHIArgs
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
iterator_range< df_iterator< T > > depth_first(const T &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
DenseMap< const BasicBlock *, bool > BBSideEffectsSet
Implement std::hash so that hash_code can be used in STL containers.
bool operator!=(const CHIArg &A) const
bool operator==(const CHIArg &A) const
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.