72#define LDIST_NAME "loop-distribute"
73#define DEBUG_TYPE LDIST_NAME
78 "llvm.loop.distribute.followup_all";
80 "llvm.loop.distribute.followup_coincident";
82 "llvm.loop.distribute.followup_sequential";
84 "llvm.loop.distribute.followup_fallback";
89 cl::desc(
"Turn on DominatorTree and LoopInfo verification "
90 "after Loop Distribution"),
94 "loop-distribute-non-if-convertible",
cl::Hidden,
95 cl::desc(
"Whether to distribute into a loop that may not be "
96 "if-convertible by the loop vectorizer"),
101 cl::desc(
"The maximum number of SCEV checks allowed for Loop "
105 "loop-distribute-scev-check-threshold-with-pragma",
cl::init(128),
107 cl::desc(
"The maximum number of SCEV checks allowed for Loop "
108 "Distribution for loop marked with #pragma clang loop "
109 "distribute(enable)"));
113 cl::desc(
"Enable the new, experimental LoopDistribution Pass"),
116STATISTIC(NumLoopsDistributed,
"Number of loops distributed");
127 : DepCycle(DepCycle), OrigLoop(L) {
132 bool hasDepCycle()
const {
return DepCycle; }
142 bool empty()
const {
return Set.empty(); }
146 void moveTo(InstPartition &
Other) {
147 Other.Set.insert(Set.begin(), Set.end());
149 Other.DepCycle |= DepCycle;
154 void populateUsedSet() {
158 for (
auto *
B : OrigLoop->getBlocks())
159 Set.insert(
B->getTerminator());
164 while (!Worklist.empty()) {
167 for (
Value *V :
I->operand_values()) {
168 auto *
I = dyn_cast<Instruction>(V);
169 if (
I && OrigLoop->contains(
I->getParent()) && Set.insert(
I))
170 Worklist.push_back(
I);
184 LI, DT, ClonedLoopBlocks);
190 const Loop *getClonedLoop()
const {
return ClonedLoop; }
195 Loop *getDistributedLoop()
const {
196 return ClonedLoop ? ClonedLoop : OrigLoop;
204 void remapInstructions() {
210 void removeUnusedInsts() {
213 for (
auto *
Block : OrigLoop->getBlocks())
214 for (
auto &Inst : *
Block)
215 if (!Set.count(&Inst)) {
218 NewInst = cast<Instruction>(VMap[NewInst]);
220 assert(!isa<BranchInst>(NewInst) &&
221 "Branches are marked used early on");
222 Unused.push_back(NewInst);
227 for (
auto *Inst :
reverse(Unused)) {
228 if (!Inst->use_empty())
230 Inst->eraseFromParent();
235 OS << (DepCycle ?
" (cycle)\n" :
"\n");
238 OS <<
" " <<
I->getParent()->getName() <<
":" << *
I <<
"\n";
242 for (
auto *BB : getDistributedLoop()->getBlocks())
258 Loop *ClonedLoop =
nullptr;
272class InstPartitionContainer {
277 :
L(
L), LI(LI), DT(DT) {}
280 unsigned getSize()
const {
return PartitionContainer.size(); }
286 if (PartitionContainer.empty() || !PartitionContainer.back().hasDepCycle())
287 PartitionContainer.emplace_back(Inst, L,
true);
289 PartitionContainer.back().add(Inst);
297 void addToNewNonCyclicPartition(
Instruction *Inst) {
298 PartitionContainer.emplace_back(Inst, L);
306 void mergeAdjacentNonCyclic() {
307 mergeAdjacentPartitionsIf(
308 [](
const InstPartition *
P) {
return !
P->hasDepCycle(); });
313 void mergeNonIfConvertible() {
314 mergeAdjacentPartitionsIf([&](
const InstPartition *Partition) {
315 if (Partition->hasDepCycle())
319 bool seenStore =
false;
321 for (
auto *Inst : *Partition)
322 if (isa<StoreInst>(Inst)) {
332 void mergeBeforePopulating() {
333 mergeAdjacentNonCyclic();
335 mergeNonIfConvertible();
345 bool mergeToAvoidDuplicatedLoads() {
349 LoadToPartitionT LoadToPartition;
350 ToBeMergedT ToBeMerged;
355 for (PartitionContainerT::iterator
I = PartitionContainer.begin(),
356 E = PartitionContainer.end();
363 if (isa<LoadInst>(Inst)) {
365 LoadToPartitionT::iterator LoadToPart;
367 std::tie(LoadToPart, NewElt) =
368 LoadToPartition.insert(std::make_pair(Inst, PartI));
372 <<
"LDist: Merging partitions due to this load in multiple "
373 <<
"partitions: " << PartI <<
", " << LoadToPart->second <<
"\n"
379 ToBeMerged.unionSets(PartI, &*PartJ);
380 }
while (&*PartJ != LoadToPart->second);
384 if (ToBeMerged.empty())
389 for (ToBeMergedT::iterator
I = ToBeMerged.begin(), E = ToBeMerged.end();
394 auto PartI =
I->getData();
395 for (
auto *PartJ :
make_range(std::next(ToBeMerged.member_begin(
I)),
396 ToBeMerged.member_end())) {
397 PartJ->moveTo(*PartI);
402 PartitionContainer.remove_if(
403 [](
const InstPartition &
P) {
return P.empty(); });
410 void setupPartitionIdOnInstructions() {
412 for (
const auto &Partition : PartitionContainer) {
417 std::tie(Iter, NewElt) =
418 InstToPartitionId.insert(std::make_pair(Inst, PartitionID));
428 void populateUsedSet() {
429 for (
auto &
P : PartitionContainer)
440 assert(Pred &&
"Preheader does not have a single predecessor");
442 assert(ExitBlock &&
"No single exit block");
445 assert(!PartitionContainer.empty() &&
"at least two partitions expected");
449 "preheader not empty");
452 MDNode *OrigLoopID =
L->getLoopID();
460 NewLoop = Part.cloneLoopWithPreheader(TopPH, Pred,
Index, LI, DT);
462 Part.getVMap()[ExitBlock] = TopPH;
463 Part.remapInstructions();
464 setNewLoopID(OrigLoopID, &Part);
471 setNewLoopID(OrigLoopID, &PartitionContainer.back());
476 for (
auto Curr = PartitionContainer.cbegin(),
477 Next = std::next(PartitionContainer.cbegin()),
478 E = PartitionContainer.cend();
479 Next != E; ++Curr, ++Next)
481 Next->getDistributedLoop()->getLoopPreheader(),
482 Curr->getDistributedLoop()->getExitingBlock());
486 void removeUnusedInsts() {
487 for (
auto &Partition : PartitionContainer)
488 Partition.removeUnusedInsts();
501 unsigned N = RtPtrCheck->
Pointers.size();
503 for (
unsigned I = 0;
I <
N; ++
I) {
508 int &Partition = PtrToPartitions[
I];
514 int ThisPartition = this->InstToPartitionId[Inst];
516 Partition = ThisPartition;
518 else if (Partition == -1)
520 else if (Partition != (
int)ThisPartition)
523 assert(Partition != -2 &&
"Pointer not belonging to any partition");
526 return PtrToPartitions;
531 for (
const auto &
P : PartitionContainer) {
532 OS <<
"LDist: Partition " <<
Index++ <<
":";
541 const InstPartitionContainer &Partitions) {
542 Partitions.print(
OS);
549 for (
const auto &
P : PartitionContainer) {
550 OS <<
"LDist: Partition " <<
Index++ <<
":";
556 using PartitionContainerT = std::list<InstPartition>;
559 PartitionContainerT PartitionContainer;
563 InstToPartitionIdT InstToPartitionId;
571 template <
class UnaryPredicate>
572 void mergeAdjacentPartitionsIf(UnaryPredicate Predicate) {
573 InstPartition *PrevMatch =
nullptr;
574 for (
auto I = PartitionContainer.begin();
I != PartitionContainer.end();) {
576 if (PrevMatch ==
nullptr && DoesMatch) {
579 }
else if (PrevMatch !=
nullptr && DoesMatch) {
580 I->moveTo(*PrevMatch);
581 I = PartitionContainer.erase(
I);
590 void setNewLoopID(
MDNode *OrigLoopID, InstPartition *Part) {
597 Loop *NewLoop = Part->getDistributedLoop();
609class MemoryInstructionDependences {
615 unsigned NumUnsafeDependencesStartOrEnd = 0;
625 MemoryInstructionDependences(
631 for (
const auto &Dep : Dependences)
632 if (Dep.isPossiblyBackward()) {
636 ++Accesses[Dep.Source].NumUnsafeDependencesStartOrEnd;
637 --Accesses[Dep.Destination].NumUnsafeDependencesStartOrEnd;
644 AccessesType Accesses;
648class LoopDistributeForLoop {
653 :
L(
L),
F(
F), LI(LI), DT(DT), SE(SE), LAIs(LAIs), ORE(ORE) {
659 assert(
L->isInnermost() &&
"Only process inner loops.");
662 <<
L->getHeader()->getParent()->getName() <<
"' from "
663 <<
L->getLocStr() <<
"\n");
666 if (!
L->getExitBlock())
667 return fail(
"MultipleExitBlocks",
"multiple exit blocks");
668 if (!
L->isLoopSimplifyForm())
669 return fail(
"NotLoopSimplifyForm",
670 "loop is not in loop-simplify form");
671 if (!
L->isRotatedForm())
672 return fail(
"NotBottomTested",
"loop is not bottom tested");
676 LAI = &LAIs.getInfo(*L);
681 return fail(
"MemOpsCanBeVectorized",
682 "memory operations are safe for vectorization");
685 if (!Dependences || Dependences->empty())
686 return fail(
"NoUnsafeDeps",
"no unsafe dependences to isolate");
689 <<
L->getHeader()->getName() <<
"\n");
691 InstPartitionContainer Partitions(L, LI, DT);
716 int NumUnsafeDependencesActive = 0;
717 for (
const auto &InstDep : MID) {
721 if (NumUnsafeDependencesActive ||
722 InstDep.NumUnsafeDependencesStartOrEnd > 0)
723 Partitions.addToCyclicPartition(
I);
725 Partitions.addToNewNonCyclicPartition(
I);
726 NumUnsafeDependencesActive += InstDep.NumUnsafeDependencesStartOrEnd;
727 assert(NumUnsafeDependencesActive >= 0 &&
728 "Negative number of dependences active");
737 for (
auto *Inst : DefsUsedOutside)
738 Partitions.addToNewNonCyclicPartition(Inst);
740 LLVM_DEBUG(
dbgs() <<
"LDist: Seeded partitions:\n" << Partitions);
741 if (Partitions.getSize() < 2)
742 return fail(
"CantIsolateUnsafeDeps",
743 "cannot isolate unsafe dependencies");
747 Partitions.mergeBeforePopulating();
748 LLVM_DEBUG(
dbgs() <<
"LDist: Merged partitions:\n" << Partitions);
749 if (Partitions.getSize() < 2)
750 return fail(
"CantIsolateUnsafeDeps",
751 "cannot isolate unsafe dependencies");
754 Partitions.populateUsedSet();
755 LLVM_DEBUG(
dbgs() <<
"LDist: Populated partitions:\n" << Partitions);
759 if (Partitions.mergeToAvoidDuplicatedLoads()) {
760 LLVM_DEBUG(
dbgs() <<
"LDist: Partitions merged to ensure unique loads:\n"
762 if (Partitions.getSize() < 2)
763 return fail(
"CantIsolateUnsafeDeps",
764 "cannot isolate unsafe dependencies");
771 return fail(
"RuntimeCheckWithConvergent",
772 "may not insert runtime check with convergent operation");
778 return fail(
"TooManySCEVRuntimeChecks",
779 "too many SCEV run-time checks needed.\n");
782 return fail(
"HeuristicDisabled",
"distribution heuristic disabled");
785 <<
L->getHeader()->getName() <<
"\n");
788 Partitions.setupPartitionIdOnInstructions();
791 auto PtrToPartition = Partitions.computePartitionSetForPointers(*LAI);
793 const auto &AllChecks = RtPtrChecking->
getChecks();
794 auto Checks = includeOnlyCrossPartitionChecks(AllChecks, PtrToPartition,
798 return fail(
"RuntimeCheckWithConvergent",
799 "may not insert runtime check with convergent operation");
811 MDNode *OrigLoopID =
L->getLoopID();
816 LVer.versionLoop(DefsUsedOutside);
817 LVer.annotateLoopWithNoAlias();
825 "llvm.loop.distribute.",
true);
826 LVer.getNonVersionedLoop()->setLoopID(UnversionedLoopID);
831 Partitions.cloneLoops();
835 Partitions.removeUnusedInsts();
841 assert(DT->
verify(DominatorTree::VerificationLevel::Fast));
844 ++NumLoopsDistributed;
849 <<
"distributed loop";
857 bool Forced = isForced().value_or(
false);
864 L->getStartLoc(),
L->getHeader())
865 <<
"loop not distributed: use -Rpass-analysis=loop-distribute for "
874 RemarkName,
L->getStartLoc(),
L->getHeader())
875 <<
"loop not distributed: " << Message);
881 *F,
L->getStartLoc(),
"loop not distributed: failed "
882 "explicitly specified loop distribution"));
892 const std::optional<bool> &isForced()
const {
return IsForced; }
906 copy_if(AllChecks, std::back_inserter(Checks),
908 for (
unsigned PtrIdx1 :
Check.first->Members)
909 for (
unsigned PtrIdx2 :
Check.second->Members)
925 PtrToPartition, PtrIdx1, PtrIdx2))
936 std::optional<const MDOperand *>
Value =
942 assert(
Op && mdconst::hasa<ConstantInt>(*
Op) &&
"invalid metadata");
943 IsForced = mdconst::extract<ConstantInt>(*Op)->getZExtValue();
963 std::optional<bool> IsForced;
976 for (
Loop *TopLevelLoop : *LI)
979 if (L->isInnermost())
983 bool Changed =
false;
984 for (
Loop *L : Worklist) {
985 LoopDistributeForLoop LDL(L, &
F, LI, DT, SE, LAIs, ORE);
990 Changed |= LDL.processLoop();
1005 bool Changed =
runImpl(
F, &LI, &DT, &SE, &ORE, LAIs);
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg, SDValue Val={})
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 builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
std::optional< std::vector< StOtherPiece > > Other
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
static bool runImpl(Function &F, const TargetLowering &TLI)
This is the interface for a simple mod/ref and alias analysis over globals.
This header provides classes for managing per-loop analyses.
static const char *const LLVMLoopDistributeFollowupCoincident
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))
static cl::opt< bool > EnableLoopDistribute("enable-loop-distribute", cl::Hidden, cl::desc("Enable the new, experimental LoopDistribution Pass"), cl::init(false))
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"))
static const char *const LLVMLoopDistributeFollowupSequential
static const char *const LLVMLoopDistributeFollowupAll
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 clang loop " "distribute(enable)"))
static const char *const LLVMLoopDistributeFollowupFallback
static bool runImpl(Function &F, LoopInfo *LI, DominatorTree *DT, ScalarEvolution *SE, OptimizationRemarkEmitter *ORE, LoopAccessInfoManager &LAIs)
static cl::opt< bool > LDistVerify("loop-distribute-verify", cl::Hidden, cl::desc("Turn on DominatorTree and LoopInfo verification " "after Loop Distribution"), cl::init(false))
This header defines various interfaces for pass management in LLVM.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
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 unsigned getSize(unsigned Kind)
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.
iterator begin()
Instruction iterator methods.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor 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...
This class represents an Operation in the Expression.
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Dependence - This class represents a dependence between two memory memory references in a function.
Diagnostic information for optimization failures.
Analysis pass which computes a DominatorTree.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
This is an important class for using LLVM in a threaded context.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
This analysis provides dependence information for the memory accesses of a loop.
Drive the analysis of memory accesses in the loop.
const MemoryDepChecker & getDepChecker() const
the Memory Dependence Checker which can determine the loop-independent and loop-carried dependences b...
const RuntimePointerChecking * getRuntimePointerChecking() const
bool canVectorizeMemory() const
Return true we can analyze the memory accesses in the loop and there are no memory dependence cycles.
const PredicatedScalarEvolution & getPSE() const
Used to add runtime SCEV checks.
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.
SmallVector< Instruction *, 4 > getInstructionsForAccess(Value *Ptr, bool isWrite) const
Return the list of instructions that use Ptr to read or write memory.
bool hasConvergentOp() const
Return true if there is a convergent operation in the loop.
Analysis pass that exposes the LoopInfo for a function.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
void verify(const DominatorTreeBase< BlockT, false > &DomTree) const
This class emits a version of the loop where run-time checks ensure that may-alias pointers can't ove...
Represents a single loop in the control flow graph.
void setLoopID(MDNode *LoopID) const
Set the llvm.loop loop id metadata for this loop.
Tracking metadata reference owned by Metadata.
Checks memory dependences among accesses to the same underlying object to determine whether there vec...
const SmallVectorImpl< Instruction * > & getMemoryInstructions() const
The vector of memory access instructions.
const SmallVectorImpl< Dependence > * getDependences() const
Returns the memory dependences.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
const SCEVPredicate & getPredicate() const
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.
Holds information about the memory runtime legality checks to verify that a group of pointers do not ...
void printChecks(raw_ostream &OS, const SmallVectorImpl< RuntimePointerCheck > &Checks, unsigned Depth=0) const
Print Checks.
bool needsChecking(const RuntimeCheckingPtrGroup &M, const RuntimeCheckingPtrGroup &N) const
Decide if we need to add a check between two groups of pointers, according to needsChecking.
static bool arePointersInSamePartition(const SmallVectorImpl< int > &PtrToPartition, unsigned PtrIdx1, unsigned PtrIdx2)
Check if pointers are in the same partition.
SmallVector< PointerInfo, 2 > Pointers
Information about the pointers that may require checking.
const SmallVectorImpl< RuntimePointerCheck > & getChecks() const
Returns the checks that generateChecks created.
This class represents an assumption made using SCEV expressions which can be checked at run-time.
virtual unsigned getComplexity() const
Returns the estimated complexity of this predicate.
virtual bool isAlwaysTrue() const =0
Returns true if the predicate is always true.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
typename vector_type::const_iterator iterator
typename vector_type::const_iterator const_iterator
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
LLVM Value Representation.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
friend const_iterator begin(StringRef path, Style style)
Get begin iterator over path.
friend const_iterator end(StringRef path)
Get end iterator over path.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
initializer< Ty > init(const Ty &Val)
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
std::pair< const RuntimeCheckingPtrGroup *, const RuntimeCheckingPtrGroup * > RuntimePointerCheck
A memcheck which made up of a pair of grouped pointers.
std::optional< const MDOperand * > findStringMetadataForLoop(const Loop *TheLoop, StringRef Name)
Find string metadata for loop.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
std::optional< MDNode * > makeFollowupLoopID(MDNode *OrigLoopID, ArrayRef< StringRef > FollowupAttrs, const char *InheritOptionsAttrsPrefix="", bool AlwaysNew=false)
Create a new loop identifier for a loop created from a loop transformation.
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
SmallVector< Instruction *, 8 > findDefsUsedOutsideOfLoop(Loop *L)
Returns the instructions that use values defined in the loop.
auto reverse(ContainerTy &&C)
Loop * cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB, Loop *OrigLoop, ValueToValueMapTy &VMap, const Twine &NameSuffix, LoopInfo *LI, DominatorTree *DT, SmallVectorImpl< BasicBlock * > &Blocks)
Clones a loop OrigLoop.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool hasDisableAllTransformsHint(const Loop *L)
Look for the loop attribute that disables all transformation heuristic.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="", bool Before=false)
Split the specified block at the specified instruction.
iterator_range< df_iterator< T > > depth_first(const T &G)
Dependece between memory access instructions.