40#ifndef LLVM_SUPPORT_GENERICLOOPINFO_H
41#define LLVM_SUPPORT_GENERICLOOPINFO_H
53template <
class N,
class M>
class LoopBase;
59template <
class BlockT,
class LoopT>
class LoopBase {
62 std::vector<LoopT *> SubLoops;
75 unsigned BlockLen = 0;
76 unsigned BlockCapacity = 0;
78 static constexpr unsigned BorrowedCapacity = -1u;
84#if LLVM_ENABLE_ABI_BREAKING_CHECKS
86 bool IsInvalid =
false;
100 for (
const LoopT *CurLoop = ParentLoop; CurLoop;
101 CurLoop = CurLoop->ParentLoop)
119 const LoopT *L =
static_cast<const LoopT *
>(
this);
120 while (L->ParentLoop)
126 LoopT *L =
static_cast<LoopT *
>(
this);
127 while (L->ParentLoop)
149 L = L->getParentLoop();
164 if (BB->getParent() != LI->ParentPtr)
166 return contains(LI->lookupLoopFor(BB));
170 template <
class InstT>
bool contains(
const InstT *Inst)
const {
179 using iterator =
typename std::vector<LoopT *>::const_iterator;
181 typename std::vector<LoopT *>::const_reverse_iterator;
225#if LLVM_ENABLE_ABI_BREAKING_CHECKS
258 [&](BlockT *Pred) {
return contains(Pred); });
334 template <
class Type>
338 PreOrderWorklist.
append(L.rbegin(), L.rend());
340 while (!PreOrderWorklist.
empty()) {
344 PreOrderWorklist.
append(L->rbegin(), L->rend());
353 const LoopT *CurLoop =
static_cast<const LoopT *
>(
this);
356 return PreOrderLoops;
360 LoopT *CurLoop =
static_cast<LoopT *
>(
this);
363 return PreOrderLoops;
381 assert(!NewChild->ParentLoop &&
"NewChild already has a parent!");
382 NewChild->ParentLoop =
static_cast<LoopT *
>(
this);
383 SubLoops.push_back(NewChild);
390 assert(
I != SubLoops.end() &&
"Cannot remove end iterator!");
392 assert(Child->ParentLoop ==
this &&
"Child is not a child of this loop!");
393 SubLoops.erase(SubLoops.begin() + (
I -
begin()));
394 Child->ParentLoop =
nullptr;
411 if (BlockCapacity == BorrowedCapacity || BlockLen == BlockCapacity)
412 LI->reallocBlocks(*
static_cast<LoopT *
>(
this),
413 std::max(2 * BlockLen, 4u));
420 if (BlockCapacity <
Size)
421 LI->reallocBlocks(*
static_cast<LoopT *
>(
this),
Size);
430 LI->materializeBlocks(*
static_cast<LoopT *
>(
this));
431 for (
unsigned i = 0;; ++i) {
432 assert(i != BlockLen &&
"Loop does not contain BB!");
446 LI->materializeBlocks(*
static_cast<LoopT *
>(
this));
449 assert(
I != Blocks.
end() &&
"N is not in this list!");
450 std::move(
I + 1, Blocks.
end(),
I);
468 unsigned Depth = 0)
const;
481 for (
auto *SubLoop : SubLoops)
484#if LLVM_ENABLE_ABI_BREAKING_CHECKS
496 ParentLoop =
nullptr;
500template <
class BlockT,
class LoopT>
511template <
class BlockT,
class LoopT>
class LoopInfoBase {
513 "LoopInfo requires GraphTraits<BlockT *>::getNumber (see "
514 "GraphHasNodeNumbers)");
520 using ParentT =
decltype(std::declval<BlockT *>()->getParent());
521 ParentT ParentPtr =
nullptr;
522 unsigned BlockNumberEpoch;
524 std::vector<LoopT *> TopLevelLoops;
528 std::unique_ptr<BlockT *[]> BlockLayout;
532 friend class LoopBase<BlockT, LoopT>;
535 void operator=(
const LoopInfoBase &) =
delete;
544 TopLevelLoops(
std::
move(Arg.TopLevelLoops)),
545 BlockLayout(
std::
move(Arg.BlockLayout)),
546 LoopAllocator(
std::
move(Arg.LoopAllocator)) {
547 ParentPtr = Arg.ParentPtr;
548 BlockNumberEpoch = Arg.BlockNumberEpoch;
549 resetLoopInfoOwners();
551 Arg.TopLevelLoops.clear();
554 BBMap = std::move(
RHS.BBMap);
555 ParentPtr =
RHS.ParentPtr;
556 BlockNumberEpoch =
RHS.BlockNumberEpoch;
558 for (
auto *L : TopLevelLoops)
561 TopLevelLoops = std::move(
RHS.TopLevelLoops);
562 BlockLayout = std::move(
RHS.BlockLayout);
563 LoopAllocator = std::move(
RHS.LoopAllocator);
564 resetLoopInfoOwners();
565 RHS.TopLevelLoops.clear();
572 for (
auto *L : TopLevelLoops)
574 TopLevelLoops.clear();
576 LoopAllocator.Reset();
580 LoopT *Storage = LoopAllocator.Allocate<LoopT>();
581 LoopT *L =
new (Storage) LoopT();
589 using iterator =
typename std::vector<LoopT *>::const_iterator;
591 typename std::vector<LoopT *>::const_reverse_iterator;
596 bool empty()
const {
return TopLevelLoops.empty(); }
618 void resetLoopInfoOwners() {
620 TopLevelLoops.end());
621 while (!Worklist.empty()) {
622 LoopT *L = Worklist.pop_back_val();
624 Worklist.append(L->begin(), L->end());
630 verifyBlockNumberEpoch(
const std::remove_pointer_t<ParentT> *BBParent)
const {
631 assert(ParentPtr == BBParent &&
632 "loop info queried with block of other function");
633 assert(BlockNumberEpoch ==
634 GraphTraits<ParentT>::getNumberEpoch(ParentPtr) &&
635 "loop info used with outdated block numbers");
640 LoopT *lookupLoopFor(
const BlockT *BB)
const {
641 unsigned Number = GraphTraits<const BlockT *>::getNumber(BB);
646 using ReuseLoopT = function_ref<LoopT *(BlockT *)>;
652 LoopT *allocateLoop(BlockT *Header, ReuseLoopT ReuseLoop) {
653 LoopT *
L = ReuseLoop ? ReuseLoop(Header) : nullptr;
656 L->PendingHeader = Header;
662 function_ref<
const DominatorTreeBase<BlockT, false> &()> GetDomTree,
663 ReuseLoopT ReuseLoop);
664 void analyzeImpl(
const DominatorTreeBase<BlockT, false> &DomTree,
665 ReuseLoopT ReuseLoop);
669 static BlockT *pendingHeader(
const LoopT *L) {
return L->PendingHeader; }
672 static bool hasBorrowedBlocks(
const LoopT &L) {
673 return L.BlockCapacity == LoopT::BorrowedCapacity;
679 void reallocBlocks(LoopT &L,
unsigned NewCapacity) {
680 assert(NewCapacity >=
L.BlockLen &&
"capacity below size");
681 BlockT **
New = LoopAllocator.Allocate<BlockT *>(NewCapacity);
684 L.BlockCapacity = NewCapacity;
688 void materializeBlocks(LoopT &L) {
689 if (hasBorrowedBlocks(L))
690 reallocBlocks(L,
L.BlockLen);
697 verifyBlockNumberEpoch(BB->getParent());
698 return lookupLoopFor(BB);
708 return L ? L->getLoopDepth() : 0;
712 using Edge = std::pair<BlockT *, BlockT *>;
727 template <
typename PredicateT>
729 materializeBlocks(L);
738 template <
typename PredicateT>
740 std::vector<LoopT *> &
List = Parent ? Parent->SubLoops : TopLevelLoops;
745 Child->ParentLoop =
nullptr;
766 return L && L->getHeader() == BB;
776 assert(
I !=
end() &&
"Cannot remove end iterator!");
778 assert(L->isOutermost() &&
"Not a top-level loop!");
779 TopLevelLoops.erase(TopLevelLoops.begin() + (
I -
begin()));
787 verifyBlockNumberEpoch(BB->getParent());
789 if (
Number >= BBMap.size()) {
791 GraphTraits<
decltype(BB->getParent())>::getMaxNumber(BB->getParent());
801 assert(!New->ParentLoop &&
"New loop already has a parent!");
802 LoopT *Parent = Old->ParentLoop;
803 auto &Siblings = Parent ? Parent->SubLoops : TopLevelLoops;
804 auto I =
find(Siblings, Old);
805 assert(
I != Siblings.end() &&
"Old loop is not among its siblings!");
807 Old->ParentLoop =
nullptr;
808 New->ParentLoop = Parent;
813 assert(New->isOutermost() &&
"Loop already in subloop!");
814 TopLevelLoops.push_back(New);
821 verifyBlockNumberEpoch(BB->getParent());
823 if (
Number >= BBMap.size())
826 for (LoopT *L = BBMap[
Number]; L; L = L->getParentLoop())
827 L->removeBlockFromLoop(BB);
834 const LoopT *ParentLoop) {
837 if (SubLoop == ParentLoop)
888 LoopAllocator.Deallocate(L);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseSet and SmallDenseSet classes.
This file defines a set of templates that efficiently compute a dominator tree over a generic graph.
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file defines generic set operations that may be used on set's of different types,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const_pointer const_iterator
Implements a dense probed hash-table based set.
Core dominator tree base class.
Instances of this class are used to represent loops that are detected in the flow graph.
bool isAnnotatedParallel() const
Returns true if the loop is annotated parallel.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within this loop.
static void getInnerLoopsInPreorder(const LoopT &L, SmallVectorImpl< Type > &PreOrderLoops)
Return all inner loops in the loop nest rooted by the loop in preorder, with siblings in forward prog...
typename std::vector< LoopT * >::const_iterator iterator
bool isOutermost() const
Return true if the loop does not have a parent (natural) loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
void reserveBlocks(unsigned Size)
interface to do reserve() for Blocks
bool isInnermost() const
Return true if the loop does not contain any (natural) loops.
void removeBlockFromLoop(BlockT *BB)
This removes the specified basic block from the current loop, updating the Blocks as appropriate.
void getExitBlocks(SmallVectorImpl< BlockT * > &ExitBlocks) const
Return all of the successor blocks of this loop.
bool contains(const InstT *Inst) const
Return true if the specified instruction is in this loop.
unsigned getNumBlocks() const
Get the number of blocks in this loop in constant time.
void verifyLoop() const
Verify loop structure.
void verifyLoopNest(DenseSet< const LoopT * > *Loops) const
Verify loop structure of this loop and all nested loops.
SmallVector< LoopT *, 4 > getLoopsInPreorder()
typename std::vector< LoopT * >::const_reverse_iterator reverse_iterator
unsigned getNumBackEdges() const
Calculate the number of back edges to the loop header.
SmallVector< const LoopT *, 4 > getLoopsInPreorder() const
Return all loops in the loop nest rooted by the loop in preorder, with siblings in forward program or...
void getExitingBlocks(SmallVectorImpl< BlockT * > &ExitingBlocks) const
Return all blocks inside the loop that have successors outside of the loop.
const std::vector< LoopT * > & getSubLoops() const
Return the loops contained entirely within this loop.
BlockT * getHeader() const
const LoopT * getOutermostLoop() const
Get the outermost loop in which this loop is contained.
void getLoopLatches(SmallVectorImpl< BlockT * > &LoopLatches) const
Return all loop latch blocks of this loop.
unsigned getLoopDepth() const
Return the nesting level of this loop.
LoopBase()
This creates an empty loop.
void print(raw_ostream &OS, bool Verbose=false, bool PrintNested=true, unsigned Depth=0) const
Print loop with all the BBs inside it.
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)
This method is used by other analyses to update loop information.
LoopT * removeChildLoop(LoopT *Child)
This removes the specified child from being a subloop of this loop.
iterator_range< block_iterator > blocks() const
block_iterator block_end() const
bool isInvalid() const
Return true if this loop is no longer valid.
BlockT * getLoopPredecessor() const
If the given loop's header has exactly one unique predecessor outside the loop, return it.
bool contains(const BlockT *BB) const
Return true if the specified basic block is in this loop, using LoopInfo's block-to-loop map.
bool isLoopLatch(const BlockT *BB) const
void addChildLoop(LoopT *NewChild)
Add the specified loop to be a child of this loop.
void addBlockEntry(BlockT *BB)
This adds a basic block directly to the basic block list.
reverse_iterator rbegin() const
BlockT * getExitBlock() const
If getExitBlocks would return exactly one block, return that block.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
reverse_iterator rend() const
BlockT * getExitingBlock() const
If getExitingBlocks would return exactly one block, return that block.
LoopT * getOutermostLoop()
void getUniqueExitBlocks(SmallVectorImpl< BlockT * > &ExitBlocks) const
Return all unique successor blocks of this loop.
void setParentLoop(LoopT *L)
This is a raw interface for bypassing addChildLoop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
bool hasDedicatedExits() const
Return true if no exit block for the loop has a predecessor that is outside the loop.
void getUniqueNonLatchExitBlocks(SmallVectorImpl< BlockT * > &ExitBlocks) const
Return all unique successor blocks of this loop except successors from Latch block are not considered...
bool isLoopExiting(const BlockT *BB) const
True if terminator in the block can branch to another block that is outside of the current loop.
block_iterator block_begin() const
void moveToHeader(BlockT *BB)
This method is used to move BB (which must be part of this loop) to be the loop header of the loop (t...
typename ArrayRef< BlockT * >::const_iterator block_iterator
BlockT * getUniqueExitBlock() const
If getUniqueExitBlocks would return exactly one block, return that block.
LoopT * removeChildLoop(iterator I)
This removes the specified child from being a subloop of this loop.
This class builds and contains all of the top-level loop structures in the specified function.
const std::vector< LoopT * > & getTopLevelLoops() const
Return the top-level loops.
SmallVector< std::pair< LoopT *, BlockT * >, 4 > recompute(const DominatorTreeBase< BlockT, false > &DomTree)
Rebuild the loop forest from the CFG, refilling the existing loop object of every block that still he...
void addTopLevelLoop(LoopT *New)
This adds the specified loop to the collection of top-level loops.
void analyze(const DominatorTreeBase< BlockT, false > &DomTree)
Analyze the function DomTree describes.
bool hasNoExitBlocks(const LoopT &L) const
Return true if L does not have any exit blocks.
SmallVector< LoopT *, 4 > getLoopsInReverseSiblingPreorder() const
Return all of the loops in the function in preorder across the loop nests, with siblings in reverse p...
void print(raw_ostream &OS) const
reverse_iterator rend() const
void removeBlock(BlockT *BB)
This method completely removes BB from all data structures, including all of the Loop objects it is n...
LoopInfoBase(LoopInfoBase &&Arg)
const LoopT * operator[](const BlockT *BB) const
Same as getLoopFor.
void analyze(ParentT F, function_ref< const DominatorTreeBase< BlockT, false > &()> GetDomTree)
Call GetDomTree if a dominator tree is needed.
bool isLoopHeader(const BlockT *BB) const
LoopT * removeLoop(iterator I)
This removes the specified top-level loop from this loop info object.
LoopT * getSmallestCommonLoop(BlockT *A, BlockT *B) const
Find the innermost loop containing both given blocks.
SmallVector< LoopT *, 4 > getLoopsInPreorder() const
Return all of the loops in the function in preorder across the loop nests, with siblings in forward p...
LoopT * getSmallestCommonLoop(LoopT *A, LoopT *B) const
Find the innermost loop containing both given loops.
typename std::vector< Loop * >::const_iterator iterator
typename std::vector< Loop * >::const_reverse_iterator reverse_iterator
unsigned getLoopDepth(const BlockT *BB) const
Return the loop nesting level of the specified block.
void analyze(ParentT F)
Create the loop forest for a function.
void replaceLoop(LoopT *Old, LoopT *New)
Replace a loop among its siblings (a parent loop's child list or the top-level list) with a new loop.
SmallVector< LoopT *, 4 > takeChildrenIf(LoopT *Parent, PredicateT Pred)
Detach and return the children of Parent (the top-level loops if Parent is null) that satisfy Pred,...
BlockT * getUniqueLatchExitBlock(const LoopT &L) const
Return the unique exit block for the latch of L, or null if there are multiple different exit blocks ...
void getExitEdges(const LoopT &L, SmallVectorImpl< Edge > &ExitEdges) const
Return all pairs of (inside_block,outside_block).
static bool isNotAlreadyContainedIn(const LoopT *SubLoop, const LoopT *ParentLoop)
void removeBlocksIf(LoopT &L, PredicateT Pred)
Remove every block satisfying Pred from L's block list, preserving the order of the remaining blocks.
reverse_iterator rbegin() const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
std::pair< BasicBlock *, BasicBlock * > Edge
LoopInfoBase & operator=(LoopInfoBase &&RHS)
void destroy(LoopT *L)
Destroy a loop that has been removed from the LoopInfo nest.
void changeLoopFor(const BlockT *BB, LoopT *L)
Change the top-level loop that contains BB to the specified loop.
Represents a single loop in the control flow graph.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr bool GraphHasNodeNumbers
Indicate whether a GraphTraits<NodeT>::getNumber() is supported.
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
iterator_range< typename GraphTraits< Inverse< GraphType > >::ChildIteratorType > inverse_children(const typename GraphTraits< GraphType >::NodeRef &G)
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Implement std::hash so that hash_code can be used in STL containers.