#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif //===- RegionInfo.h - SESE region analysis ----------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Calculate a program structure tree built out of single entry single exit // regions. // The basic ideas are taken from "The Program Structure Tree - Richard Johnson, // David Pearson, Keshav Pingali - 1994", however enriched with ideas from "The // Refined Process Structure Tree - Jussi Vanhatalo, Hagen Voelyer, Jana // Koehler - 2009". // The algorithm to calculate these data structures however is completely // different, as it takes advantage of existing information already available // in (Post)dominace tree and dominance frontier passes. This leads to a simpler // and in practice hopefully better performing algorithm. The runtime of the // algorithms described in the papers above are both linear in graph size, // O(V+E), whereas this algorithm is not, as the dominance frontier information // itself is not, but in practice runtime seems to be in the order of magnitude // of dominance tree calculation. // // WARNING: LLVM is generally very concerned about compile time such that // the use of additional analysis passes in the default // optimization sequence is avoided as much as possible. // Specifically, if you do not need the RegionInfo, but dominance // information could be sufficient please base your work only on // the dominator tree. Most passes maintain it, such that using // it has often near zero cost. In contrast RegionInfo is by // default not available, is not maintained by existing // transformations and there is no intention to do so. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_REGIONINFO_H #define LLVM_ANALYSIS_REGIONINFO_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include #include #include #include #include #include #include #include namespace llvm { class BasicBlock; class DominanceFrontier; class Loop; class LoopInfo; class PostDominatorTree; class Region; template class RegionBase; class RegionInfo; template class RegionInfoBase; class RegionNode; class raw_ostream; // Class to be specialized for different users of RegionInfo // (i.e. BasicBlocks or MachineBasicBlocks). This is only to avoid needing to // pass around an unreasonable number of template parameters. template struct RegionTraits { // FuncT // BlockT // RegionT // RegionNodeT // RegionInfoT using BrokenT = typename FuncT_::UnknownRegionTypeError; }; template <> struct RegionTraits { using FuncT = Function; using BlockT = BasicBlock; using RegionT = Region; using RegionNodeT = RegionNode; using RegionInfoT = RegionInfo; using DomTreeT = DominatorTree; using DomTreeNodeT = DomTreeNode; using DomFrontierT = DominanceFrontier; using PostDomTreeT = PostDominatorTree; using InstT = Instruction; using LoopT = Loop; using LoopInfoT = LoopInfo; static unsigned getNumSuccessors(BasicBlock *BB) { return BB->getTerminator()->getNumSuccessors(); } }; /// Marker class to iterate over the elements of a Region in flat mode. /// /// The class is used to either iterate in Flat mode or by not using it to not /// iterate in Flat mode. During a Flat mode iteration all Regions are entered /// and the iteration returns every BasicBlock. If the Flat mode is not /// selected for SubRegions just one RegionNode containing the subregion is /// returned. template class FlatIt {}; /// A RegionNode represents a subregion or a BasicBlock that is part of a /// Region. template class RegionNodeBase { friend class RegionBase; public: using BlockT = typename Tr::BlockT; using RegionT = typename Tr::RegionT; private: /// This is the entry basic block that starts this region node. If this is a /// BasicBlock RegionNode, then entry is just the basic block, that this /// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode. /// /// In the BBtoRegionNode map of the parent of this node, BB will always map /// to this node no matter which kind of node this one is. /// /// The node can hold either a Region or a BasicBlock. /// Use one bit to save, if this RegionNode is a subregion or BasicBlock /// RegionNode. PointerIntPair entry; /// The parent Region of this RegionNode. /// @see getParent() RegionT *parent; protected: /// Create a RegionNode. /// /// @param Parent The parent of this RegionNode. /// @param Entry The entry BasicBlock of the RegionNode. If this /// RegionNode represents a BasicBlock, this is the /// BasicBlock itself. If it represents a subregion, this /// is the entry BasicBlock of the subregion. /// @param isSubRegion If this RegionNode represents a SubRegion. inline RegionNodeBase(RegionT *Parent, BlockT *Entry, bool isSubRegion = false) : entry(Entry, isSubRegion), parent(Parent) {} public: RegionNodeBase(const RegionNodeBase &) = delete; RegionNodeBase &operator=(const RegionNodeBase &) = delete; /// Get the parent Region of this RegionNode. /// /// The parent Region is the Region this RegionNode belongs to. If for /// example a BasicBlock is element of two Regions, there exist two /// RegionNodes for this BasicBlock. Each with the getParent() function /// pointing to the Region this RegionNode belongs to. /// /// @return Get the parent Region of this RegionNode. inline RegionT *getParent() const { return parent; } /// Get the entry BasicBlock of this RegionNode. /// /// If this RegionNode represents a BasicBlock this is just the BasicBlock /// itself, otherwise we return the entry BasicBlock of the Subregion /// /// @return The entry BasicBlock of this RegionNode. inline BlockT *getEntry() const { return entry.getPointer(); } /// Get the content of this RegionNode. /// /// This can be either a BasicBlock or a subregion. Before calling getNodeAs() /// check the type of the content with the isSubRegion() function call. /// /// @return The content of this RegionNode. template inline T *getNodeAs() const; /// Is this RegionNode a subregion? /// /// @return True if it contains a subregion. False if it contains a /// BasicBlock. inline bool isSubRegion() const { return entry.getInt(); } }; //===----------------------------------------------------------------------===// /// A single entry single exit Region. /// /// A Region is a connected subgraph of a control flow graph that has exactly /// two connections to the remaining graph. It can be used to analyze or /// optimize parts of the control flow graph. /// /// A simple Region is connected to the remaining graph by just two /// edges. One edge entering the Region and another one leaving the Region. /// /// An extended Region (or just Region) is a subgraph that can be /// transform into a simple Region. The transformation is done by adding /// BasicBlocks that merge several entry or exit edges so that after the merge /// just one entry and one exit edge exists. /// /// The \e Entry of a Region is the first BasicBlock that is passed after /// entering the Region. It is an element of the Region. The entry BasicBlock /// dominates all BasicBlocks in the Region. /// /// The \e Exit of a Region is the first BasicBlock that is passed after /// leaving the Region. It is not an element of the Region. The exit BasicBlock, /// postdominates all BasicBlocks in the Region. /// /// A canonical Region cannot be constructed by combining smaller /// Regions. /// /// Region A is the \e parent of Region B, if B is completely contained in A. /// /// Two canonical Regions either do not intersect at all or one is /// the parent of the other. /// /// The Program Structure Tree is a graph (V, E) where V is the set of /// Regions in the control flow graph and E is the \e parent relation of these /// Regions. /// /// Example: /// /// \verbatim /// A simple control flow graph, that contains two regions. /// /// 1 /// / | /// 2 | /// / \ 3 /// 4 5 | /// | | | /// 6 7 8 /// \ | / /// \ |/ Region A: 1 -> 9 {1,2,3,4,5,6,7,8} /// 9 Region B: 2 -> 9 {2,4,5,6,7} /// \endverbatim /// /// You can obtain more examples by either calling /// /// "opt -passes='print' anyprogram.ll" /// or /// "opt -view-regions-only anyprogram.ll" /// /// on any LLVM file you are interested in. /// /// The first call returns a textual representation of the program structure /// tree, the second one creates a graphical representation using graphviz. template class RegionBase : public RegionNodeBase { friend class RegionInfoBase; using FuncT = typename Tr::FuncT; using BlockT = typename Tr::BlockT; using RegionInfoT = typename Tr::RegionInfoT; using RegionT = typename Tr::RegionT; using RegionNodeT = typename Tr::RegionNodeT; using DomTreeT = typename Tr::DomTreeT; using LoopT = typename Tr::LoopT; using LoopInfoT = typename Tr::LoopInfoT; using InstT = typename Tr::InstT; using BlockTraits = GraphTraits; using InvBlockTraits = GraphTraits>; using SuccIterTy = typename BlockTraits::ChildIteratorType; using PredIterTy = typename InvBlockTraits::ChildIteratorType; // Information necessary to manage this Region. RegionInfoT *RI; DomTreeT *DT; // The exit BasicBlock of this region. // (The entry BasicBlock is part of RegionNode) BlockT *exit; using RegionSet = std::vector>; // The subregions of this region. RegionSet children; using BBNodeMapT = std::map>; // Save the BasicBlock RegionNodes that are element of this Region. mutable BBNodeMapT BBNodeMap; /// Check if a BB is in this Region. This check also works /// if the region is incorrectly built. (EXPENSIVE!) void verifyBBInRegion(BlockT *BB) const; /// Walk over all the BBs of the region starting from BB and /// verify that all reachable basic blocks are elements of the region. /// (EXPENSIVE!) void verifyWalk(BlockT *BB, std::set *visitedBB) const; /// Verify if the region and its children are valid regions (EXPENSIVE!) void verifyRegionNest() const; public: /// Create a new region. /// /// @param Entry The entry basic block of the region. /// @param Exit The exit basic block of the region. /// @param RI The region info object that is managing this region. /// @param DT The dominator tree of the current function. /// @param Parent The surrounding region or NULL if this is a top level /// region. RegionBase(BlockT *Entry, BlockT *Exit, RegionInfoT *RI, DomTreeT *DT, RegionT *Parent = nullptr); RegionBase(const RegionBase &) = delete; RegionBase &operator=(const RegionBase &) = delete; /// Delete the Region and all its subregions. ~RegionBase(); /// Get the entry BasicBlock of the Region. /// @return The entry BasicBlock of the region. BlockT *getEntry() const { return RegionNodeBase::getEntry(); } /// Replace the entry basic block of the region with the new basic /// block. /// /// @param BB The new entry basic block of the region. void replaceEntry(BlockT *BB); /// Replace the exit basic block of the region with the new basic /// block. /// /// @param BB The new exit basic block of the region. void replaceExit(BlockT *BB); /// Recursively replace the entry basic block of the region. /// /// This function replaces the entry basic block with a new basic block. It /// also updates all child regions that have the same entry basic block as /// this region. /// /// @param NewEntry The new entry basic block. void replaceEntryRecursive(BlockT *NewEntry); /// Recursively replace the exit basic block of the region. /// /// This function replaces the exit basic block with a new basic block. It /// also updates all child regions that have the same exit basic block as /// this region. /// /// @param NewExit The new exit basic block. void replaceExitRecursive(BlockT *NewExit); /// Get the exit BasicBlock of the Region. /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel /// Region. BlockT *getExit() const { return exit; } /// Get the parent of the Region. /// @return The parent of the Region or NULL if this is a top level /// Region. RegionT *getParent() const { return RegionNodeBase::getParent(); } /// Get the RegionNode representing the current Region. /// @return The RegionNode representing the current Region. RegionNodeT *getNode() const { return const_cast( reinterpret_cast(this)); } /// Get the nesting level of this Region. /// /// An toplevel Region has depth 0. /// /// @return The depth of the region. unsigned getDepth() const; /// Check if a Region is the TopLevel region. /// /// The toplevel region represents the whole function. bool isTopLevelRegion() const { return exit == nullptr; } /// Return a new (non-canonical) region, that is obtained by joining /// this region with its predecessors. /// /// @return A region also starting at getEntry(), but reaching to the next /// basic block that forms with getEntry() a (non-canonical) region. /// NULL if such a basic block does not exist. RegionT *getExpandedRegion() const; /// Return the first block of this region's single entry edge, /// if existing. /// /// @return The BasicBlock starting this region's single entry edge, /// else NULL. BlockT *getEnteringBlock() const; /// Return the first block of this region's single exit edge, /// if existing. /// /// @return The BasicBlock starting this region's single exit edge, /// else NULL. BlockT *getExitingBlock() const; /// Collect all blocks of this region's single exit edge, if existing. /// /// @return True if this region contains all the predecessors of the exit. bool getExitingBlocks(SmallVectorImpl &Exitings) const; /// Is this a simple region? /// /// A region is simple if it has exactly one exit and one entry edge. /// /// @return True if the Region is simple. bool isSimple() const; /// Returns the name of the Region. /// @return The Name of the Region. std::string getNameStr() const; /// Return the RegionInfo object, that belongs to this Region. RegionInfoT *getRegionInfo() const { return RI; } /// PrintStyle - Print region in difference ways. enum PrintStyle { PrintNone, PrintBB, PrintRN }; /// Print the region. /// /// @param OS The output stream the Region is printed to. /// @param printTree Print also the tree of subregions. /// @param level The indentation level used for printing. void print(raw_ostream &OS, bool printTree = true, unsigned level = 0, PrintStyle Style = PrintNone) const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// Print the region to stderr. void dump() const; #endif /// Check if the region contains a BasicBlock. /// /// @param BB The BasicBlock that might be contained in this Region. /// @return True if the block is contained in the region otherwise false. bool contains(const BlockT *BB) const; /// Check if the region contains another region. /// /// @param SubRegion The region that might be contained in this Region. /// @return True if SubRegion is contained in the region otherwise false. bool contains(const RegionT *SubRegion) const { // Toplevel Region. if (!getExit()) return true; return contains(SubRegion->getEntry()) && (contains(SubRegion->getExit()) || SubRegion->getExit() == getExit()); } /// Check if the region contains an Instruction. /// /// @param Inst The Instruction that might be contained in this region. /// @return True if the Instruction is contained in the region otherwise /// false. bool contains(const InstT *Inst) const { return contains(Inst->getParent()); } /// Check if the region contains a loop. /// /// @param L The loop that might be contained in this region. /// @return True if the loop is contained in the region otherwise false. /// In case a NULL pointer is passed to this function the result /// is false, except for the region that describes the whole function. /// In that case true is returned. bool contains(const LoopT *L) const; /// Get the outermost loop in the region that contains a loop. /// /// Find for a Loop L the outermost loop OuterL that is a parent loop of L /// and is itself contained in the region. /// /// @param L The loop the lookup is started. /// @return The outermost loop in the region, NULL if such a loop does not /// exist or if the region describes the whole function. LoopT *outermostLoopInRegion(LoopT *L) const; /// Get the outermost loop in the region that contains a basic block. /// /// Find for a basic block BB the outermost loop L that contains BB and is /// itself contained in the region. /// /// @param LI A pointer to a LoopInfo analysis. /// @param BB The basic block surrounded by the loop. /// @return The outermost loop in the region, NULL if such a loop does not /// exist or if the region describes the whole function. LoopT *outermostLoopInRegion(LoopInfoT *LI, BlockT *BB) const; /// Get the subregion that starts at a BasicBlock /// /// @param BB The BasicBlock the subregion should start. /// @return The Subregion if available, otherwise NULL. RegionT *getSubRegionNode(BlockT *BB) const; /// Get the RegionNode for a BasicBlock /// /// @param BB The BasicBlock at which the RegionNode should start. /// @return If available, the RegionNode that represents the subregion /// starting at BB. If no subregion starts at BB, the RegionNode /// representing BB. RegionNodeT *getNode(BlockT *BB) const; /// Get the BasicBlock RegionNode for a BasicBlock /// /// @param BB The BasicBlock for which the RegionNode is requested. /// @return The RegionNode representing the BB. RegionNodeT *getBBNode(BlockT *BB) const; /// Add a new subregion to this Region. /// /// @param SubRegion The new subregion that will be added. /// @param moveChildren Move the children of this region, that are also /// contained in SubRegion into SubRegion. void addSubRegion(RegionT *SubRegion, bool moveChildren = false); /// Remove a subregion from this Region. /// /// The subregion is not deleted, as it will probably be inserted into another /// region. /// @param SubRegion The SubRegion that will be removed. RegionT *removeSubRegion(RegionT *SubRegion); /// Move all direct child nodes of this Region to another Region. /// /// @param To The Region the child nodes will be transferred to. void transferChildrenTo(RegionT *To); /// Verify if the region is a correct region. /// /// Check if this is a correctly build Region. This is an expensive check, as /// the complete CFG of the Region will be walked. void verifyRegion() const; /// Clear the cache for BB RegionNodes. /// /// After calling this function the BasicBlock RegionNodes will be stored at /// different memory locations. RegionNodes obtained before this function is /// called are therefore not comparable to RegionNodes abtained afterwords. void clearNodeCache(); /// @name Subregion Iterators /// /// These iterators iterator over all subregions of this Region. //@{ using iterator = typename RegionSet::iterator; using const_iterator = typename RegionSet::const_iterator; iterator begin() { return children.begin(); } iterator end() { return children.end(); } const_iterator begin() const { return children.begin(); } const_iterator end() const { return children.end(); } //@} /// @name BasicBlock Iterators /// /// These iterators iterate over all BasicBlocks that are contained in this /// Region. The iterator also iterates over BasicBlocks that are elements of /// a subregion of this Region. It is therefore called a flat iterator. //@{ template class block_iterator_wrapper : public df_iterator< std::conditional_t *> { using super = df_iterator *>; public: using Self = block_iterator_wrapper; using value_type = typename super::value_type; // Construct the begin iterator. block_iterator_wrapper(value_type Entry, value_type Exit) : super(df_begin(Entry)) { // Mark the exit of the region as visited, so that the children of the // exit and the exit itself, i.e. the block outside the region will never // be visited. super::Visited.insert(Exit); } // Construct the end iterator. block_iterator_wrapper() : super(df_end((BlockT *)nullptr)) {} /*implicit*/ block_iterator_wrapper(super I) : super(I) {} // FIXME: Even a const_iterator returns a non-const BasicBlock pointer. // This was introduced for backwards compatibility, but should // be removed as soon as all users are fixed. BlockT *operator*() const { return const_cast(super::operator*()); } }; using block_iterator = block_iterator_wrapper; using const_block_iterator = block_iterator_wrapper; block_iterator block_begin() { return block_iterator(getEntry(), getExit()); } block_iterator block_end() { return block_iterator(); } const_block_iterator block_begin() const { return const_block_iterator(getEntry(), getExit()); } const_block_iterator block_end() const { return const_block_iterator(); } using block_range = iterator_range; using const_block_range = iterator_range; /// Returns a range view of the basic blocks in the region. inline block_range blocks() { return block_range(block_begin(), block_end()); } /// Returns a range view of the basic blocks in the region. /// /// This is the 'const' version of the range view. inline const_block_range blocks() const { return const_block_range(block_begin(), block_end()); } //@} /// @name Element Iterators /// /// These iterators iterate over all BasicBlock and subregion RegionNodes that /// are direct children of this Region. It does not iterate over any /// RegionNodes that are also element of a subregion of this Region. //@{ using element_iterator = df_iterator, false, GraphTraits>; using const_element_iterator = df_iterator, false, GraphTraits>; element_iterator element_begin(); element_iterator element_end(); iterator_range elements() { return make_range(element_begin(), element_end()); } const_element_iterator element_begin() const; const_element_iterator element_end() const; iterator_range elements() const { return make_range(element_begin(), element_end()); } //@} }; /// Print a RegionNode. template inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase &Node); //===----------------------------------------------------------------------===// /// Analysis that detects all canonical Regions. /// /// The RegionInfo pass detects all canonical regions in a function. The Regions /// are connected using the parent relation. This builds a Program Structure /// Tree. template class RegionInfoBase { friend class RegionInfo; friend class MachineRegionInfo; using BlockT = typename Tr::BlockT; using FuncT = typename Tr::FuncT; using RegionT = typename Tr::RegionT; using RegionInfoT = typename Tr::RegionInfoT; using DomTreeT = typename Tr::DomTreeT; using DomTreeNodeT = typename Tr::DomTreeNodeT; using PostDomTreeT = typename Tr::PostDomTreeT; using DomFrontierT = typename Tr::DomFrontierT; using BlockTraits = GraphTraits; using InvBlockTraits = GraphTraits>; using SuccIterTy = typename BlockTraits::ChildIteratorType; using PredIterTy = typename InvBlockTraits::ChildIteratorType; using BBtoBBMap = DenseMap; using BBtoRegionMap = DenseMap; RegionInfoBase(); RegionInfoBase(RegionInfoBase &&Arg) : DT(std::move(Arg.DT)), PDT(std::move(Arg.PDT)), DF(std::move(Arg.DF)), TopLevelRegion(std::move(Arg.TopLevelRegion)), BBtoRegion(std::move(Arg.BBtoRegion)) { Arg.wipe(); } RegionInfoBase &operator=(RegionInfoBase &&RHS) { DT = std::move(RHS.DT); PDT = std::move(RHS.PDT); DF = std::move(RHS.DF); TopLevelRegion = std::move(RHS.TopLevelRegion); BBtoRegion = std::move(RHS.BBtoRegion); RHS.wipe(); return *this; } virtual ~RegionInfoBase(); DomTreeT *DT; PostDomTreeT *PDT; DomFrontierT *DF; /// The top level region. RegionT *TopLevelRegion = nullptr; /// Map every BB to the smallest region, that contains BB. BBtoRegionMap BBtoRegion; protected: /// Update refences to a RegionInfoT held by the RegionT managed here /// /// This is a post-move helper. Regions hold references to the owning /// RegionInfo object. After a move these need to be fixed. template void updateRegionTree(RegionInfoT &RI, TheRegionT *R) { if (!R) return; R->RI = &RI; for (auto &SubR : *R) updateRegionTree(RI, SubR.get()); } private: /// Wipe this region tree's state without releasing any resources. /// /// This is essentially a post-move helper only. It leaves the object in an /// assignable and destroyable state, but otherwise invalid. void wipe() { DT = nullptr; PDT = nullptr; DF = nullptr; TopLevelRegion = nullptr; BBtoRegion.clear(); } // Check whether the entries of BBtoRegion for the BBs of region // SR are correct. Triggers an assertion if not. Calls itself recursively for // subregions. void verifyBBMap(const RegionT *SR) const; // Returns true if BB is in the dominance frontier of // entry, because it was inherited from exit. In the other case there is an // edge going from entry to BB without passing exit. bool isCommonDomFrontier(BlockT *BB, BlockT *entry, BlockT *exit) const; // Check if entry and exit surround a valid region, based on // dominance tree and dominance frontier. bool isRegion(BlockT *entry, BlockT *exit) const; // Saves a shortcut pointing from entry to exit. // This function may extend this shortcut if possible. void insertShortCut(BlockT *entry, BlockT *exit, BBtoBBMap *ShortCut) const; // Returns the next BB that postdominates N, while skipping // all post dominators that cannot finish a canonical region. DomTreeNodeT *getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const; // A region is trivial, if it contains only one BB. bool isTrivialRegion(BlockT *entry, BlockT *exit) const; // Creates a single entry single exit region. RegionT *createRegion(BlockT *entry, BlockT *exit); // Detect all regions starting with bb 'entry'. void findRegionsWithEntry(BlockT *entry, BBtoBBMap *ShortCut); // Detects regions in F. void scanForRegions(FuncT &F, BBtoBBMap *ShortCut); // Get the top most parent with the same entry block. RegionT *getTopMostParent(RegionT *region); // Build the region hierarchy after all region detected. void buildRegionsTree(DomTreeNodeT *N, RegionT *region); // Update statistic about created regions. virtual void updateStatistics(RegionT *R) = 0; // Detect all regions in function and build the region tree. void calculate(FuncT &F); public: RegionInfoBase(const RegionInfoBase &) = delete; RegionInfoBase &operator=(const RegionInfoBase &) = delete; static bool VerifyRegionInfo; static typename RegionT::PrintStyle printStyle; void print(raw_ostream &OS) const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const; #endif void releaseMemory(); /// Get the smallest region that contains a BasicBlock. /// /// @param BB The basic block. /// @return The smallest region, that contains BB or NULL, if there is no /// region containing BB. RegionT *getRegionFor(BlockT *BB) const; /// Set the smallest region that surrounds a basic block. /// /// @param BB The basic block surrounded by a region. /// @param R The smallest region that surrounds BB. void setRegionFor(BlockT *BB, RegionT *R); /// A shortcut for getRegionFor(). /// /// @param BB The basic block. /// @return The smallest region, that contains BB or NULL, if there is no /// region containing BB. RegionT *operator[](BlockT *BB) const; /// Return the exit of the maximal refined region, that starts at a /// BasicBlock. /// /// @param BB The BasicBlock the refined region starts. BlockT *getMaxRegionExit(BlockT *BB) const; /// Find the smallest region that contains two regions. /// /// @param A The first region. /// @param B The second region. /// @return The smallest region containing A and B. RegionT *getCommonRegion(RegionT *A, RegionT *B) const; /// Find the smallest region that contains two basic blocks. /// /// @param A The first basic block. /// @param B The second basic block. /// @return The smallest region that contains A and B. RegionT *getCommonRegion(BlockT *A, BlockT *B) const { return getCommonRegion(getRegionFor(A), getRegionFor(B)); } /// Find the smallest region that contains a set of regions. /// /// @param Regions A vector of regions. /// @return The smallest region that contains all regions in Regions. RegionT *getCommonRegion(SmallVectorImpl &Regions) const; /// Find the smallest region that contains a set of basic blocks. /// /// @param BBs A vector of basic blocks. /// @return The smallest region that contains all basic blocks in BBS. RegionT *getCommonRegion(SmallVectorImpl &BBs) const; RegionT *getTopLevelRegion() const { return TopLevelRegion; } /// Clear the Node Cache for all Regions. /// /// @see Region::clearNodeCache() void clearNodeCache() { if (TopLevelRegion) TopLevelRegion->clearNodeCache(); } void verifyAnalysis() const; }; class RegionNode : public RegionNodeBase> { public: inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) : RegionNodeBase>(Parent, Entry, isSubRegion) {} bool operator==(const Region &RN) const { return this == reinterpret_cast(&RN); } }; class Region : public RegionBase> { public: Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo *RI, DominatorTree *DT, Region *Parent = nullptr); ~Region(); bool operator==(const RegionNode &RN) const { return &RN == reinterpret_cast(this); } }; class RegionInfo : public RegionInfoBase> { public: using Base = RegionInfoBase>; explicit RegionInfo(); RegionInfo(RegionInfo &&Arg) : Base(std::move(static_cast(Arg))) { updateRegionTree(*this, TopLevelRegion); } RegionInfo &operator=(RegionInfo &&RHS) { Base::operator=(std::move(static_cast(RHS))); updateRegionTree(*this, TopLevelRegion); return *this; } ~RegionInfo() override; /// Handle invalidation explicitly. bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &); // updateStatistics - Update statistic about created regions. void updateStatistics(Region *R) final; void recalculate(Function &F, DominatorTree *DT, PostDominatorTree *PDT, DominanceFrontier *DF); #ifndef NDEBUG /// Opens a viewer to show the GraphViz visualization of the regions. /// /// Useful during debugging as an alternative to dump(). void view(); /// Opens a viewer to show the GraphViz visualization of this region /// without instructions in the BasicBlocks. /// /// Useful during debugging as an alternative to dump(). void viewOnly(); #endif }; class RegionInfoPass : public FunctionPass { RegionInfo RI; public: static char ID; explicit RegionInfoPass(); ~RegionInfoPass() override; RegionInfo &getRegionInfo() { return RI; } const RegionInfo &getRegionInfo() const { return RI; } /// @name FunctionPass interface //@{ bool runOnFunction(Function &F) override; void releaseMemory() override; void verifyAnalysis() const override; void getAnalysisUsage(AnalysisUsage &AU) const override; void print(raw_ostream &OS, const Module *) const override; void dump() const; //@} }; /// Analysis pass that exposes the \c RegionInfo for a function. class RegionInfoAnalysis : public AnalysisInfoMixin { friend AnalysisInfoMixin; static AnalysisKey Key; public: using Result = RegionInfo; RegionInfo run(Function &F, FunctionAnalysisManager &AM); }; /// Printer pass for the \c RegionInfo. class RegionInfoPrinterPass : public PassInfoMixin { raw_ostream &OS; public: explicit RegionInfoPrinterPass(raw_ostream &OS); PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; /// Verifier pass for the \c RegionInfo. struct RegionInfoVerifierPass : PassInfoMixin { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; template <> template <> inline BasicBlock * RegionNodeBase>::getNodeAs() const { assert(!isSubRegion() && "This is not a BasicBlock RegionNode!"); return getEntry(); } template <> template <> inline Region * RegionNodeBase>::getNodeAs() const { assert(isSubRegion() && "This is not a subregion RegionNode!"); auto Unconst = const_cast> *>(this); return reinterpret_cast(Unconst); } template inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase &Node) { using BlockT = typename Tr::BlockT; using RegionT = typename Tr::RegionT; if (Node.isSubRegion()) return OS << Node.template getNodeAs()->getNameStr(); else return OS << Node.template getNodeAs()->getName(); } extern template class RegionBase>; extern template class RegionNodeBase>; extern template class RegionInfoBase>; } // end namespace llvm #endif // LLVM_ANALYSIS_REGIONINFO_H #ifdef __GNUC__ #pragma GCC diagnostic pop #endif