47 #define LDIST_NAME "loop-distribute"
48 #define DEBUG_TYPE LDIST_NAME
54 cl::desc(
"Turn on DominatorTree and LoopInfo verification "
55 "after Loop Distribution"),
59 "loop-distribute-non-if-convertible",
cl::Hidden,
60 cl::desc(
"Whether to distribute into a loop that may not be "
61 "if-convertible by the loop vectorizer"),
66 cl::desc(
"The maximum number of SCEV checks allowed for Loop "
70 "loop-distribute-scev-check-threshold-with-pragma",
cl::init(128),
73 "The maximum number of SCEV checks allowed for Loop "
74 "Distribution for loop marked with #pragma loop distribute(enable)"));
78 cl::desc(
"Enable the new, experimental LoopDistribution Pass"),
81 STATISTIC(NumLoopsDistributed,
"Number of loops distributed");
91 : DepCycle(DepCycle), OrigLoop(L), ClonedLoop(nullptr) {
96 bool hasDepCycle()
const {
return DepCycle; }
102 InstructionSet::iterator
begin() {
return Set.
begin(); }
103 InstructionSet::iterator
end() {
return Set.
end(); }
104 InstructionSet::const_iterator
begin()
const {
return Set.
begin(); }
105 InstructionSet::const_iterator
end()
const {
return Set.
end(); }
106 bool empty()
const {
return Set.empty(); }
110 void moveTo(InstPartition &Other) {
111 Other.Set.insert(Set.begin(), Set.end());
113 Other.DepCycle |= DepCycle;
118 void populateUsedSet() {
122 for (
auto *
B : OrigLoop->getBlocks())
123 Set.insert(
B->getTerminator());
128 while (!Worklist.empty()) {
133 if (I && OrigLoop->contains(I->
getParent()) && Set.insert(I).second)
134 Worklist.push_back(I);
148 LI, DT, ClonedLoopBlocks);
154 const Loop *getClonedLoop()
const {
return ClonedLoop; }
159 const Loop *getDistributedLoop()
const {
160 return ClonedLoop ? ClonedLoop : OrigLoop;
168 void remapInstructions() {
174 void removeUnusedInsts() {
177 for (
auto *Block : OrigLoop->getBlocks())
178 for (
auto &Inst : *Block)
179 if (!Set.count(&Inst)) {
182 NewInst = cast<Instruction>(VMap[NewInst]);
184 assert(!isa<BranchInst>(NewInst) &&
185 "Branches are marked used early on");
191 for (
auto *Inst :
reverse(Unused)) {
192 if (!Inst->use_empty())
194 Inst->eraseFromParent();
200 dbgs() <<
" (cycle)\n";
206 void printBlocks()
const {
207 for (
auto *BB : getDistributedLoop()->getBlocks())
237 class InstPartitionContainer {
242 : L(L), LI(LI), DT(DT) {}
245 unsigned getSize()
const {
return PartitionContainer.size(); }
251 if (PartitionContainer.empty() || !PartitionContainer.back().hasDepCycle())
252 PartitionContainer.emplace_back(Inst, L,
true);
254 PartitionContainer.back().add(Inst);
262 void addToNewNonCyclicPartition(
Instruction *Inst) {
263 PartitionContainer.emplace_back(Inst, L);
271 void mergeAdjacentNonCyclic() {
272 mergeAdjacentPartitionsIf(
273 [](
const InstPartition *
P) {
return !P->hasDepCycle(); });
278 void mergeNonIfConvertible() {
279 mergeAdjacentPartitionsIf([&](
const InstPartition *Partition) {
280 if (Partition->hasDepCycle())
284 bool seenStore =
false;
286 for (
auto *Inst : *Partition)
287 if (isa<StoreInst>(Inst)) {
297 void mergeBeforePopulating() {
298 mergeAdjacentNonCyclic();
300 mergeNonIfConvertible();
310 bool mergeToAvoidDuplicatedLoads() {
314 LoadToPartitionT LoadToPartition;
315 ToBeMergedT ToBeMerged;
320 for (PartitionContainerT::iterator I = PartitionContainer.begin(),
321 E = PartitionContainer.end();
328 if (isa<LoadInst>(Inst)) {
330 LoadToPartitionT::iterator LoadToPart;
332 std::tie(LoadToPart, NewElt) =
333 LoadToPartition.insert(std::make_pair(Inst, PartI));
335 DEBUG(
dbgs() <<
"Merging partitions due to this load in multiple "
336 <<
"partitions: " << PartI <<
", "
337 << LoadToPart->second <<
"\n" << *Inst <<
"\n");
342 ToBeMerged.unionSets(PartI, &*PartJ);
343 }
while (&*PartJ != LoadToPart->second);
347 if (ToBeMerged.empty())
352 for (ToBeMergedT::iterator I = ToBeMerged.begin(),
E = ToBeMerged.end();
357 auto PartI = I->getData();
358 for (
auto PartJ :
make_range(std::next(ToBeMerged.member_begin(I)),
359 ToBeMerged.member_end())) {
360 PartJ->moveTo(*PartI);
365 PartitionContainer.remove_if(
366 [](
const InstPartition &P) {
return P.empty(); });
373 void setupPartitionIdOnInstructions() {
375 for (
const auto &Partition : PartitionContainer) {
378 InstToPartitionIdT::iterator Iter;
380 std::tie(Iter, NewElt) =
381 InstToPartitionId.insert(std::make_pair(Inst, PartitionID));
391 void populateUsedSet() {
392 for (
auto &P : PartitionContainer)
403 assert(Pred &&
"Preheader does not have a single predecessor");
405 assert(ExitBlock &&
"No single exit block");
408 assert(!PartitionContainer.empty() &&
"at least two partitions expected");
412 "preheader not empty");
418 unsigned Index = getSize() - 1;
419 for (
auto I = std::next(PartitionContainer.rbegin()),
420 E = PartitionContainer.rend();
424 NewLoop = Part->cloneLoopWithPreheader(TopPH, Pred, Index, LI, DT);
426 Part->getVMap()[ExitBlock] = TopPH;
427 Part->remapInstructions();
434 for (
auto Curr = PartitionContainer.cbegin(),
435 Next = std::next(PartitionContainer.cbegin()),
436 E = PartitionContainer.cend();
437 Next !=
E; ++Curr, ++Next)
439 Next->getDistributedLoop()->getLoopPreheader(),
440 Curr->getDistributedLoop()->getExitingBlock());
444 void removeUnusedInsts() {
445 for (
auto &Partition : PartitionContainer)
446 Partition.removeUnusedInsts();
459 unsigned N = RtPtrCheck->
Pointers.size();
461 for (
unsigned I = 0; I <
N; ++
I) {
466 int &Partition = PtrToPartitions[
I];
472 int ThisPartition = this->InstToPartitionId[Inst];
474 Partition = ThisPartition;
476 else if (Partition == -1)
478 else if (Partition != (
int)ThisPartition)
481 assert(Partition != -2 &&
"Pointer not belonging to any partition");
484 return PtrToPartitions;
489 for (
const auto &P : PartitionContainer) {
490 OS <<
"Partition " << Index++ <<
" (" << &P <<
"):\n";
495 void dump()
const { print(
dbgs()); }
499 const InstPartitionContainer &Partitions) {
500 Partitions.print(OS);
505 void printBlocks()
const {
507 for (
const auto &P : PartitionContainer) {
508 dbgs() <<
"\nPartition " << Index++ <<
" (" << &P <<
"):\n";
514 typedef std::list<InstPartition> PartitionContainerT;
517 PartitionContainerT PartitionContainer;
521 InstToPartitionIdT InstToPartitionId;
529 template <
class UnaryPredicate>
530 void mergeAdjacentPartitionsIf(UnaryPredicate
Predicate) {
531 InstPartition *PrevMatch =
nullptr;
532 for (
auto I = PartitionContainer.begin(); I != PartitionContainer.end();) {
534 if (PrevMatch ==
nullptr && DoesMatch) {
537 }
else if (PrevMatch !=
nullptr && DoesMatch) {
538 I->moveTo(*PrevMatch);
539 I = PartitionContainer.erase(I);
554 class MemoryInstructionDependences {
560 unsigned NumUnsafeDependencesStartOrEnd;
562 Entry(
Instruction *Inst) : Inst(Inst), NumUnsafeDependencesStartOrEnd(0) {}
567 AccessesType::const_iterator
begin()
const {
return Accesses.
begin(); }
568 AccessesType::const_iterator
end()
const {
return Accesses.
end(); }
570 MemoryInstructionDependences(
573 Accesses.append(Instructions.
begin(), Instructions.
end());
575 DEBUG(
dbgs() <<
"Backward dependences:\n");
576 for (
auto &Dep : Dependences)
577 if (Dep.isPossiblyBackward()) {
581 ++Accesses[Dep.Source].NumUnsafeDependencesStartOrEnd;
582 --Accesses[Dep.Destination].NumUnsafeDependencesStartOrEnd;
584 DEBUG(Dep.print(
dbgs(), 2, Instructions));
589 AccessesType Accesses;
593 class LoopDistributeForLoop {
597 : L(L), F(F), LI(LI), LAI(nullptr), DT(DT), SE(SE), ORE(ORE) {
606 <<
"\" checking " << *L <<
"\n");
609 return fail(
"MultipleExitBlocks",
"multiple exit blocks");
611 return fail(
"NotLoopSimplifyForm",
612 "loop is not in loop-simplify form");
622 return fail(
"MemOpsCanBeVectorized",
623 "memory operations are safe for vectorization");
626 if (!Dependences || Dependences->empty())
627 return fail(
"NoUnsafeDeps",
"no unsafe dependences to isolate");
629 InstPartitionContainer Partitions(L, LI, DT);
654 int NumUnsafeDependencesActive = 0;
655 for (
auto &InstDep : MID) {
659 if (NumUnsafeDependencesActive ||
660 InstDep.NumUnsafeDependencesStartOrEnd > 0)
661 Partitions.addToCyclicPartition(I);
663 Partitions.addToNewNonCyclicPartition(I);
664 NumUnsafeDependencesActive += InstDep.NumUnsafeDependencesStartOrEnd;
665 assert(NumUnsafeDependencesActive >= 0 &&
666 "Negative number of dependences active");
675 for (
auto *Inst : DefsUsedOutside)
676 Partitions.addToNewNonCyclicPartition(Inst);
678 DEBUG(
dbgs() <<
"Seeded partitions:\n" << Partitions);
679 if (Partitions.getSize() < 2)
680 return fail(
"CantIsolateUnsafeDeps",
681 "cannot isolate unsafe dependencies");
685 Partitions.mergeBeforePopulating();
686 DEBUG(
dbgs() <<
"\nMerged partitions:\n" << Partitions);
687 if (Partitions.getSize() < 2)
688 return fail(
"CantIsolateUnsafeDeps",
689 "cannot isolate unsafe dependencies");
692 Partitions.populateUsedSet();
693 DEBUG(
dbgs() <<
"\nPopulated partitions:\n" << Partitions);
697 if (Partitions.mergeToAvoidDuplicatedLoads()) {
698 DEBUG(
dbgs() <<
"\nPartitions merged to ensure unique loads:\n"
700 if (Partitions.getSize() < 2)
701 return fail(
"CantIsolateUnsafeDeps",
702 "cannot isolate unsafe dependencies");
710 return fail(
"TooManySCEVRuntimeChecks",
711 "too many SCEV run-time checks needed.\n");
713 DEBUG(
dbgs() <<
"\nDistributing loop: " << *L <<
"\n");
716 Partitions.setupPartitionIdOnInstructions();
725 auto PtrToPartition = Partitions.computePartitionSetForPointers(*LAI);
727 const auto &AllChecks = RtPtrChecking->
getChecks();
728 auto Checks = includeOnlyCrossPartitionChecks(AllChecks, PtrToPartition,
735 LVer.setAliasChecks(std::move(Checks));
737 LVer.versionLoop(DefsUsedOutside);
738 LVer.annotateLoopWithNoAlias();
743 Partitions.cloneLoops();
747 Partitions.removeUnusedInsts();
748 DEBUG(
dbgs() <<
"\nAfter removing unused Instrs:\n");
749 DEBUG(Partitions.printBlocks());
756 ++NumLoopsDistributed;
760 <<
"distributed loop");
767 bool Forced = isForced().getValueOr(
false);
769 DEBUG(
dbgs() <<
"Skipping; " << Message <<
"\n");
775 <<
"loop not distributed: use -Rpass-analysis=loop-distribute for more "
783 <<
"loop not distributed: " << Message);
790 "explicitly specified loop distribution"));
809 includeOnlyCrossPartitionChecks(
815 std::copy_if(AllChecks.
begin(), AllChecks.
end(), std::back_inserter(Checks),
817 for (
unsigned PtrIdx1 :
Check.first->Members)
818 for (
unsigned PtrIdx2 :
Check.second->Members)
834 PtrToPartition, PtrIdx1, PtrIdx2))
851 assert(Op && mdconst::hasa<ConstantInt>(*Op) &&
"invalid metadata");
852 IsForced = mdconst::extract<ConstantInt>(*Op)->getZExtValue();
883 for (
Loop *TopLevelLoop : *LI)
890 bool Changed =
false;
891 for (
Loop *L : Worklist) {
892 LoopDistributeForLoop
LDL(L, &F, LI, DT, SE, ORE);
897 Changed |=
LDL.processLoop(GetLAA);
912 bool runOnFunction(
Function &F)
override {
916 auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
917 auto *LAA = &getAnalysis<LoopAccessLegacyAnalysis>();
918 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
919 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
920 auto *ORE = &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
921 std::function<const LoopAccessInfo &(Loop &)> GetLAA =
924 return runImpl(F, LI, DT, SE, ORE, GetLAA);
957 std::function<const LoopAccessInfo &(Loop &)> GetLAA =
963 bool Changed =
runImpl(F, &LI, &DT, &SE, &ORE, GetLAA);
Legacy wrapper pass to provide the GlobalsAAResult object.
static bool Check(DecodeStatus &Out, DecodeStatus In)
void push_back(const T &Elt)
const_iterator end(StringRef path)
Get end iterator over path.
Tracking metadata reference owned by Metadata.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
BasicBlock * SplitBlock(BasicBlock *Old, Instruction *SplitPt, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the specified block at the specified instruction - everything before SplitPt stays in Old and e...
This header provides classes for managing a pipeline of passes over loops in LLVM IR...
This is the interface for a simple mod/ref and alias analysis over globals.
const SmallVectorImpl< Instruction * > & getMemoryInstructions() const
The vector of memory access instructions.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
DebugLoc getStartLoc() const
Return the debug location of the start of this loop.
static cl::opt< bool > DistributeNonIfConvertible("loop-distribute-non-if-convertible", cl::Hidden, cl::desc("Whether to distribute into a loop that may not be ""if-convertible by the loop vectorizer"), cl::init(false))
The main scalar evolution driver.
static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg)
Analysis pass providing the TargetTransformInfo.
const_iterator begin(StringRef path)
Get begin iterator over path.
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...
Analysis pass which computes a DominatorTree.
Checks memory dependences among accesses to the same underlying object to determine whether there vec...
BlockT * getExitBlock() const
If getExitBlocks would return exactly one block, return that block.
BlockT * getHeader() const
void remapInstructionsInBlocks(const SmallVectorImpl< BasicBlock * > &Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
StringRef getName() const
Return a constant reference to the value's name.
iterator begin()
Instruction iterator methods.
void printChecks(raw_ostream &OS, const SmallVectorImpl< PointerCheck > &Checks, unsigned Depth=0) const
Print Checks.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Diagnostic information for optimization failures.
static bool arePointersInSamePartition(const SmallVectorImpl< int > &PtrToPartition, unsigned PtrIdx1, unsigned PtrIdx2)
Check if pointers are in the same partition.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
const PredicatedScalarEvolution & getPSE() const
Used to add runtime SCEV checks.
Analysis pass that exposes the LoopInfo for a function.
SmallVector< Instruction *, 8 > findDefsUsedOutsideOfLoop(Loop *L)
Returns the instructions that use values defined in the loop.
bool isLoopSimplifyForm() const
Return true if the Loop is in the form that the LoopSimplify form transforms loops to...
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
static cl::opt< unsigned > DistributeSCEVCheckThreshold("loop-distribute-scev-check-threshold", cl::init(8), cl::Hidden, cl::desc("The maximum number of SCEV checks allowed for Loop ""Distribution"))
const RuntimePointerChecking * getRuntimePointerChecking() const
Function Alias Analysis false
static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, unsigned len)
This function adds the integer array x to the integer array Y and places the result in dest...
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
void replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
initializer< Ty > init(const Ty &Val)
friend const_iterator end(StringRef path)
Get end iterator over path.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
A set of analyses that are preserved following a run of a transformation pass.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs...ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
This is an important class for using LLVM in a threaded context.
This analysis provides dependence information for the memory accesses of a loop.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
SmallVector< Instruction *, 4 > getInstructionsForAccess(Value *Ptr, bool isWrite) const
Return the list of instructions that use Ptr to read or write memory.
A manager for alias analyses.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
Represent the analysis usage information of a pass.
const SmallVector< PointerCheck, 4 > & getChecks() const
Returns the checks that generateChecks created.
Analysis pass providing a never-invalidated alias analysis result.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
void verifyDomTree() const
Verify the correctness of the domtree by re-computing it.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
std::pair< const CheckingPtrGroup *, const CheckingPtrGroup * > PointerCheck
A memcheck which made up of a pair of grouped pointers.
Optional< const MDOperand * > findStringMetadataForLoop(Loop *TheLoop, StringRef Name)
Find string metadata for loop.
A function analysis which provides an AssumptionCache.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool isAlwaysTrue() const override
Implementation of the SCEVPredicate interface.
friend const_iterator begin(StringRef path)
Get begin iterator over path.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
void initializeLoopDistributeLegacyPass(PassRegistry &)
const MemoryDepChecker & getDepChecker() const
the Memory Dependence Checker which can determine the loop-independent and loop-carried dependences b...
Drive the analysis of memory accesses in the loop.
INITIALIZE_PASS_BEGIN(LoopDistributeLegacy, LDIST_NAME, ldist_name, false, false) namespace llvm
This class emits a version of the loop where run-time checks ensure that may-alias pointers can't ove...
const SmallVectorImpl< Dependence > * getDependences() const
Returns the memory dependences.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
BasicBlock * getSinglePredecessor()
Return the predecessor of this block if it has a single predecessor block.
static const char ldist_name[]
Loop * cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB, Loop *OrigLoop, ValueToValueMapTy &VMap, const Twine &NameSuffix, LoopInfo *LI, DominatorTree *DT, SmallVectorImpl< BasicBlock * > &Blocks)
Clones a loop OrigLoop.
Holds information about the memory runtime legality checks to verify that a group of pointers do not ...
Analysis pass that exposes the ScalarEvolution for a function.
unsigned getComplexity() const override
We estimate the complexity of a union predicate as the size number of predicates in the union...
const SCEVUnionPredicate & getUnionPredicate() const
This analysis provides dependence information for the memory accesses of a loop.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Dependece between memory access instructions.
Represents a single loop in the control flow graph.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
SmallVector< PointerInfo, 2 > Pointers
Information about the pointers that may require checking.
iterator_range< value_op_iterator > operand_values()
static cl::opt< unsigned > PragmaDistributeSCEVCheckThreshold("loop-distribute-scev-check-threshold-with-pragma", cl::init(128), cl::Hidden, cl::desc("The maximum number of SCEV checks allowed for Loop ""Distribution for loop marked with #pragma loop distribute(enable)"))
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void preserve()
Mark an analysis as preserved.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
void verify(const DominatorTreeBase< BlockT > &DomTree) const
Analysis pass providing the TargetLibraryInfo.
iterator_range< df_iterator< T > > depth_first(const T &G)
static cl::opt< bool > LDistVerify("loop-distribute-verify", cl::Hidden, cl::desc("Turn on DominatorTree and LoopInfo verification ""after Loop Distribution"), cl::init(false))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class represents a composition of other SCEV predicates, and is the class that most clients will...
static cl::opt< bool > EnableLoopDistribute("enable-loop-distribute", cl::Hidden, cl::desc("Enable the new, experimental LoopDistribution Pass"), cl::init(false))
LLVM Value Representation.
static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, DominatorTree *DT)
Return true if the block BB needs to be predicated in order for the loop to be vectorized.
bool canVectorizeMemory() const
Return true we can analyze the memory accesses in the loop and there are no memory dependence cycles...
bool needsChecking(const CheckingPtrGroup &M, const CheckingPtrGroup &N) const
Decide if we need to add a check between two groups of pointers, according to needsChecking.
This class implements an extremely fast bulk output stream that can only output to a stream...
The legacy pass manager's analysis pass to compute loop information.
print Print MemDeps of function
StringRef - Represent a constant reference to a string, i.e.
A container for analyses that lazily runs them and caches their results.
Legacy analysis pass which computes a DominatorTree.
Dependence - This class represents a dependence between two memory memory references in a function...
const BasicBlock * getParent() const
FunctionPass * createLoopDistributePass()
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...