X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FAnalysis%2FRegionInfo.h;h=4988386fdc82ca548532aa1f146010c15e1ebeea;hb=152b80c1ee088dc65151051ab42e07a8e75c5101;hp=8af02e3efbdd60092697e5069183619df99e62df;hpb=087ab613f42890b2e84fb8a058f346ead2bfd595;p=oota-llvm.git diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 8af02e3efbd..4988386fdc8 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -22,24 +22,77 @@ // 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/DepthFirstIterator.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/Analysis/DominanceFrontier.h" -#include "llvm/Analysis/PostDominators.h" -#include "llvm/Support/Allocator.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Dominators.h" #include +#include +#include namespace llvm { -class Region; -class RegionInfo; -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 + typedef typename FuncT_::UnknownRegionTypeError BrokenT; +}; + +class DominatorTree; +class DominanceFrontier; class Loop; class LoopInfo; +struct PostDominatorTree; +class raw_ostream; +class Region; +template +class RegionBase; +class RegionNode; +class RegionInfo; +template +class RegionInfoBase; + +template <> +struct RegionTraits { + typedef Function FuncT; + typedef BasicBlock BlockT; + typedef Region RegionT; + typedef RegionNode RegionNodeT; + typedef RegionInfo RegionInfoT; + typedef DominatorTree DomTreeT; + typedef DomTreeNode DomTreeNodeT; + typedef DominanceFrontier DomFrontierT; + typedef PostDominatorTree PostDomTreeT; + typedef Instruction InstT; + typedef Loop LoopT; + typedef LoopInfo LoopInfoT; + + static unsigned getNumSuccessors(BasicBlock *BB) { + return BB->getTerminator()->getNumSuccessors(); + } +}; /// @brief Marker class to iterate over the elements of a Region in flat mode. /// @@ -53,11 +106,18 @@ class FlatIt {}; /// @brief A RegionNode represents a subregion or a BasicBlock that is part of a /// Region. -class RegionNode { - RegionNode(const RegionNode &) LLVM_DELETED_FUNCTION; - const RegionNode &operator=(const RegionNode &) LLVM_DELETED_FUNCTION; +template +class RegionNodeBase { + friend class RegionBase; + +public: + typedef typename Tr::BlockT BlockT; + typedef typename Tr::RegionT RegionT; + +private: + RegionNodeBase(const RegionNodeBase &) = delete; + const RegionNodeBase &operator=(const RegionNodeBase &) = delete; -protected: /// 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. @@ -68,13 +128,13 @@ protected: /// 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; + PointerIntPair entry; /// @brief The parent Region of this RegionNode. /// @see getParent() - Region* parent; + RegionT *parent; -public: +protected: /// @brief Create a RegionNode. /// /// @param Parent The parent of this RegionNode. @@ -83,9 +143,11 @@ public: /// BasicBlock itself. If it represents a subregion, this /// is the entry BasicBlock of the subregion. /// @param isSubRegion If this RegionNode represents a SubRegion. - inline RegionNode(Region* Parent, BasicBlock* Entry, bool isSubRegion = 0) - : entry(Entry, isSubRegion), parent(Parent) {} + inline RegionNodeBase(RegionT *Parent, BlockT *Entry, + bool isSubRegion = false) + : entry(Entry, isSubRegion), parent(Parent) {} +public: /// @brief Get the parent Region of this RegionNode. /// /// The parent Region is the Region this RegionNode belongs to. If for @@ -94,7 +156,7 @@ public: /// pointing to the Region this RegionNode belongs to. /// /// @return Get the parent Region of this RegionNode. - inline Region* getParent() const { return parent; } + inline RegionT *getParent() const { return parent; } /// @brief Get the entry BasicBlock of this RegionNode. /// @@ -102,7 +164,7 @@ public: /// itself, otherwise we return the entry BasicBlock of the Subregion /// /// @return The entry BasicBlock of this RegionNode. - inline BasicBlock* getEntry() const { return entry.getPointer(); } + inline BlockT *getEntry() const { return entry.getPointer(); } /// @brief Get the content of this RegionNode. /// @@ -110,33 +172,15 @@ public: /// check the type of the content with the isSubRegion() function call. /// /// @return The content of this RegionNode. - template - inline T* getNodeAs() const; + template inline T *getNodeAs() const; /// @brief 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(); - } + inline bool isSubRegion() const { return entry.getInt(); } }; -/// Print a RegionNode. -inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node); - -template<> -inline BasicBlock* RegionNode::getNodeAs() const { - assert(!isSubRegion() && "This is not a BasicBlock RegionNode!"); - return getEntry(); -} - -template<> -inline Region* RegionNode::getNodeAs() const { - assert(isSubRegion() && "This is not a subregion RegionNode!"); - return reinterpret_cast(const_cast(this)); -} - //===----------------------------------------------------------------------===// /// @brief A single entry single exit Region. /// @@ -199,40 +243,55 @@ inline Region* RegionNode::getNodeAs() const { /// /// The first call returns a textual representation of the program structure /// tree, the second one creates a graphical representation using graphviz. -class Region : public RegionNode { - friend class RegionInfo; - Region(const Region &) LLVM_DELETED_FUNCTION; - const Region &operator=(const Region &) LLVM_DELETED_FUNCTION; +template +class RegionBase : public RegionNodeBase { + typedef typename Tr::FuncT FuncT; + typedef typename Tr::BlockT BlockT; + typedef typename Tr::RegionInfoT RegionInfoT; + typedef typename Tr::RegionT RegionT; + typedef typename Tr::RegionNodeT RegionNodeT; + typedef typename Tr::DomTreeT DomTreeT; + typedef typename Tr::LoopT LoopT; + typedef typename Tr::LoopInfoT LoopInfoT; + typedef typename Tr::InstT InstT; + + typedef GraphTraits BlockTraits; + typedef GraphTraits> InvBlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + typedef typename InvBlockTraits::ChildIteratorType PredIterTy; + + friend class RegionInfoBase; + RegionBase(const RegionBase &) = delete; + const RegionBase &operator=(const RegionBase &) = delete; // Information necessary to manage this Region. - RegionInfo* RI; - DominatorTree *DT; + RegionInfoT *RI; + DomTreeT *DT; // The exit BasicBlock of this region. // (The entry BasicBlock is part of RegionNode) - BasicBlock *exit; + BlockT *exit; - typedef std::vector RegionSet; + typedef std::vector> RegionSet; // The subregions of this region. RegionSet children; - typedef std::map BBNodeMapT; + typedef std::map BBNodeMapT; // Save the BasicBlock RegionNodes that are element of this Region. mutable BBNodeMapT BBNodeMap; - /// verifyBBInRegion - Check if a BB is in this Region. This check also works + /// Check if a BB is in this Region. This check also works /// if the region is incorrectly built. (EXPENSIVE!) - void verifyBBInRegion(BasicBlock* BB) const; + void verifyBBInRegion(BlockT *BB) const; - /// verifyWalk - Walk over all the BBs of the region starting from BB and + /// 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(BasicBlock* BB, std::set* visitedBB) const; + void verifyWalk(BlockT *BB, std::set *visitedBB) const; - /// verifyRegionNest - Verify if the region and its children are valid - /// regions (EXPENSIVE!) + /// Verify if the region and its children are valid regions (EXPENSIVE!) void verifyRegionNest() const; public: @@ -244,27 +303,29 @@ public: /// @param DT The dominator tree of the current function. /// @param Parent The surrounding region or NULL if this is a top level /// region. - Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo* RI, - DominatorTree *DT, Region *Parent = 0); + RegionBase(BlockT *Entry, BlockT *Exit, RegionInfoT *RI, DomTreeT *DT, + RegionT *Parent = nullptr); /// Delete the Region and all its subregions. - ~Region(); + ~RegionBase(); /// @brief Get the entry BasicBlock of the Region. /// @return The entry BasicBlock of the region. - BasicBlock *getEntry() const { return RegionNode::getEntry(); } + BlockT *getEntry() const { + return RegionNodeBase::getEntry(); + } /// @brief 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(BasicBlock *BB); + void replaceEntry(BlockT *BB); /// @brief 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(BasicBlock *BB); + void replaceExit(BlockT *BB); /// @brief Recursively replace the entry basic block of the region. /// @@ -273,7 +334,7 @@ public: /// this region. /// /// @param NewEntry The new entry basic block. - void replaceEntryRecursive(BasicBlock *NewEntry); + void replaceEntryRecursive(BlockT *NewEntry); /// @brief Recursively replace the exit basic block of the region. /// @@ -282,22 +343,25 @@ public: /// this region. /// /// @param NewExit The new exit basic block. - void replaceExitRecursive(BasicBlock *NewExit); + void replaceExitRecursive(BlockT *NewExit); /// @brief Get the exit BasicBlock of the Region. /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel /// Region. - BasicBlock *getExit() const { return exit; } + BlockT *getExit() const { return exit; } /// @brief Get the parent of the Region. /// @return The parent of the Region or NULL if this is a top level /// Region. - Region *getParent() const { return RegionNode::getParent(); } + RegionT *getParent() const { + return RegionNodeBase::getParent(); + } /// @brief Get the RegionNode representing the current Region. /// @return The RegionNode representing the current Region. - RegionNode* getNode() const { - return const_cast(reinterpret_cast(this)); + RegionNodeT *getNode() const { + return const_cast( + reinterpret_cast(this)); } /// @brief Get the nesting level of this Region. @@ -310,7 +374,7 @@ public: /// @brief Check if a Region is the TopLevel region. /// /// The toplevel region represents the whole function. - bool isTopLevelRegion() const { return exit == NULL; } + bool isTopLevelRegion() const { return exit == nullptr; } /// @brief Return a new (non-canonical) region, that is obtained by joining /// this region with its predecessors. @@ -318,21 +382,21 @@ public: /// @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. - Region *getExpandedRegion() const; + RegionT *getExpandedRegion() const; /// @brief 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. - BasicBlock *getEnteringBlock() const; + BlockT *getEnteringBlock() const; /// @brief 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. - BasicBlock *getExitingBlock() const; + BlockT *getExitingBlock() const; /// @brief Is this a simple region? /// @@ -346,50 +410,50 @@ public: std::string getNameStr() const; /// @brief Return the RegionInfo object, that belongs to this Region. - RegionInfo *getRegionInfo() const { - return RI; - } + RegionInfoT *getRegionInfo() const { return RI; } /// PrintStyle - Print region in difference ways. - enum PrintStyle { PrintNone, PrintBB, PrintRN }; + enum PrintStyle { PrintNone, PrintBB, PrintRN }; /// @brief 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, - enum PrintStyle Style = PrintNone) const; + void print(raw_ostream &OS, bool printTree = true, unsigned level = 0, + PrintStyle Style = PrintNone) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// @brief Print the region to stderr. void dump() const; +#endif /// @brief 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 BasicBlock *BB) const; + bool contains(const BlockT *BB) const; /// @brief 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 Region *SubRegion) const { + bool contains(const RegionT *SubRegion) const { // Toplevel Region. if (!getExit()) return true; - return contains(SubRegion->getEntry()) - && (contains(SubRegion->getExit()) || SubRegion->getExit() == getExit()); + return contains(SubRegion->getEntry()) && + (contains(SubRegion->getExit()) || + SubRegion->getExit() == getExit()); } /// @brief 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 Instruction *Inst) const { - return contains(Inst->getParent()); - } + /// @return True if the Instruction is contained in the region otherwise + /// false. + bool contains(const InstT *Inst) const { return contains(Inst->getParent()); } /// @brief Check if the region contains a loop. /// @@ -398,7 +462,7 @@ public: /// 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 Loop *L) const; + bool contains(const LoopT *L) const; /// @brief Get the outermost loop in the region that contains a loop. /// @@ -408,7 +472,7 @@ public: /// @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. - Loop *outermostLoopInRegion(Loop *L) const; + LoopT *outermostLoopInRegion(LoopT *L) const; /// @brief Get the outermost loop in the region that contains a basic block. /// @@ -419,13 +483,13 @@ public: /// @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. - Loop *outermostLoopInRegion(LoopInfo *LI, BasicBlock* BB) const; + LoopT *outermostLoopInRegion(LoopInfoT *LI, BlockT *BB) const; /// @brief Get the subregion that starts at a BasicBlock /// /// @param BB The BasicBlock the subregion should start. /// @return The Subregion if available, otherwise NULL. - Region* getSubRegionNode(BasicBlock *BB) const; + RegionT *getSubRegionNode(BlockT *BB) const; /// @brief Get the RegionNode for a BasicBlock /// @@ -433,32 +497,32 @@ public: /// @return If available, the RegionNode that represents the subregion /// starting at BB. If no subregion starts at BB, the RegionNode /// representing BB. - RegionNode* getNode(BasicBlock *BB) const; + RegionNodeT *getNode(BlockT *BB) const; /// @brief Get the BasicBlock RegionNode for a BasicBlock /// /// @param BB The BasicBlock for which the RegionNode is requested. /// @return The RegionNode representing the BB. - RegionNode* getBBNode(BasicBlock *BB) const; + RegionNodeT *getBBNode(BlockT *BB) const; /// @brief 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(Region *SubRegion, bool moveChildren = false); + void addSubRegion(RegionT *SubRegion, bool moveChildren = false); /// @brief 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. - Region *removeSubRegion(Region *SubRegion); + RegionT *removeSubRegion(RegionT *SubRegion); /// @brief Move all direct child nodes of this Region to another Region. /// /// @param To The Region the child nodes will be transferred to. - void transferChildrenTo(Region *To); + void transferChildrenTo(RegionT *To); /// @brief Verify if the region is a correct region. /// @@ -477,8 +541,8 @@ public: /// /// These iterators iterator over all subregions of this Region. //@{ - typedef RegionSet::iterator iterator; - typedef RegionSet::const_iterator const_iterator; + typedef typename RegionSet::iterator iterator; + typedef typename RegionSet::const_iterator const_iterator; iterator begin() { return children.begin(); } iterator end() { return children.end(); } @@ -495,20 +559,18 @@ public: //@{ template class block_iterator_wrapper - : public df_iterator::type*> { - typedef df_iterator::type*> - super; + : public df_iterator< + typename std::conditional::type *> { + typedef df_iterator< + typename std::conditional::type *> super; + public: typedef block_iterator_wrapper Self; typedef typename super::pointer pointer; // Construct the begin iterator. - block_iterator_wrapper(pointer Entry, pointer Exit) : super(df_begin(Entry)) - { + block_iterator_wrapper(pointer Entry, pointer 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. @@ -516,34 +578,43 @@ public: } // Construct the end iterator. - block_iterator_wrapper() : super(df_end((BasicBlock *)0)) {} + 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. - BasicBlock *operator*() const { - return const_cast(super::operator*()); + BlockT *operator*() const { + return const_cast(super::operator*()); } }; typedef block_iterator_wrapper block_iterator; - typedef block_iterator_wrapper const_block_iterator; + typedef block_iterator_wrapper const_block_iterator; - block_iterator block_begin() { - return block_iterator(getEntry(), getExit()); - } + block_iterator block_begin() { return block_iterator(getEntry(), getExit()); } - block_iterator block_end() { - return block_iterator(); - } + 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(); + const_block_iterator block_end() const { return const_block_iterator(); } + + typedef iterator_range block_range; + typedef iterator_range const_block_range; + + /// @brief Returns a range view of the basic blocks in the region. + inline block_range blocks() { + return block_range(block_begin(), block_end()); + } + + /// @brief 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()); } //@} @@ -553,12 +624,12 @@ public: /// are direct children of this Region. It does not iterate over any /// RegionNodes that are also element of a subregion of this Region. //@{ - typedef df_iterator, false, - GraphTraits > element_iterator; + typedef df_iterator, false, + GraphTraits> element_iterator; - typedef df_iterator, - false, GraphTraits > - const_element_iterator; + typedef df_iterator, + false, + GraphTraits> const_element_iterator; element_iterator element_begin(); element_iterator element_end(); @@ -568,132 +639,150 @@ public: //@} }; +/// Print a RegionNode. +template +inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase &Node); + //===----------------------------------------------------------------------===// /// @brief 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. -class RegionInfo : public FunctionPass { - typedef DenseMap BBtoBBMap; - typedef DenseMap BBtoRegionMap; - typedef SmallPtrSet RegionSet; +template +class RegionInfoBase { + typedef typename Tr::BlockT BlockT; + typedef typename Tr::FuncT FuncT; + typedef typename Tr::RegionT RegionT; + typedef typename Tr::RegionInfoT RegionInfoT; + typedef typename Tr::DomTreeT DomTreeT; + typedef typename Tr::DomTreeNodeT DomTreeNodeT; + typedef typename Tr::PostDomTreeT PostDomTreeT; + typedef typename Tr::DomFrontierT DomFrontierT; + typedef GraphTraits BlockTraits; + typedef GraphTraits> InvBlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + typedef typename InvBlockTraits::ChildIteratorType PredIterTy; + + friend class RegionInfo; + friend class MachineRegionInfo; + typedef DenseMap BBtoBBMap; + typedef DenseMap BBtoRegionMap; + typedef SmallPtrSet RegionSet; + + RegionInfoBase(); + virtual ~RegionInfoBase(); - RegionInfo(const RegionInfo &) LLVM_DELETED_FUNCTION; - const RegionInfo &operator=(const RegionInfo &) LLVM_DELETED_FUNCTION; + RegionInfoBase(const RegionInfoBase &) = delete; + const RegionInfoBase &operator=(const RegionInfoBase &) = delete; - DominatorTree *DT; - PostDominatorTree *PDT; - DominanceFrontier *DF; + DomTreeT *DT; + PostDomTreeT *PDT; + DomFrontierT *DF; /// The top level region. - Region *TopLevelRegion; + RegionT *TopLevelRegion; +private: /// Map every BB to the smallest region, that contains BB. BBtoRegionMap BBtoRegion; - // isCommonDomFrontier - Returns true if BB is in the dominance frontier of + // 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(BasicBlock* BB, BasicBlock* entry, - BasicBlock* exit) const; + bool isCommonDomFrontier(BlockT *BB, BlockT *entry, BlockT *exit) const; - // isRegion - Check if entry and exit surround a valid region, based on + // Check if entry and exit surround a valid region, based on // dominance tree and dominance frontier. - bool isRegion(BasicBlock* entry, BasicBlock* exit) const; + bool isRegion(BlockT *entry, BlockT *exit) const; - // insertShortCut - Saves a shortcut pointing from entry to exit. + // Saves a shortcut pointing from entry to exit. // This function may extend this shortcut if possible. - void insertShortCut(BasicBlock* entry, BasicBlock* exit, - BBtoBBMap* ShortCut) const; + void insertShortCut(BlockT *entry, BlockT *exit, BBtoBBMap *ShortCut) const; - // getNextPostDom - Returns the next BB that postdominates N, while skipping + // Returns the next BB that postdominates N, while skipping // all post dominators that cannot finish a canonical region. - DomTreeNode *getNextPostDom(DomTreeNode* N, BBtoBBMap *ShortCut) const; - - // isTrivialRegion - A region is trivial, if it contains only one BB. - bool isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const; - - // createRegion - Creates a single entry single exit region. - Region *createRegion(BasicBlock *entry, BasicBlock *exit); + DomTreeNodeT *getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const; - // findRegionsWithEntry - Detect all regions starting with bb 'entry'. - void findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut); + // A region is trivial, if it contains only one BB. + bool isTrivialRegion(BlockT *entry, BlockT *exit) const; - // scanForRegions - Detects regions in F. - void scanForRegions(Function &F, BBtoBBMap *ShortCut); + // Creates a single entry single exit region. + RegionT *createRegion(BlockT *entry, BlockT *exit); - // getTopMostParent - Get the top most parent with the same entry block. - Region *getTopMostParent(Region *region); + // Detect all regions starting with bb 'entry'. + void findRegionsWithEntry(BlockT *entry, BBtoBBMap *ShortCut); - // buildRegionsTree - build the region hierarchy after all region detected. - void buildRegionsTree(DomTreeNode *N, Region *region); + // Detects regions in F. + void scanForRegions(FuncT &F, BBtoBBMap *ShortCut); - // Calculate - detecte all regions in function and build the region tree. - void Calculate(Function& F); + // Get the top most parent with the same entry block. + RegionT *getTopMostParent(RegionT *region); - void releaseMemory(); + // Build the region hierarchy after all region detected. + void buildRegionsTree(DomTreeNodeT *N, RegionT *region); - // updateStatistics - Update statistic about created regions. - void updateStatistics(Region *R); + // Update statistic about created regions. + virtual void updateStatistics(RegionT *R) = 0; - // isSimple - Check if a region is a simple region with exactly one entry - // edge and exactly one exit edge. - bool isSimple(Region* R) const; + // Detect all regions in function and build the region tree. + void calculate(FuncT &F); public: - static char ID; - explicit RegionInfo(); + static bool VerifyRegionInfo; + static typename RegionT::PrintStyle printStyle; - ~RegionInfo(); + void print(raw_ostream &OS) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + void dump() const; +#endif - /// @name FunctionPass interface - //@{ - virtual bool runOnFunction(Function &F); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void print(raw_ostream &OS, const Module *) const; - virtual void verifyAnalysis() const; - //@} + void releaseMemory(); /// @brief 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. - Region *getRegionFor(BasicBlock *BB) const; + RegionT *getRegionFor(BlockT *BB) const; /// @brief 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(BasicBlock *BB, Region *R); + void setRegionFor(BlockT *BB, RegionT *R); /// @brief 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. - Region *operator[](BasicBlock *BB) const; + RegionT *operator[](BlockT *BB) const; /// @brief Return the exit of the maximal refined region, that starts at a /// BasicBlock. /// /// @param BB The BasicBlock the refined region starts. - BasicBlock *getMaxRegionExit(BasicBlock *BB) const; + BlockT *getMaxRegionExit(BlockT *BB) const; /// @brief 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. - Region *getCommonRegion(Region* A, Region *B) const; + RegionT *getCommonRegion(RegionT *A, RegionT *B) const; /// @brief 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. - Region* getCommonRegion(BasicBlock* A, BasicBlock *B) const { + RegionT *getCommonRegion(BlockT *A, BlockT *B) const { return getCommonRegion(getRegionFor(A), getRegionFor(B)); } @@ -701,23 +790,15 @@ public: /// /// @param Regions A vector of regions. /// @return The smallest region that contains all regions in Regions. - Region* getCommonRegion(SmallVectorImpl &Regions) const; + RegionT *getCommonRegion(SmallVectorImpl &Regions) const; /// @brief 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. - Region* getCommonRegion(SmallVectorImpl &BBs) const; - - Region *getTopLevelRegion() const { - return TopLevelRegion; - } + RegionT *getCommonRegion(SmallVectorImpl &BBs) const; - /// @brief Update RegionInfo after a basic block was split. - /// - /// @param NewBB The basic block that was created before OldBB. - /// @param OldBB The old basic block. - void splitBlock(BasicBlock* NewBB, BasicBlock *OldBB); + RegionT *getTopLevelRegion() const { return TopLevelRegion; } /// @brief Clear the Node Cache for all Regions. /// @@ -726,14 +807,115 @@ public: if (TopLevelRegion) TopLevelRegion->clearNodeCache(); } + + void verifyAnalysis() const; }; -inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node) { +class Region; + +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: + explicit RegionInfo(); + + ~RegionInfo() override; + + // updateStatistics - Update statistic about created regions. + void updateStatistics(Region *R) final; + + void recalculate(Function &F, DominatorTree *DT, PostDominatorTree *PDT, + DominanceFrontier *DF); + +#ifndef NDEBUG + /// @brief Opens a viewer to show the GraphViz visualization of the regions. + /// + /// Useful during debugging as an alternative to dump(). + void view(); + + /// @brief 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; + //@} +}; + +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) { + typedef typename Tr::BlockT BlockT; + typedef typename Tr::RegionT RegionT; + if (Node.isSubRegion()) - return OS << Node.getNodeAs()->getNameStr(); + return OS << Node.template getNodeAs()->getNameStr(); else - return OS << Node.getNodeAs()->getName(); + return OS << Node.template getNodeAs()->getName(); } + +extern template class RegionBase>; +extern template class RegionNodeBase>; +extern template class RegionInfoBase>; + } // End llvm namespace #endif -