From 5e1c96a6324f6fdeda1457d114886db37ef0c803 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 19 Jul 2014 18:29:29 +0000 Subject: [PATCH] Templatify RegionInfo so it works on MachineBasicBlocks git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213456 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/RegionInfo.h | 484 +++++++----- include/llvm/Analysis/RegionInfoImpl.h | 919 +++++++++++++++++++++++ include/llvm/Analysis/RegionIterator.h | 119 +-- include/llvm/CodeGen/MachineRegionInfo.h | 183 +++++ include/llvm/InitializePasses.h | 3 +- lib/Analysis/Analysis.cpp | 2 +- lib/Analysis/RegionInfo.cpp | 854 ++------------------- lib/Analysis/RegionPass.cpp | 4 +- lib/Analysis/RegionPrinter.cpp | 51 +- lib/CodeGen/CMakeLists.txt | 1 + lib/CodeGen/MachineRegionInfo.cpp | 137 ++++ lib/Transforms/Scalar/StructurizeCFG.cpp | 6 +- 12 files changed, 1739 insertions(+), 1024 deletions(-) create mode 100644 include/llvm/Analysis/RegionInfoImpl.h create mode 100644 include/llvm/CodeGen/MachineRegionInfo.h create mode 100644 lib/CodeGen/MachineRegionInfo.cpp diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 93a1a48720f..cdf8277e02c 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -37,21 +37,62 @@ #ifndef LLVM_ANALYSIS_REGIONINFO_H #define LLVM_ANALYSIS_REGIONINFO_H +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/iterator_range.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; +// RegionTraits - 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. /// @@ -65,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 &) LLVM_DELETED_FUNCTION; + const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION; -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. @@ -80,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. @@ -95,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 @@ -106,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. /// @@ -114,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. /// @@ -122,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. /// @@ -211,37 +243,53 @@ 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 &) LLVM_DELETED_FUNCTION; + const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION; // 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 /// 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 /// 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!) @@ -256,27 +304,27 @@ 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 = nullptr); + 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 RegionNodeT::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. /// @@ -285,7 +333,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. /// @@ -294,22 +342,23 @@ 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 RegionNodeT::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. @@ -330,21 +379,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? /// @@ -358,20 +407,18 @@ 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; /// @brief Print the region to stderr. void dump() const; @@ -380,28 +427,28 @@ public: /// /// @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. /// @@ -410,7 +457,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. /// @@ -420,7 +467,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. /// @@ -431,13 +478,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 /// @@ -445,32 +492,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. /// @@ -489,8 +536,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(); } @@ -507,18 +554,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. @@ -526,35 +573,29 @@ public: } // Construct the end iterator. - block_iterator_wrapper() : super(df_end((BasicBlock *)nullptr)) {} + 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; @@ -578,12 +619,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(); @@ -593,132 +634,147 @@ 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; - RegionInfo(const RegionInfo &) LLVM_DELETED_FUNCTION; - const RegionInfo &operator=(const RegionInfo &) LLVM_DELETED_FUNCTION; + friend class RegionInfo; + friend class MachineRegionInfo; + typedef DenseMap BBtoBBMap; + typedef DenseMap BBtoRegionMap; + typedef SmallPtrSet RegionSet; - DominatorTree *DT; - PostDominatorTree *PDT; - DominanceFrontier *DF; + RegionInfoBase(); + ~RegionInfoBase(); + + RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION; + const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION; + + 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 // 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 // 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. // 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 // all post dominators that cannot finish a canonical region. - DomTreeNode *getNextPostDom(DomTreeNode* N, BBtoBBMap *ShortCut) const; + DomTreeNodeT *getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const; // isTrivialRegion - A region is trivial, if it contains only one BB. - bool isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const; + bool isTrivialRegion(BlockT *entry, BlockT *exit) const; // createRegion - Creates a single entry single exit region. - Region *createRegion(BasicBlock *entry, BasicBlock *exit); + RegionT *createRegion(BlockT *entry, BlockT *exit); // findRegionsWithEntry - Detect all regions starting with bb 'entry'. - void findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut); + void findRegionsWithEntry(BlockT *entry, BBtoBBMap *ShortCut); // scanForRegions - Detects regions in F. - void scanForRegions(Function &F, BBtoBBMap *ShortCut); + void scanForRegions(FuncT &F, BBtoBBMap *ShortCut); // getTopMostParent - Get the top most parent with the same entry block. - Region *getTopMostParent(Region *region); + RegionT *getTopMostParent(RegionT *region); // buildRegionsTree - build the region hierarchy after all region detected. - void buildRegionsTree(DomTreeNode *N, Region *region); - - // Calculate - detecte all regions in function and build the region tree. - void Calculate(Function& F); - - void releaseMemory() override; + void buildRegionsTree(DomTreeNodeT *N, RegionT *region); // updateStatistics - Update statistic about created regions. - void updateStatistics(Region *R); + 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; + bool isSimple(RegionT *R) const; + + // calculate - 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; + void dump() const; - /// @name FunctionPass interface - //@{ - bool runOnFunction(Function &F) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - void print(raw_ostream &OS, const Module *) const override; - void verifyAnalysis() const override; - //@} + 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)); } @@ -726,23 +782,21 @@ 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; + RegionT *getCommonRegion(SmallVectorImpl &BBs) const; - Region *getTopLevelRegion() const { - return TopLevelRegion; - } + RegionT *getTopLevelRegion() const { return TopLevelRegion; } /// @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); + void splitBlock(BlockT *NewBB, BlockT *OldBB); /// @brief Clear the Node Cache for all Regions. /// @@ -751,14 +805,104 @@ public: if (TopLevelRegion) TopLevelRegion->clearNodeCache(); } + + void verifyAnalysis() const; }; -inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node) { - if (Node.isSubRegion()) - return OS << Node.getNodeAs()->getNameStr(); - else - return OS << Node.getNodeAs()->getName(); +class Region; + +class RegionNode : public RegionNodeBase> { +public: + inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) + : RegionNodeBase>(Parent, Entry, isSubRegion) {} + + ~RegionNode() {} + + 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(); + + virtual ~RegionInfo(); + + // updateStatistics - Update statistic about created regions. + void updateStatistics(Region *R) final; + + void recalculate(Function &F, DominatorTree *DT, PostDominatorTree *PDT, + DominanceFrontier *DF); +}; + +class RegionInfoPass : public FunctionPass { + RegionInfo RI; + +public: + static char ID; + explicit RegionInfoPass(); + + ~RegionInfoPass(); + + 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.template getNodeAs()->getNameStr(); + else + return OS << Node.template getNodeAs()->getName(); +} + +EXTERN_TEMPLATE_INSTANTIATION(class RegionBase>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase>); + } // End llvm namespace #endif - diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h new file mode 100644 index 00000000000..4266b84c32c --- /dev/null +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -0,0 +1,919 @@ +//===- RegionInfoImpl.h - SESE region detection analysis --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Detects single entry single exit regions in the control flow graph. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H +#define LLVM_ANALYSIS_REGIONINFOIMPL_H + +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionIterator.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include +#include + +using namespace llvm; + +#define DEBUG_TYPE "region" + +//===----------------------------------------------------------------------===// +/// RegionBase Implementation +template +RegionBase::RegionBase(BlockT *Entry, BlockT *Exit, + typename Tr::RegionInfoT *RInfo, DomTreeT *dt, + RegionT *Parent) + : RegionNodeBase(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {} + +template +RegionBase::~RegionBase() { + // Free the cached nodes. + for (typename BBNodeMapT::iterator it = BBNodeMap.begin(), + ie = BBNodeMap.end(); + it != ie; ++it) + delete it->second; + + // Only clean the cache for this Region. Caches of child Regions will be + // cleaned when the child Regions are deleted. + BBNodeMap.clear(); +} + +template +void RegionBase::replaceEntry(BlockT *BB) { + this->entry.setPointer(BB); +} + +template +void RegionBase::replaceExit(BlockT *BB) { + assert(exit && "No exit to replace!"); + exit = BB; +} + +template +void RegionBase::replaceEntryRecursive(BlockT *NewEntry) { + std::vector RegionQueue; + BlockT *OldEntry = getEntry(); + + RegionQueue.push_back(static_cast(this)); + while (!RegionQueue.empty()) { + RegionT *R = RegionQueue.back(); + RegionQueue.pop_back(); + + R->replaceEntry(NewEntry); + for (typename RegionT::const_iterator RI = R->begin(), RE = R->end(); + RI != RE; ++RI) { + if ((*RI)->getEntry() == OldEntry) + RegionQueue.push_back(RI->get()); + } + } +} + +template +void RegionBase::replaceExitRecursive(BlockT *NewExit) { + std::vector RegionQueue; + BlockT *OldExit = getExit(); + + RegionQueue.push_back(static_cast(this)); + while (!RegionQueue.empty()) { + RegionT *R = RegionQueue.back(); + RegionQueue.pop_back(); + + R->replaceExit(NewExit); + for (typename RegionT::const_iterator RI = R->begin(), RE = R->end(); + RI != RE; ++RI) { + if ((*RI)->getExit() == OldExit) + RegionQueue.push_back(RI->get()); + } + } +} + +template +bool RegionBase::contains(const BlockT *B) const { + BlockT *BB = const_cast(B); + + if (!DT->getNode(BB)) + return false; + + BlockT *entry = getEntry(), *exit = getExit(); + + // Toplevel region. + if (!exit) + return true; + + return (DT->dominates(entry, BB) && + !(DT->dominates(exit, BB) && DT->dominates(entry, exit))); +} + +template +bool RegionBase::contains(const LoopT *L) const { + // BBs that are not part of any loop are element of the Loop + // described by the NULL pointer. This loop is not part of any region, + // except if the region describes the whole function. + if (!L) + return getExit() == nullptr; + + if (!contains(L->getHeader())) + return false; + + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + + for (BlockT *BB : ExitingBlocks) { + if (!contains(BB)) + return false; + } + + return true; +} + +template +typename Tr::LoopT *RegionBase::outermostLoopInRegion(LoopT *L) const { + if (!contains(L)) + return nullptr; + + while (L && contains(L->getParentLoop())) { + L = L->getParentLoop(); + } + + return L; +} + +template +typename Tr::LoopT *RegionBase::outermostLoopInRegion(LoopInfoT *LI, + BlockT *BB) const { + assert(LI && BB && "LI and BB cannot be null!"); + LoopT *L = LI->getLoopFor(BB); + return outermostLoopInRegion(L); +} + +template +typename RegionBase::BlockT *RegionBase::getEnteringBlock() const { + BlockT *entry = getEntry(); + BlockT *Pred; + BlockT *enteringBlock = nullptr; + + for (PredIterTy PI = InvBlockTraits::child_begin(entry), + PE = InvBlockTraits::child_end(entry); + PI != PE; ++PI) { + Pred = *PI; + if (DT->getNode(Pred) && !contains(Pred)) { + if (enteringBlock) + return nullptr; + + enteringBlock = Pred; + } + } + + return enteringBlock; +} + +template +typename RegionBase::BlockT *RegionBase::getExitingBlock() const { + BlockT *exit = getExit(); + BlockT *Pred; + BlockT *exitingBlock = nullptr; + + if (!exit) + return nullptr; + + for (PredIterTy PI = InvBlockTraits::child_begin(exit), + PE = InvBlockTraits::child_end(exit); + PI != PE; ++PI) { + Pred = *PI; + if (contains(Pred)) { + if (exitingBlock) + return nullptr; + + exitingBlock = Pred; + } + } + + return exitingBlock; +} + +template +bool RegionBase::isSimple() const { + return !isTopLevelRegion() && getEnteringBlock() && getExitingBlock(); +} + +template +std::string RegionBase::getNameStr() const { + std::string exitName; + std::string entryName; + + if (getEntry()->getName().empty()) { + raw_string_ostream OS(entryName); + + getEntry()->printAsOperand(OS, false); + } else + entryName = getEntry()->getName(); + + if (getExit()) { + if (getExit()->getName().empty()) { + raw_string_ostream OS(exitName); + + getExit()->printAsOperand(OS, false); + } else + exitName = getExit()->getName(); + } else + exitName = ""; + + return entryName + " => " + exitName; +} + +template +void RegionBase::verifyBBInRegion(BlockT *BB) const { + if (!contains(BB)) + llvm_unreachable("Broken region found!"); + + BlockT *entry = getEntry(), *exit = getExit(); + + for (SuccIterTy SI = BlockTraits::child_begin(BB), + SE = BlockTraits::child_end(BB); + SI != SE; ++SI) { + if (!contains(*SI) && exit != *SI) + llvm_unreachable("Broken region found!"); + } + + if (entry != BB) { + for (PredIterTy SI = InvBlockTraits::child_begin(BB), + SE = InvBlockTraits::child_end(BB); + SI != SE; ++SI) { + if (!contains(*SI)) + llvm_unreachable("Broken region found!"); + } + } +} + +template +void RegionBase::verifyWalk(BlockT *BB, std::set *visited) const { + BlockT *exit = getExit(); + + visited->insert(BB); + + verifyBBInRegion(BB); + + for (SuccIterTy SI = BlockTraits::child_begin(BB), + SE = BlockTraits::child_end(BB); + SI != SE; ++SI) { + if (*SI != exit && visited->find(*SI) == visited->end()) + verifyWalk(*SI, visited); + } +} + +template +void RegionBase::verifyRegion() const { + // Only do verification when user wants to, otherwise this expensive check + // will be invoked by PMDataManager::verifyPreservedAnalysis when + // a regionpass (marked PreservedAll) finish. + if (!RegionInfoBase::VerifyRegionInfo) + return; + + std::set visited; + verifyWalk(getEntry(), &visited); +} + +template +void RegionBase::verifyRegionNest() const { + for (typename RegionT::const_iterator RI = begin(), RE = end(); RI != RE; + ++RI) + (*RI)->verifyRegionNest(); + + verifyRegion(); +} + +template +typename RegionBase::element_iterator RegionBase::element_begin() { + return GraphTraits::nodes_begin(static_cast(this)); +} + +template +typename RegionBase::element_iterator RegionBase::element_end() { + return GraphTraits::nodes_end(static_cast(this)); +} + +template +typename RegionBase::const_element_iterator +RegionBase::element_begin() const { + return GraphTraits::nodes_begin( + static_cast(this)); +} + +template +typename RegionBase::const_element_iterator +RegionBase::element_end() const { + return GraphTraits::nodes_end( + static_cast(this)); +} + +template +typename Tr::RegionT *RegionBase::getSubRegionNode(BlockT *BB) const { + typedef typename Tr::RegionT RegionT; + RegionT *R = RI->getRegionFor(BB); + + if (!R || R == this) + return nullptr; + + // If we pass the BB out of this region, that means our code is broken. + assert(contains(R) && "BB not in current region!"); + + while (contains(R->getParent()) && R->getParent() != this) + R = R->getParent(); + + if (R->getEntry() != BB) + return nullptr; + + return R; +} + +template +typename Tr::RegionNodeT *RegionBase::getBBNode(BlockT *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + + typename BBNodeMapT::const_iterator at = BBNodeMap.find(BB); + + if (at != BBNodeMap.end()) + return at->second; + + auto Deconst = const_cast *>(this); + RegionNodeT *NewNode = new RegionNodeT(static_cast(Deconst), BB); + BBNodeMap.insert(std::make_pair(BB, NewNode)); + return NewNode; +} + +template +typename Tr::RegionNodeT *RegionBase::getNode(BlockT *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + if (RegionT *Child = getSubRegionNode(BB)) + return Child->getNode(); + + return getBBNode(BB); +} + +template +void RegionBase::transferChildrenTo(RegionT *To) { + for (iterator I = begin(), E = end(); I != E; ++I) { + (*I)->parent = To; + To->children.push_back(std::move(*I)); + } + children.clear(); +} + +template +void RegionBase::addSubRegion(RegionT *SubRegion, bool moveChildren) { + assert(!SubRegion->parent && "SubRegion already has a parent!"); + assert(std::find_if(begin(), end(), [&](const std::unique_ptr &R) { + return R.get() == SubRegion; + }) == children.end() && + "Subregion already exists!"); + + SubRegion->parent = static_cast(this); + children.push_back(std::unique_ptr(SubRegion)); + + if (!moveChildren) + return; + + assert(SubRegion->children.empty() && + "SubRegions that contain children are not supported"); + + for (element_iterator I = element_begin(), E = element_end(); I != E; ++I) { + if (!(*I)->isSubRegion()) { + BlockT *BB = (*I)->template getNodeAs(); + + if (SubRegion->contains(BB)) + RI->setRegionFor(BB, SubRegion); + } + } + + std::vector> Keep; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (SubRegion->contains(I->get()) && I->get() != SubRegion) { + (*I)->parent = SubRegion; + SubRegion->children.push_back(std::move(*I)); + } else + Keep.push_back(std::move(*I)); + } + + children.clear(); + children.insert( + children.begin(), + std::move_iterator(Keep.begin()), + std::move_iterator(Keep.end())); +} + +template +typename Tr::RegionT *RegionBase::removeSubRegion(RegionT *Child) { + assert(Child->parent == this && "Child is not a child of this region!"); + Child->parent = nullptr; + typename RegionSet::iterator I = std::find_if( + children.begin(), children.end(), + [&](const std::unique_ptr &R) { return R.get() == Child; }); + assert(I != children.end() && "Region does not exit. Unable to remove."); + children.erase(children.begin() + (I - begin())); + return Child; +} + +template +unsigned RegionBase::getDepth() const { + unsigned Depth = 0; + + for (RegionT *R = getParent(); R != nullptr; R = R->getParent()) + ++Depth; + + return Depth; +} + +template +typename Tr::RegionT *RegionBase::getExpandedRegion() const { + unsigned NumSuccessors = Tr::getNumSuccessors(exit); + + if (NumSuccessors == 0) + return nullptr; + + for (PredIterTy PI = InvBlockTraits::child_begin(getExit()), + PE = InvBlockTraits::child_end(getExit()); + PI != PE; ++PI) { + if (!DT->dominates(getEntry(), *PI)) + return nullptr; + } + + RegionT *R = RI->getRegionFor(exit); + + if (R->getEntry() != exit) { + if (Tr::getNumSuccessors(exit) == 1) + return new RegionT(getEntry(), *BlockTraits::child_begin(exit), RI, DT); + return nullptr; + } + + while (R->getParent() && R->getParent()->getEntry() == exit) + R = R->getParent(); + + if (!DT->dominates(getEntry(), R->getExit())) { + for (PredIterTy PI = InvBlockTraits::child_begin(getExit()), + PE = InvBlockTraits::child_end(getExit()); + PI != PE; ++PI) { + if (!DT->dominates(R->getExit(), *PI)) + return nullptr; + } + } + + return new RegionT(getEntry(), R->getExit(), RI, DT); +} + +template +void RegionBase::print(raw_ostream &OS, bool print_tree, unsigned level, + PrintStyle Style) const { + if (print_tree) + OS.indent(level * 2) << '[' << level << "] " << getNameStr(); + else + OS.indent(level * 2) << getNameStr(); + + OS << '\n'; + + if (Style != PrintNone) { + OS.indent(level * 2) << "{\n"; + OS.indent(level * 2 + 2); + + if (Style == PrintBB) { + for (const auto &BB : blocks()) + OS << BB->getName() << ", "; // TODO: remove the last "," + } else if (Style == PrintRN) { + for (const_element_iterator I = element_begin(), E = element_end(); + I != E; ++I) { + OS << **I << ", "; // TODO: remove the last ", + } + } + + OS << '\n'; + } + + if (print_tree) { + for (const_iterator RI = begin(), RE = end(); RI != RE; ++RI) + (*RI)->print(OS, print_tree, level + 1, Style); + } + + if (Style != PrintNone) + OS.indent(level * 2) << "} \n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template +void RegionBase::dump() const { + print(dbgs(), true, getDepth(), RegionInfoBase::printStyle); +} +#endif + +template +void RegionBase::clearNodeCache() { + // Free the cached nodes. + for (typename BBNodeMapT::iterator I = BBNodeMap.begin(), + IE = BBNodeMap.end(); + I != IE; ++I) + delete I->second; + + BBNodeMap.clear(); + for (typename RegionT::iterator RI = begin(), RE = end(); RI != RE; ++RI) + (*RI)->clearNodeCache(); +} + +//===----------------------------------------------------------------------===// +// RegionInfoBase implementation +// + +template +RegionInfoBase::RegionInfoBase() + : TopLevelRegion(nullptr) {} + +template +RegionInfoBase::~RegionInfoBase() { + releaseMemory(); +} + +template +bool RegionInfoBase::isCommonDomFrontier(BlockT *BB, BlockT *entry, + BlockT *exit) const { + for (PredIterTy PI = InvBlockTraits::child_begin(BB), + PE = InvBlockTraits::child_end(BB); + PI != PE; ++PI) { + BlockT *P = *PI; + if (DT->dominates(entry, P) && !DT->dominates(exit, P)) + return false; + } + + return true; +} + +template +bool RegionInfoBase::isRegion(BlockT *entry, BlockT *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + typedef typename DomFrontierT::DomSetType DST; + + DST *entrySuccs = &DF->find(entry)->second; + + // Exit is the header of a loop that contains the entry. In this case, + // the dominance frontier must only contain the exit. + if (!DT->dominates(entry, exit)) { + for (typename DST::iterator SI = entrySuccs->begin(), + SE = entrySuccs->end(); + SI != SE; ++SI) { + if (*SI != exit && *SI != entry) + return false; + } + + return true; + } + + DST *exitSuccs = &DF->find(exit)->second; + + // Do not allow edges leaving the region. + for (typename DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end(); + SI != SE; ++SI) { + if (*SI == exit || *SI == entry) + continue; + if (exitSuccs->find(*SI) == exitSuccs->end()) + return false; + if (!isCommonDomFrontier(*SI, entry, exit)) + return false; + } + + // Do not allow edges pointing into the region. + for (typename DST::iterator SI = exitSuccs->begin(), SE = exitSuccs->end(); + SI != SE; ++SI) { + if (DT->properlyDominates(entry, *SI) && *SI != exit) + return false; + } + + return true; +} + +template +void RegionInfoBase::insertShortCut(BlockT *entry, BlockT *exit, + BBtoBBMap *ShortCut) const { + assert(entry && exit && "entry and exit must not be null!"); + + typename BBtoBBMap::iterator e = ShortCut->find(exit); + + if (e == ShortCut->end()) + // No further region at exit available. + (*ShortCut)[entry] = exit; + else { + // We found a region e that starts at exit. Therefore (entry, e->second) + // is also a region, that is larger than (entry, exit). Insert the + // larger one. + BlockT *BB = e->second; + (*ShortCut)[entry] = BB; + } +} + +template +typename Tr::DomTreeNodeT * +RegionInfoBase::getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const { + typename BBtoBBMap::iterator e = ShortCut->find(N->getBlock()); + + if (e == ShortCut->end()) + return N->getIDom(); + + return PDT->getNode(e->second)->getIDom(); +} + +template +bool RegionInfoBase::isTrivialRegion(BlockT *entry, BlockT *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + + unsigned num_successors = + BlockTraits::child_end(entry) - BlockTraits::child_begin(entry); + + if (num_successors <= 1 && exit == *(BlockTraits::child_begin(entry))) + return true; + + return false; +} + +template +typename Tr::RegionT *RegionInfoBase::createRegion(BlockT *entry, + BlockT *exit) { + assert(entry && exit && "entry and exit must not be null!"); + + if (isTrivialRegion(entry, exit)) + return nullptr; + + RegionT *region = + new RegionT(entry, exit, static_cast(this), DT); + BBtoRegion.insert(std::make_pair(entry, region)); + +#ifdef XDEBUG + region->verifyRegion(); +#else + DEBUG(region->verifyRegion()); +#endif + + updateStatistics(region); + return region; +} + +template +void RegionInfoBase::findRegionsWithEntry(BlockT *entry, + BBtoBBMap *ShortCut) { + assert(entry); + + DomTreeNodeT *N = PDT->getNode(entry); + if (!N) + return; + + RegionT *lastRegion = nullptr; + BlockT *lastExit = entry; + + // As only a BasicBlock that postdominates entry can finish a region, walk the + // post dominance tree upwards. + while ((N = getNextPostDom(N, ShortCut))) { + BlockT *exit = N->getBlock(); + + if (!exit) + break; + + if (isRegion(entry, exit)) { + RegionT *newRegion = createRegion(entry, exit); + + if (lastRegion) + newRegion->addSubRegion(lastRegion); + + lastRegion = newRegion; + lastExit = exit; + } + + // This can never be a region, so stop the search. + if (!DT->dominates(entry, exit)) + break; + } + + // Tried to create regions from entry to lastExit. Next time take a + // shortcut from entry to lastExit. + if (lastExit != entry) + insertShortCut(entry, lastExit, ShortCut); +} + +template +void RegionInfoBase::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) { + typedef typename std::add_pointer::type FuncPtrT; + BlockT *entry = GraphTraits::getEntryNode(&F); + DomTreeNodeT *N = DT->getNode(entry); + + // Iterate over the dominance tree in post order to start with the small + // regions from the bottom of the dominance tree. If the small regions are + // detected first, detection of bigger regions is faster, as we can jump + // over the small regions. + for (po_iterator FI = po_begin(N), FE = po_end(N); FI != FE; + ++FI) { + findRegionsWithEntry(FI->getBlock(), ShortCut); + } +} + +template +typename Tr::RegionT *RegionInfoBase::getTopMostParent(RegionT *region) { + while (region->getParent()) + region = region->getParent(); + + return region; +} + +template +void RegionInfoBase::buildRegionsTree(DomTreeNodeT *N, RegionT *region) { + BlockT *BB = N->getBlock(); + + // Passed region exit + while (BB == region->getExit()) + region = region->getParent(); + + typename BBtoRegionMap::iterator it = BBtoRegion.find(BB); + + // This basic block is a start block of a region. It is already in the + // BBtoRegion relation. Only the child basic blocks have to be updated. + if (it != BBtoRegion.end()) { + RegionT *newRegion = it->second; + region->addSubRegion(getTopMostParent(newRegion)); + region = newRegion; + } else { + BBtoRegion[BB] = region; + } + + for (typename DomTreeNodeT::iterator CI = N->begin(), CE = N->end(); CI != CE; + ++CI) { + buildRegionsTree(*CI, region); + } +} + +#ifdef XDEBUG +template +bool RegionInfoBase::VerifyRegionInfo = true; +#else +template +bool RegionInfoBase::VerifyRegionInfo = false; +#endif + +template +typename Tr::RegionT::PrintStyle RegionInfoBase::printStyle = + RegionBase::PrintNone; + +template +void RegionInfoBase::print(raw_ostream &OS) const { + OS << "Region tree:\n"; + TopLevelRegion->print(OS, true, 0, printStyle); + OS << "End region tree\n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template +void RegionInfoBase::dump() const { print(dbgs()); } +#endif + +template +void RegionInfoBase::releaseMemory() { + BBtoRegion.clear(); + if (TopLevelRegion) + delete TopLevelRegion; + TopLevelRegion = nullptr; +} + +template +void RegionInfoBase::verifyAnalysis() const { + TopLevelRegion->verifyRegionNest(); +} + +// Region pass manager support. +template +typename Tr::RegionT *RegionInfoBase::getRegionFor(BlockT *BB) const { + typename BBtoRegionMap::const_iterator I = BBtoRegion.find(BB); + return I != BBtoRegion.end() ? I->second : nullptr; +} + +template +void RegionInfoBase::setRegionFor(BlockT *BB, RegionT *R) { + BBtoRegion[BB] = R; +} + +template +typename Tr::RegionT *RegionInfoBase::operator[](BlockT *BB) const { + return getRegionFor(BB); +} + +template +typename RegionInfoBase::BlockT * +RegionInfoBase::getMaxRegionExit(BlockT *BB) const { + BlockT *Exit = nullptr; + + while (true) { + // Get largest region that starts at BB. + RegionT *R = getRegionFor(BB); + while (R && R->getParent() && R->getParent()->getEntry() == BB) + R = R->getParent(); + + // Get the single exit of BB. + if (R && R->getEntry() == BB) + Exit = R->getExit(); + else if (++BlockTraits::child_begin(BB) == BlockTraits::child_end(BB)) + Exit = *BlockTraits::child_begin(BB); + else // No single exit exists. + return Exit; + + // Get largest region that starts at Exit. + RegionT *ExitR = getRegionFor(Exit); + while (ExitR && ExitR->getParent() && + ExitR->getParent()->getEntry() == Exit) + ExitR = ExitR->getParent(); + + for (PredIterTy PI = InvBlockTraits::child_begin(Exit), + PE = InvBlockTraits::child_end(Exit); + PI != PE; ++PI) { + if (!R->contains(*PI) && !ExitR->contains(*PI)) + break; + } + + // This stops infinite cycles. + if (DT->dominates(Exit, BB)) + break; + + BB = Exit; + } + + return Exit; +} + +template +typename Tr::RegionT *RegionInfoBase::getCommonRegion(RegionT *A, + RegionT *B) const { + assert(A && B && "One of the Regions is NULL"); + + if (A->contains(B)) + return A; + + while (!B->contains(A)) + B = B->getParent(); + + return B; +} + +template +typename Tr::RegionT * +RegionInfoBase::getCommonRegion(SmallVectorImpl &Regions) const { + RegionT *ret = Regions.back(); + Regions.pop_back(); + + for (RegionT *R : Regions) + ret = getCommonRegion(ret, R); + + return ret; +} + +template +typename Tr::RegionT * +RegionInfoBase::getCommonRegion(SmallVectorImpl &BBs) const { + RegionT *ret = getRegionFor(BBs.back()); + BBs.pop_back(); + + for (BlockT *BB : BBs) + ret = getCommonRegion(ret, getRegionFor(BB)); + + return ret; +} + +template +void RegionInfoBase::splitBlock(BlockT *NewBB, BlockT *OldBB) { + RegionT *R = getRegionFor(OldBB); + + setRegionFor(NewBB, R); + + while (R->getEntry() == OldBB && !R->isTopLevelRegion()) { + R->replaceEntry(NewBB); + R = R->getParent(); + } + + setRegionFor(OldBB, R); +} + +template +void RegionInfoBase::calculate(FuncT &F) { + typedef typename std::add_pointer::type FuncPtrT; + + // ShortCut a function where for every BB the exit of the largest region + // starting with BB is stored. These regions can be threated as single BBS. + // This improves performance on linear CFGs. + BBtoBBMap ShortCut; + + scanForRegions(F, &ShortCut); + BlockT *BB = GraphTraits::getEntryNode(&F); + buildRegionsTree(DT->getNode(BB), TopLevelRegion); +} + +#endif diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index ab4d0e0fcc0..0daff58475d 100644 --- a/include/llvm/Analysis/RegionIterator.h +++ b/include/llvm/Analysis/RegionIterator.h @@ -30,13 +30,16 @@ namespace llvm { /// /// For a subregion RegionNode there is just one successor. The RegionNode /// representing the exit of the subregion. -template +template class RNSuccIterator : public std::iterator -{ + NodeType, ptrdiff_t> { typedef std::iterator super; + + typedef GraphTraits BlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + // The iterator works in two modes, bb mode or region mode. - enum ItMode{ + enum ItMode { // In BB mode it returns all successors of this BasicBlock as its // successors. ItBB, @@ -47,10 +50,10 @@ class RNSuccIterator : public std::iterator Node; + PointerIntPair Node; // The block successor iterator. - succ_iterator BItor; + SuccIterTy BItor; // advanceRegionSucc - A region node has only one successor. It reaches end // once we advance it. @@ -66,37 +69,36 @@ class RNSuccIterator : public std::iteratorgetParent()->getNode(BB); assert(succ && "BB not in Region or entered subregion!"); return succ; } // getRegionSucc - Return the successor basic block of a SubRegion RegionNode. - inline BasicBlock* getRegionSucc() const { + inline BlockT* getRegionSucc() const { assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!"); - return getNode()->template getNodeAs()->getExit(); + return getNode()->template getNodeAs()->getExit(); } // isExit - Is this the exit BB of the Region? - inline bool isExit(BasicBlock* BB) const { + inline bool isExit(BlockT* BB) const { return getNode()->getParent()->getExit() == BB; } public: - typedef RNSuccIterator Self; + typedef RNSuccIterator Self; typedef typename super::pointer pointer; /// @brief Create begin iterator of a RegionNode. inline RNSuccIterator(NodeType* node) : Node(node, node->isSubRegion() ? ItRgBegin : ItBB), - BItor(succ_begin(node->getEntry())) { - + BItor(BlockTraits::child_begin(node->getEntry())) { // Skip the exit block if (!isRegionMode()) - while (succ_end(node->getEntry()) != BItor && isExit(*BItor)) + while (BlockTraits::child_end(node->getEntry()) != BItor && isExit(*BItor)) ++BItor; if (isRegionMode() && isExit(getRegionSucc())) @@ -106,7 +108,7 @@ public: /// @brief Create an end iterator. inline RNSuccIterator(NodeType* node, bool) : Node(node, node->isSubRegion() ? ItRgEnd : ItBB), - BItor(succ_end(node->getEntry())) {} + BItor(BlockTraits::child_end(node->getEntry())) {} inline bool operator==(const Self& x) const { assert(isRegionMode() == x.isRegionMode() && "Broken iterator!"); @@ -119,7 +121,7 @@ public: inline bool operator!=(const Self& x) const { return !operator==(x); } inline pointer operator*() const { - BasicBlock* BB = isRegionMode() ? getRegionSucc() : *BItor; + BlockT *BB = isRegionMode() ? getRegionSucc() : *BItor; assert(!isExit(BB) && "Iterator out of range!"); return getISucc(BB); } @@ -132,7 +134,7 @@ public: // Skip the exit. do ++BItor; - while (BItor != succ_end(getNode()->getEntry()) + while (BItor != BlockTraits::child_end(getNode()->getEntry()) && isExit(*BItor)); } return *this; @@ -162,36 +164,41 @@ public: /// The Flat Region iterator will iterate over all BasicBlock RegionNodes that /// are contained in the Region and its subregions. This is close to a virtual /// control flow graph of the Region. -template -class RNSuccIterator > - : public std::iterator -{ +template +class RNSuccIterator, BlockT, RegionT> + : public std::iterator { typedef std::iterator super; + typedef GraphTraits BlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + NodeType* Node; - succ_iterator Itor; + SuccIterTy Itor; public: - typedef RNSuccIterator > Self; + typedef RNSuccIterator, BlockT, RegionT> Self; typedef typename super::pointer pointer; /// @brief Create the iterator from a RegionNode. /// /// Note that the incoming node must be a bb node, otherwise it will trigger /// an assertion when we try to get a BasicBlock. - inline RNSuccIterator(NodeType* node) : Node(node), - Itor(succ_begin(node->getEntry())) { + inline RNSuccIterator(NodeType* node) : + Node(node), + Itor(BlockTraits::child_begin(node->getEntry())) { assert(!Node->isSubRegion() && "Subregion node not allowed in flat iterating mode!"); assert(Node->getParent() && "A BB node must have a parent!"); // Skip the exit block of the iterating region. - while (succ_end(Node->getEntry()) != Itor + while (BlockTraits::child_end(Node->getEntry()) != Itor && Node->getParent()->getExit() == *Itor) ++Itor; } + /// @brief Create an end iterator - inline RNSuccIterator(NodeType* node, bool) : Node(node), - Itor(succ_end(node->getEntry())) { + inline RNSuccIterator(NodeType* node, bool) : + Node(node), + Itor(BlockTraits::child_end(node->getEntry())) { assert(!Node->isSubRegion() && "Subregion node not allowed in flat iterating mode!"); } @@ -206,10 +213,10 @@ public: inline bool operator!=(const Self& x) const { return !operator==(x); } inline pointer operator*() const { - BasicBlock* BB = *Itor; + BlockT *BB = *Itor; // Get the iterating region. - Region* Parent = Node->getParent(); + RegionT *Parent = Node->getParent(); // The only case that the successor reaches out of the region is it reaches // the exit of the region. @@ -245,14 +252,14 @@ public: } }; -template -inline RNSuccIterator succ_begin(NodeType* Node) { - return RNSuccIterator(Node); +template +inline RNSuccIterator succ_begin(NodeType* Node) { + return RNSuccIterator(Node); } -template -inline RNSuccIterator succ_end(NodeType* Node) { - return RNSuccIterator(Node, true); +template +inline RNSuccIterator succ_end(NodeType* Node) { + return RNSuccIterator(Node, true); } //===--------------------------------------------------------------------===// @@ -262,27 +269,27 @@ inline RNSuccIterator succ_end(NodeType* Node) { // NodeT can either be region node or const region node, otherwise child_begin // and child_end fail. -#define RegionNodeGraphTraits(NodeT) \ - template<> struct GraphTraits { \ +#define RegionNodeGraphTraits(NodeT, BlockT, RegionT) \ + template<> struct GraphTraits { \ typedef NodeT NodeType; \ - typedef RNSuccIterator ChildIteratorType; \ + typedef RNSuccIterator ChildIteratorType; \ static NodeType *getEntryNode(NodeType* N) { return N; } \ static inline ChildIteratorType child_begin(NodeType *N) { \ - return RNSuccIterator(N); \ + return RNSuccIterator(N); \ } \ static inline ChildIteratorType child_end(NodeType *N) { \ - return RNSuccIterator(N, true); \ + return RNSuccIterator(N, true); \ } \ }; \ -template<> struct GraphTraits > { \ +template<> struct GraphTraits> { \ typedef NodeT NodeType; \ - typedef RNSuccIterator > ChildIteratorType; \ + typedef RNSuccIterator, BlockT, RegionT > ChildIteratorType; \ static NodeType *getEntryNode(NodeType* N) { return N; } \ static inline ChildIteratorType child_begin(NodeType *N) { \ - return RNSuccIterator >(N); \ + return RNSuccIterator, BlockT, RegionT>(N); \ } \ static inline ChildIteratorType child_end(NodeType *N) { \ - return RNSuccIterator >(N, true); \ + return RNSuccIterator, BlockT, RegionT>(N, true); \ } \ } @@ -315,8 +322,8 @@ template<> struct GraphTraits > \ } \ } -RegionNodeGraphTraits(RegionNode); -RegionNodeGraphTraits(const RegionNode); +RegionNodeGraphTraits(RegionNode, BasicBlock, Region); +RegionNodeGraphTraits(const RegionNode, BasicBlock, Region); RegionGraphTraits(Region, RegionNode); RegionGraphTraits(const Region, const RegionNode); @@ -337,6 +344,22 @@ template <> struct GraphTraits } }; +template <> struct GraphTraits + : public GraphTraits { + typedef df_iterator, false, + GraphTraits > > nodes_iterator; + + static NodeType *getEntryNode(RegionInfoPass *RI) { + return GraphTraits::getEntryNode(&RI->getRegionInfo()); + } + static nodes_iterator nodes_begin(RegionInfoPass* RI) { + return GraphTraits::nodes_begin(&RI->getRegionInfo()); + } + static nodes_iterator nodes_end(RegionInfoPass *RI) { + return GraphTraits::nodes_end(&RI->getRegionInfo()); + } +}; + } // End namespace llvm #endif diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h new file mode 100644 index 00000000000..43499dba71c --- /dev/null +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -0,0 +1,183 @@ +//===- llvm/CodeGen/MachineRegionInfo.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEREGIONINFO_H +#define LLVM_CODEGEN_MACHINEREGIONINFO_H + +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/Analysis/RegionIterator.h" +#include "llvm/CodeGen/MachineDominanceFrontier.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" + + +namespace llvm { + +class MachineDominatorTree; +struct MachinePostDominatorTree; +class MachineRegion; +class MachineRegionNode; +class MachineRegionInfo; + +template<> +struct RegionTraits { + typedef MachineFunction FuncT; + typedef MachineBasicBlock BlockT; + typedef MachineRegion RegionT; + typedef MachineRegionNode RegionNodeT; + typedef MachineRegionInfo RegionInfoT; + typedef MachineDominatorTree DomTreeT; + typedef MachineDomTreeNode DomTreeNodeT; + typedef MachinePostDominatorTree PostDomTreeT; + typedef MachineDominanceFrontier DomFrontierT; + typedef MachineInstr InstT; + typedef MachineLoop LoopT; + typedef MachineLoopInfo LoopInfoT; + + static unsigned getNumSuccessors(MachineBasicBlock *BB) { + return BB->succ_size(); + } +}; + + +class MachineRegionNode : public RegionNodeBase> { +public: + inline MachineRegionNode(MachineRegion *Parent, + MachineBasicBlock *Entry, + bool isSubRegion = false) + : RegionNodeBase>(Parent, Entry, isSubRegion) { + + } + + ~MachineRegionNode() { } + + bool operator==(const MachineRegion &RN) const { + return this == reinterpret_cast(&RN); + } +}; + +class MachineRegion : public RegionBase> { +public: + MachineRegion(MachineBasicBlock *Entry, MachineBasicBlock *Exit, + MachineRegionInfo* RI, + MachineDominatorTree *DT, MachineRegion *Parent = nullptr); + ~MachineRegion(); + + bool operator==(const MachineRegionNode &RN) const { + return &RN == reinterpret_cast(this); + } +}; + +class MachineRegionInfo : public RegionInfoBase> { +public: + explicit MachineRegionInfo(); + + virtual ~MachineRegionInfo(); + + // updateStatistics - Update statistic about created regions. + void updateStatistics(MachineRegion *R) final; + + void recalculate(MachineFunction &F, + MachineDominatorTree *DT, + MachinePostDominatorTree *PDT, + MachineDominanceFrontier *DF); +}; + +class MachineRegionInfoPass : public MachineFunctionPass { + MachineRegionInfo RI; + +public: + static char ID; + explicit MachineRegionInfoPass(); + + ~MachineRegionInfoPass(); + + MachineRegionInfo &getRegionInfo() { + return RI; + } + + const MachineRegionInfo &getRegionInfo() const { + return RI; + } + + /// @name MachineFunctionPass interface + //@{ + bool runOnMachineFunction(MachineFunction &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 MachineBasicBlock* RegionNodeBase>::getNodeAs() const { + assert(!isSubRegion() && "This is not a MachineBasicBlock RegionNode!"); + return getEntry(); +} + +template<> +template<> +inline MachineRegion* RegionNodeBase>::getNodeAs() const { + assert(isSubRegion() && "This is not a subregion RegionNode!"); + auto Unconst = const_cast>*>(this); + return reinterpret_cast(Unconst); +} + + +RegionNodeGraphTraits(MachineRegionNode, MachineBasicBlock, MachineRegion); +RegionNodeGraphTraits(const MachineRegionNode, MachineBasicBlock, MachineRegion); + +RegionGraphTraits(MachineRegion, MachineRegionNode); +RegionGraphTraits(const MachineRegion, const MachineRegionNode); + +template <> struct GraphTraits + : public GraphTraits > { + typedef df_iterator, false, + GraphTraits > > nodes_iterator; + + static NodeType *getEntryNode(MachineRegionInfo *RI) { + return GraphTraits >::getEntryNode(RI->getTopLevelRegion()); + } + static nodes_iterator nodes_begin(MachineRegionInfo* RI) { + return nodes_iterator::begin(getEntryNode(RI)); + } + static nodes_iterator nodes_end(MachineRegionInfo *RI) { + return nodes_iterator::end(getEntryNode(RI)); + } +}; + +template <> struct GraphTraits + : public GraphTraits { + typedef df_iterator, false, + GraphTraits > > nodes_iterator; + + static NodeType *getEntryNode(MachineRegionInfoPass *RI) { + return GraphTraits::getEntryNode(&RI->getRegionInfo()); + } + static nodes_iterator nodes_begin(MachineRegionInfoPass* RI) { + return GraphTraits::nodes_begin(&RI->getRegionInfo()); + } + static nodes_iterator nodes_end(MachineRegionInfoPass *RI) { + return GraphTraits::nodes_end(&RI->getRegionInfo()); + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class RegionBase>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase>); + +} + +#endif diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 7b97f2c21bf..02f4259a51a 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -189,6 +189,7 @@ void initializeMachinePostDominatorTreePass(PassRegistry&); void initializeMachineLICMPass(PassRegistry&); void initializeMachineLoopInfoPass(PassRegistry&); void initializeMachineModuleInfoPass(PassRegistry&); +void initializeMachineRegionInfoPassPass(PassRegistry&); void initializeMachineSchedulerPass(PassRegistry&); void initializeMachineSinkingPass(PassRegistry&); void initializeMachineTraceMetricsPass(PassRegistry&); @@ -227,7 +228,7 @@ void initializePromotePassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); void initializeReassociatePass(PassRegistry&); void initializeRegToMemPass(PassRegistry&); -void initializeRegionInfoPass(PassRegistry&); +void initializeRegionInfoPassPass(PassRegistry&); void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp index ade940a7d30..c58012f3a8c 100644 --- a/lib/Analysis/Analysis.cpp +++ b/lib/Analysis/Analysis.cpp @@ -57,7 +57,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeMemoryDependenceAnalysisPass(Registry); initializeModuleDebugInfoPrinterPass(Registry); initializePostDominatorTreePass(Registry); - initializeRegionInfoPass(Registry); + initializeRegionInfoPassPass(Registry); initializeRegionViewerPass(Registry); initializeRegionPrinterPass(Registry); initializeRegionOnlyViewerPass(Registry); diff --git a/lib/Analysis/RegionInfo.cpp b/lib/Analysis/RegionInfo.cpp index 7f88ae12501..46aa1bcf045 100644 --- a/lib/Analysis/RegionInfo.cpp +++ b/lib/Analysis/RegionInfo.cpp @@ -10,6 +10,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/RegionInfo.h" +#include "llvm/Analysis/RegionInfoImpl.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/LoopInfo.h" @@ -25,21 +26,26 @@ using namespace llvm; #define DEBUG_TYPE "region" -// Always verify if expensive checking is enabled. -#ifdef XDEBUG -static bool VerifyRegionInfo = true; -#else -static bool VerifyRegionInfo = false; -#endif - -static cl::opt -VerifyRegionInfoX("verify-region-info", cl::location(VerifyRegionInfo), - cl::desc("Verify region info (time consuming)")); +namespace llvm { +template class RegionBase>; +template class RegionNodeBase>; +template class RegionInfoBase>; +} STATISTIC(numRegions, "The # of regions"); STATISTIC(numSimpleRegions, "The # of simple regions"); -static cl::opt printStyle("print-region-style", +// Always verify if expensive checking is enabled. + +static cl::opt +VerifyRegionInfoX( + "verify-region-info", + cl::location(RegionInfoBase>::VerifyRegionInfo), + cl::desc("Verify region info (time consuming)")); + + +static cl::opt printStyleX("print-region-style", + cl::location(RegionInfo::printStyle), cl::Hidden, cl::desc("style of printing regions"), cl::values( @@ -49,812 +55,110 @@ static cl::opt printStyle("print-region-style", clEnumValN(Region::PrintRN, "rn", "print regions in detail with element_iterator"), clEnumValEnd)); + + //===----------------------------------------------------------------------===// -/// Region Implementation -Region::Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo* RInfo, - DominatorTree *dt, Region *Parent) - : RegionNode(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {} +// Region implementation +// -Region::~Region() { - // Free the cached nodes. - for (BBNodeMapT::iterator it = BBNodeMap.begin(), - ie = BBNodeMap.end(); it != ie; ++it) - delete it->second; +Region::Region(BasicBlock *Entry, BasicBlock *Exit, + RegionInfo* RI, + DominatorTree *DT, Region *Parent) : + RegionBase>(Entry, Exit, RI, DT, Parent) { - // Only clean the cache for this Region. Caches of child Regions will be - // cleaned when the child Regions are deleted. - BBNodeMap.clear(); } -void Region::replaceEntry(BasicBlock *BB) { - entry.setPointer(BB); -} - -void Region::replaceExit(BasicBlock *BB) { - assert(exit && "No exit to replace!"); - exit = BB; -} - -void Region::replaceEntryRecursive(BasicBlock *NewEntry) { - std::vector RegionQueue; - BasicBlock *OldEntry = getEntry(); - - RegionQueue.push_back(this); - while (!RegionQueue.empty()) { - Region *R = RegionQueue.back(); - RegionQueue.pop_back(); - - R->replaceEntry(NewEntry); - for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI) - if ((*RI)->getEntry() == OldEntry) - RegionQueue.push_back(RI->get()); - } -} - -void Region::replaceExitRecursive(BasicBlock *NewExit) { - std::vector RegionQueue; - BasicBlock *OldExit = getExit(); - - RegionQueue.push_back(this); - while (!RegionQueue.empty()) { - Region *R = RegionQueue.back(); - RegionQueue.pop_back(); - - R->replaceExit(NewExit); - for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI) - if ((*RI)->getExit() == OldExit) - RegionQueue.push_back(RI->get()); - } -} - -bool Region::contains(const BasicBlock *B) const { - BasicBlock *BB = const_cast(B); - - if (!DT->getNode(BB)) - return false; - - BasicBlock *entry = getEntry(), *exit = getExit(); - - // Toplevel region. - if (!exit) - return true; - - return (DT->dominates(entry, BB) - && !(DT->dominates(exit, BB) && DT->dominates(entry, exit))); -} - -bool Region::contains(const Loop *L) const { - // BBs that are not part of any loop are element of the Loop - // described by the NULL pointer. This loop is not part of any region, - // except if the region describes the whole function. - if (!L) - return getExit() == nullptr; - - if (!contains(L->getHeader())) - return false; - - SmallVector ExitingBlocks; - L->getExitingBlocks(ExitingBlocks); - - for (SmallVectorImpl::iterator BI = ExitingBlocks.begin(), - BE = ExitingBlocks.end(); BI != BE; ++BI) - if (!contains(*BI)) - return false; - - return true; -} - -Loop *Region::outermostLoopInRegion(Loop *L) const { - if (!contains(L)) - return nullptr; - - while (L && contains(L->getParentLoop())) { - L = L->getParentLoop(); - } - - return L; -} - -Loop *Region::outermostLoopInRegion(LoopInfo *LI, BasicBlock* BB) const { - assert(LI && BB && "LI and BB cannot be null!"); - Loop *L = LI->getLoopFor(BB); - return outermostLoopInRegion(L); -} - -BasicBlock *Region::getEnteringBlock() const { - BasicBlock *entry = getEntry(); - BasicBlock *Pred; - BasicBlock *enteringBlock = nullptr; - - for (pred_iterator PI = pred_begin(entry), PE = pred_end(entry); PI != PE; - ++PI) { - Pred = *PI; - if (DT->getNode(Pred) && !contains(Pred)) { - if (enteringBlock) - return nullptr; - - enteringBlock = Pred; - } - } - - return enteringBlock; -} - -BasicBlock *Region::getExitingBlock() const { - BasicBlock *exit = getExit(); - BasicBlock *Pred; - BasicBlock *exitingBlock = nullptr; - - if (!exit) - return nullptr; - - for (pred_iterator PI = pred_begin(exit), PE = pred_end(exit); PI != PE; - ++PI) { - Pred = *PI; - if (contains(Pred)) { - if (exitingBlock) - return nullptr; - - exitingBlock = Pred; - } - } - - return exitingBlock; -} - -bool Region::isSimple() const { - return !isTopLevelRegion() && getEnteringBlock() && getExitingBlock(); -} - -std::string Region::getNameStr() const { - std::string exitName; - std::string entryName; - - if (getEntry()->getName().empty()) { - raw_string_ostream OS(entryName); - - getEntry()->printAsOperand(OS, false); - } else - entryName = getEntry()->getName(); - - if (getExit()) { - if (getExit()->getName().empty()) { - raw_string_ostream OS(exitName); - - getExit()->printAsOperand(OS, false); - } else - exitName = getExit()->getName(); - } else - exitName = ""; - - return entryName + " => " + exitName; -} - -void Region::verifyBBInRegion(BasicBlock *BB) const { - if (!contains(BB)) - llvm_unreachable("Broken region found!"); - - BasicBlock *entry = getEntry(), *exit = getExit(); - - for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) - if (!contains(*SI) && exit != *SI) - llvm_unreachable("Broken region found!"); - - if (entry != BB) - for (pred_iterator SI = pred_begin(BB), SE = pred_end(BB); SI != SE; ++SI) - if (!contains(*SI)) - llvm_unreachable("Broken region found!"); -} - -void Region::verifyWalk(BasicBlock *BB, std::set *visited) const { - BasicBlock *exit = getExit(); - - visited->insert(BB); - - verifyBBInRegion(BB); - - for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) - if (*SI != exit && visited->find(*SI) == visited->end()) - verifyWalk(*SI, visited); -} - -void Region::verifyRegion() const { - // Only do verification when user wants to, otherwise this expensive - // check will be invoked by PassManager. - if (!VerifyRegionInfo) return; - - std::set visited; - verifyWalk(getEntry(), &visited); -} - -void Region::verifyRegionNest() const { - for (Region::const_iterator RI = begin(), RE = end(); RI != RE; ++RI) - (*RI)->verifyRegionNest(); - - verifyRegion(); -} - -Region::element_iterator Region::element_begin() { - return GraphTraits::nodes_begin(this); -} - -Region::element_iterator Region::element_end() { - return GraphTraits::nodes_end(this); -} - -Region::const_element_iterator Region::element_begin() const { - return GraphTraits::nodes_begin(this); -} - -Region::const_element_iterator Region::element_end() const { - return GraphTraits::nodes_end(this); -} - -Region* Region::getSubRegionNode(BasicBlock *BB) const { - Region *R = RI->getRegionFor(BB); - - if (!R || R == this) - return nullptr; - - // If we pass the BB out of this region, that means our code is broken. - assert(contains(R) && "BB not in current region!"); - - while (contains(R->getParent()) && R->getParent() != this) - R = R->getParent(); - - if (R->getEntry() != BB) - return nullptr; - - return R; -} - -RegionNode* Region::getBBNode(BasicBlock *BB) const { - assert(contains(BB) && "Can get BB node out of this region!"); - - BBNodeMapT::const_iterator at = BBNodeMap.find(BB); - - if (at != BBNodeMap.end()) - return at->second; - - RegionNode *NewNode = new RegionNode(const_cast(this), BB); - BBNodeMap.insert(std::make_pair(BB, NewNode)); - return NewNode; -} - -RegionNode* Region::getNode(BasicBlock *BB) const { - assert(contains(BB) && "Can get BB node out of this region!"); - if (Region* Child = getSubRegionNode(BB)) - return Child->getNode(); - - return getBBNode(BB); -} - -void Region::transferChildrenTo(Region *To) { - for (iterator I = begin(), E = end(); I != E; ++I) { - (*I)->parent = To; - To->children.push_back(std::move(*I)); - } - children.clear(); -} - -void Region::addSubRegion(Region *SubRegion, bool moveChildren) { - assert(!SubRegion->parent && "SubRegion already has a parent!"); - assert(std::find_if(begin(), end(), [&](const std::unique_ptr &R) { - return R.get() == SubRegion; - }) == children.end() && - "Subregion already exists!"); - - SubRegion->parent = this; - children.push_back(std::unique_ptr(SubRegion)); - - if (!moveChildren) - return; - - assert(SubRegion->children.size() == 0 - && "SubRegions that contain children are not supported"); - - for (element_iterator I = element_begin(), E = element_end(); I != E; ++I) - if (!(*I)->isSubRegion()) { - BasicBlock *BB = (*I)->getNodeAs(); - - if (SubRegion->contains(BB)) - RI->setRegionFor(BB, SubRegion); - } - - std::vector> Keep; - for (iterator I = begin(), E = end(); I != E; ++I) - if (SubRegion->contains(I->get()) && I->get() != SubRegion) { - (*I)->parent = SubRegion; - SubRegion->children.push_back(std::move(*I)); - } else - Keep.push_back(std::move(*I)); - - children.clear(); - children.insert(children.begin(), - std::move_iterator(Keep.begin()), - std::move_iterator(Keep.end())); -} - - -Region *Region::removeSubRegion(Region *Child) { - assert(Child->parent == this && "Child is not a child of this region!"); - Child->parent = nullptr; - RegionSet::iterator I = std::find_if( - children.begin(), children.end(), - [&](const std::unique_ptr &R) { return R.get() == Child; }); - assert(I != children.end() && "Region does not exit. Unable to remove."); - children.erase(children.begin()+(I-begin())); - return Child; -} - -unsigned Region::getDepth() const { - unsigned Depth = 0; - - for (Region *R = parent; R != nullptr; R = R->parent) - ++Depth; - - return Depth; -} - -Region *Region::getExpandedRegion() const { - unsigned NumSuccessors = exit->getTerminator()->getNumSuccessors(); - - if (NumSuccessors == 0) - return nullptr; - - for (pred_iterator PI = pred_begin(getExit()), PE = pred_end(getExit()); - PI != PE; ++PI) - if (!DT->dominates(getEntry(), *PI)) - return nullptr; - - Region *R = RI->getRegionFor(exit); - - if (R->getEntry() != exit) { - if (exit->getTerminator()->getNumSuccessors() == 1) - return new Region(getEntry(), *succ_begin(exit), RI, DT); - else - return nullptr; - } - - while (R->getParent() && R->getParent()->getEntry() == exit) - R = R->getParent(); - - if (!DT->dominates(getEntry(), R->getExit())) - for (pred_iterator PI = pred_begin(getExit()), PE = pred_end(getExit()); - PI != PE; ++PI) - if (!DT->dominates(R->getExit(), *PI)) - return nullptr; - - return new Region(getEntry(), R->getExit(), RI, DT); -} - -void Region::print(raw_ostream &OS, bool print_tree, unsigned level, - enum PrintStyle Style) const { - if (print_tree) - OS.indent(level*2) << "[" << level << "] " << getNameStr(); - else - OS.indent(level*2) << getNameStr(); - - OS << "\n"; - - - if (Style != PrintNone) { - OS.indent(level*2) << "{\n"; - OS.indent(level*2 + 2); - - if (Style == PrintBB) { - for (const auto &BB : blocks()) - OS << BB->getName() << ", "; // TODO: remove the last "," - } else if (Style == PrintRN) { - for (const_element_iterator I = element_begin(), E = element_end(); I!=E; ++I) - OS << **I << ", "; // TODO: remove the last ", - } - - OS << "\n"; - } - - if (print_tree) - for (const_iterator RI = begin(), RE = end(); RI != RE; ++RI) - (*RI)->print(OS, print_tree, level+1, Style); - - if (Style != PrintNone) - OS.indent(level*2) << "} \n"; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void Region::dump() const { - print(dbgs(), true, getDepth(), printStyle.getValue()); -} -#endif - -void Region::clearNodeCache() { - // Free the cached nodes. - for (BBNodeMapT::iterator I = BBNodeMap.begin(), - IE = BBNodeMap.end(); I != IE; ++I) - delete I->second; - - BBNodeMap.clear(); - for (Region::iterator RI = begin(), RE = end(); RI != RE; ++RI) - (*RI)->clearNodeCache(); -} +Region::~Region() { } //===----------------------------------------------------------------------===// // RegionInfo implementation // -bool RegionInfo::isCommonDomFrontier(BasicBlock *BB, BasicBlock *entry, - BasicBlock *exit) const { - for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) { - BasicBlock *P = *PI; - if (DT->dominates(entry, P) && !DT->dominates(exit, P)) - return false; - } - return true; +RegionInfo::RegionInfo() : + RegionInfoBase>() { + } -bool RegionInfo::isRegion(BasicBlock *entry, BasicBlock *exit) const { - assert(entry && exit && "entry and exit must not be null!"); - typedef DominanceFrontier::DomSetType DST; +RegionInfo::~RegionInfo() { - DST *entrySuccs = &DF->find(entry)->second; - - // Exit is the header of a loop that contains the entry. In this case, - // the dominance frontier must only contain the exit. - if (!DT->dominates(entry, exit)) { - for (DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end(); - SI != SE; ++SI) - if (*SI != exit && *SI != entry) - return false; - - return true; - } - - DST *exitSuccs = &DF->find(exit)->second; - - // Do not allow edges leaving the region. - for (DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end(); - SI != SE; ++SI) { - if (*SI == exit || *SI == entry) - continue; - if (exitSuccs->find(*SI) == exitSuccs->end()) - return false; - if (!isCommonDomFrontier(*SI, entry, exit)) - return false; - } - - // Do not allow edges pointing into the region. - for (DST::iterator SI = exitSuccs->begin(), SE = exitSuccs->end(); - SI != SE; ++SI) - if (DT->properlyDominates(entry, *SI) && *SI != exit) - return false; - - - return true; -} - -void RegionInfo::insertShortCut(BasicBlock *entry, BasicBlock *exit, - BBtoBBMap *ShortCut) const { - assert(entry && exit && "entry and exit must not be null!"); - - BBtoBBMap::iterator e = ShortCut->find(exit); - - if (e == ShortCut->end()) - // No further region at exit available. - (*ShortCut)[entry] = exit; - else { - // We found a region e that starts at exit. Therefore (entry, e->second) - // is also a region, that is larger than (entry, exit). Insert the - // larger one. - BasicBlock *BB = e->second; - (*ShortCut)[entry] = BB; - } -} - -DomTreeNode* RegionInfo::getNextPostDom(DomTreeNode* N, - BBtoBBMap *ShortCut) const { - BBtoBBMap::iterator e = ShortCut->find(N->getBlock()); - - if (e == ShortCut->end()) - return N->getIDom(); - - return PDT->getNode(e->second)->getIDom(); -} - -bool RegionInfo::isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const { - assert(entry && exit && "entry and exit must not be null!"); - - unsigned num_successors = succ_end(entry) - succ_begin(entry); - - if (num_successors <= 1 && exit == *(succ_begin(entry))) - return true; - - return false; } void RegionInfo::updateStatistics(Region *R) { ++numRegions; // TODO: Slow. Should only be enabled if -stats is used. - if (R->isSimple()) ++numSimpleRegions; + if (R->isSimple()) + ++numSimpleRegions; } -Region *RegionInfo::createRegion(BasicBlock *entry, BasicBlock *exit) { - assert(entry && exit && "entry and exit must not be null!"); +void RegionInfo::RegionInfo::recalculate(Function &F, + DominatorTree *DT_, + PostDominatorTree *PDT_, + DominanceFrontier *DF_) { + DT = DT_; + PDT = PDT_; + DF = DF_; - if (isTrivialRegion(entry, exit)) - return nullptr; - - Region *region = new Region(entry, exit, this, DT); - BBtoRegion.insert(std::make_pair(entry, region)); - - #ifdef XDEBUG - region->verifyRegion(); - #else - DEBUG(region->verifyRegion()); - #endif - - updateStatistics(region); - return region; -} - -void RegionInfo::findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut) { - assert(entry); - - DomTreeNode *N = PDT->getNode(entry); - - if (!N) - return; - - Region *lastRegion= nullptr; - BasicBlock *lastExit = entry; - - // As only a BasicBlock that postdominates entry can finish a region, walk the - // post dominance tree upwards. - while ((N = getNextPostDom(N, ShortCut))) { - BasicBlock *exit = N->getBlock(); - - if (!exit) - break; - - if (isRegion(entry, exit)) { - Region *newRegion = createRegion(entry, exit); - - if (lastRegion) - newRegion->addSubRegion(lastRegion); - - lastRegion = newRegion; - lastExit = exit; - } - - // This can never be a region, so stop the search. - if (!DT->dominates(entry, exit)) - break; - } - - // Tried to create regions from entry to lastExit. Next time take a - // shortcut from entry to lastExit. - if (lastExit != entry) - insertShortCut(entry, lastExit, ShortCut); -} - -void RegionInfo::scanForRegions(Function &F, BBtoBBMap *ShortCut) { - BasicBlock *entry = &(F.getEntryBlock()); - DomTreeNode *N = DT->getNode(entry); - - // Iterate over the dominance tree in post order to start with the small - // regions from the bottom of the dominance tree. If the small regions are - // detected first, detection of bigger regions is faster, as we can jump - // over the small regions. - for (po_iterator FI = po_begin(N), FE = po_end(N); FI != FE; - ++FI) { - findRegionsWithEntry(FI->getBlock(), ShortCut); - } -} - -Region *RegionInfo::getTopMostParent(Region *region) { - while (region->parent) - region = region->getParent(); - - return region; -} - -void RegionInfo::buildRegionsTree(DomTreeNode *N, Region *region) { - BasicBlock *BB = N->getBlock(); - - // Passed region exit - while (BB == region->getExit()) - region = region->getParent(); - - BBtoRegionMap::iterator it = BBtoRegion.find(BB); - - // This basic block is a start block of a region. It is already in the - // BBtoRegion relation. Only the child basic blocks have to be updated. - if (it != BBtoRegion.end()) { - Region *newRegion = it->second; - region->addSubRegion(getTopMostParent(newRegion)); - region = newRegion; - } else { - BBtoRegion[BB] = region; - } - - for (DomTreeNode::iterator CI = N->begin(), CE = N->end(); CI != CE; ++CI) - buildRegionsTree(*CI, region); -} - -void RegionInfo::releaseMemory() { - BBtoRegion.clear(); - if (TopLevelRegion) - delete TopLevelRegion; - TopLevelRegion = nullptr; -} - -RegionInfo::RegionInfo() : FunctionPass(ID) { - initializeRegionInfoPass(*PassRegistry::getPassRegistry()); - TopLevelRegion = nullptr; -} - -RegionInfo::~RegionInfo() { - releaseMemory(); -} - -void RegionInfo::Calculate(Function &F) { - // ShortCut a function where for every BB the exit of the largest region - // starting with BB is stored. These regions can be threated as single BBS. - // This improves performance on linear CFGs. - BBtoBBMap ShortCut; - - scanForRegions(F, &ShortCut); - BasicBlock *BB = &F.getEntryBlock(); - buildRegionsTree(DT->getNode(BB), TopLevelRegion); -} - -bool RegionInfo::runOnFunction(Function &F) { - releaseMemory(); - - DT = &getAnalysis().getDomTree(); - PDT = &getAnalysis(); - DF = &getAnalysis(); - - TopLevelRegion = new Region(&F.getEntryBlock(), nullptr, this, DT, nullptr); + TopLevelRegion = new Region(&F.getEntryBlock(), nullptr, + this, DT, nullptr); updateStatistics(TopLevelRegion); + calculate(F); +} - Calculate(F); +//===----------------------------------------------------------------------===// +// RegionInfoPass implementation +// +RegionInfoPass::RegionInfoPass() : FunctionPass(ID) { + initializeRegionInfoPassPass(*PassRegistry::getPassRegistry()); +} + +RegionInfoPass::~RegionInfoPass() { + +} + +bool RegionInfoPass::runOnFunction(Function &F) { + releaseMemory(); + + auto DT = &getAnalysis().getDomTree(); + auto PDT = &getAnalysis(); + auto DF = &getAnalysis(); + + RI.recalculate(F, DT, PDT, DF); return false; } -void RegionInfo::getAnalysisUsage(AnalysisUsage &AU) const { +void RegionInfoPass::releaseMemory() { + RI.releaseMemory(); +} + +void RegionInfoPass::verifyAnalysis() const { + RI.verifyAnalysis(); +} + +void RegionInfoPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequiredTransitive(); AU.addRequired(); AU.addRequired(); } -void RegionInfo::print(raw_ostream &OS, const Module *) const { - OS << "Region tree:\n"; - TopLevelRegion->print(OS, true, 0, printStyle.getValue()); - OS << "End region tree\n"; +void RegionInfoPass::print(raw_ostream &OS, const Module *) const { + RI.print(OS); } -void RegionInfo::verifyAnalysis() const { - // Only do verification when user wants to, otherwise this expensive check - // will be invoked by PMDataManager::verifyPreservedAnalysis when - // a regionpass (marked PreservedAll) finish. - if (!VerifyRegionInfo) return; - - TopLevelRegion->verifyRegionNest(); +void RegionInfoPass::dump() const { + RI.dump(); } -// Region pass manager support. -Region *RegionInfo::getRegionFor(BasicBlock *BB) const { - BBtoRegionMap::const_iterator I= - BBtoRegion.find(BB); - return I != BBtoRegion.end() ? I->second : nullptr; -} +char RegionInfoPass::ID = 0; -void RegionInfo::setRegionFor(BasicBlock *BB, Region *R) { - BBtoRegion[BB] = R; -} - -Region *RegionInfo::operator[](BasicBlock *BB) const { - return getRegionFor(BB); -} - -BasicBlock *RegionInfo::getMaxRegionExit(BasicBlock *BB) const { - BasicBlock *Exit = nullptr; - - while (true) { - // Get largest region that starts at BB. - Region *R = getRegionFor(BB); - while (R && R->getParent() && R->getParent()->getEntry() == BB) - R = R->getParent(); - - // Get the single exit of BB. - if (R && R->getEntry() == BB) - Exit = R->getExit(); - else if (++succ_begin(BB) == succ_end(BB)) - Exit = *succ_begin(BB); - else // No single exit exists. - return Exit; - - // Get largest region that starts at Exit. - Region *ExitR = getRegionFor(Exit); - while (ExitR && ExitR->getParent() - && ExitR->getParent()->getEntry() == Exit) - ExitR = ExitR->getParent(); - - for (pred_iterator PI = pred_begin(Exit), PE = pred_end(Exit); PI != PE; - ++PI) - if (!R->contains(*PI) && !ExitR->contains(*PI)) - break; - - // This stops infinite cycles. - if (DT->dominates(Exit, BB)) - break; - - BB = Exit; - } - - return Exit; -} - -Region* -RegionInfo::getCommonRegion(Region *A, Region *B) const { - assert (A && B && "One of the Regions is NULL"); - - if (A->contains(B)) return A; - - while (!B->contains(A)) - B = B->getParent(); - - return B; -} - -Region* -RegionInfo::getCommonRegion(SmallVectorImpl &Regions) const { - Region* ret = Regions.back(); - Regions.pop_back(); - - for (SmallVectorImpl::const_iterator I = Regions.begin(), - E = Regions.end(); I != E; ++I) - ret = getCommonRegion(ret, *I); - - return ret; -} - -Region* -RegionInfo::getCommonRegion(SmallVectorImpl &BBs) const { - Region* ret = getRegionFor(BBs.back()); - BBs.pop_back(); - - for (SmallVectorImpl::const_iterator I = BBs.begin(), - E = BBs.end(); I != E; ++I) - ret = getCommonRegion(ret, getRegionFor(*I)); - - return ret; -} - -void RegionInfo::splitBlock(BasicBlock* NewBB, BasicBlock *OldBB) -{ - Region *R = getRegionFor(OldBB); - - setRegionFor(NewBB, R); - - while (R->getEntry() == OldBB && !R->isTopLevelRegion()) { - R->replaceEntry(NewBB); - R = R->getParent(); - } - - setRegionFor(OldBB, R); -} - -char RegionInfo::ID = 0; -INITIALIZE_PASS_BEGIN(RegionInfo, "regions", +INITIALIZE_PASS_BEGIN(RegionInfoPass, "regions", "Detect single entry single exit regions", true, true) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) INITIALIZE_PASS_DEPENDENCY(DominanceFrontier) -INITIALIZE_PASS_END(RegionInfo, "regions", +INITIALIZE_PASS_END(RegionInfoPass, "regions", "Detect single entry single exit regions", true, true) // Create methods available outside of this file, to use them @@ -863,7 +167,7 @@ INITIALIZE_PASS_END(RegionInfo, "regions", namespace llvm { FunctionPass *createRegionInfoPass() { - return new RegionInfo(); + return new RegionInfoPass(); } } diff --git a/lib/Analysis/RegionPass.cpp b/lib/Analysis/RegionPass.cpp index 71de14450b7..de34b727a5a 100644 --- a/lib/Analysis/RegionPass.cpp +++ b/lib/Analysis/RegionPass.cpp @@ -45,14 +45,14 @@ static void addRegionIntoQueue(Region &R, std::deque &RQ) { /// Pass Manager itself does not invalidate any analysis info. void RGPassManager::getAnalysisUsage(AnalysisUsage &Info) const { - Info.addRequired(); + Info.addRequired(); Info.setPreservesAll(); } /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the function, and if so, return true. bool RGPassManager::runOnFunction(Function &F) { - RI = &getAnalysis(); + RI = &getAnalysis().getRegionInfo(); bool Changed = false; // Collect inherited analysis from Module level pass manager. diff --git a/lib/Analysis/RegionPrinter.cpp b/lib/Analysis/RegionPrinter.cpp index 893210a5d70..ad83113ec93 100644 --- a/lib/Analysis/RegionPrinter.cpp +++ b/lib/Analysis/RegionPrinter.cpp @@ -56,23 +56,24 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { }; template<> -struct DOTGraphTraits : public DOTGraphTraits { +struct DOTGraphTraits : public DOTGraphTraits { - DOTGraphTraits (bool isSimple=false) + DOTGraphTraits (bool isSimple = false) : DOTGraphTraits(isSimple) {} - static std::string getGraphName(RegionInfo *DT) { + static std::string getGraphName(RegionInfoPass *DT) { return "Region Graph"; } - std::string getNodeLabel(RegionNode *Node, RegionInfo *G) { + std::string getNodeLabel(RegionNode *Node, RegionInfoPass *G) { + RegionInfo &RI = G->getRegionInfo(); return DOTGraphTraits::getNodeLabel(Node, - G->getTopLevelRegion()); + reinterpret_cast(RI.getTopLevelRegion())); } std::string getEdgeAttributes(RegionNode *srcNode, - GraphTraits::ChildIteratorType CI, RegionInfo *RI) { - + GraphTraits::ChildIteratorType CI, RegionInfoPass *G) { + RegionInfo &RI = G->getRegionInfo(); RegionNode *destNode = *CI; if (srcNode->isSubRegion() || destNode->isSubRegion()) @@ -82,7 +83,7 @@ struct DOTGraphTraits : public DOTGraphTraits { BasicBlock *srcBB = srcNode->getNodeAs(); BasicBlock *destBB = destNode->getNodeAs(); - Region *R = RI->getRegionFor(destBB); + Region *R = RI.getRegionFor(destBB); while (R && R->getParent()) if (R->getParent()->getEntry() == destBB) @@ -98,7 +99,8 @@ struct DOTGraphTraits : public DOTGraphTraits { // Print the cluster of the subregions. This groups the single basic blocks // and adds a different background color for each group. - static void printRegionCluster(const Region &R, GraphWriter &GW, + static void printRegionCluster(const Region &R, + GraphWriter &GW, unsigned depth = 0) { raw_ostream &O = GW.getOStream(); O.indent(2 * depth) << "subgraph cluster_" << static_cast(&R) @@ -119,22 +121,23 @@ struct DOTGraphTraits : public DOTGraphTraits { for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI) printRegionCluster(**RI, GW, depth + 1); - RegionInfo *RI = R.getRegionInfo(); + const RegionInfo &RI = *static_cast(R.getRegionInfo()); for (const auto &BB : R.blocks()) - if (RI->getRegionFor(BB) == &R) + if (RI.getRegionFor(BB) == &R) O.indent(2 * (depth + 1)) << "Node" - << static_cast(RI->getTopLevelRegion()->getBBNode(BB)) + << static_cast(RI.getTopLevelRegion()->getBBNode(BB)) << ";\n"; O.indent(2 * depth) << "}\n"; } - static void addCustomGraphFeatures(const RegionInfo* RI, - GraphWriter &GW) { + static void addCustomGraphFeatures(const RegionInfoPass* RIP, + GraphWriter &GW) { + const RegionInfo &RI = RIP->getRegionInfo(); raw_ostream &O = GW.getOStream(); O << "\tcolorscheme = \"paired12\"\n"; - printRegionCluster(*RI->getTopLevelRegion(), GW, 4); + printRegionCluster(*RI.getTopLevelRegion(), GW, 4); } }; } //end namespace llvm @@ -142,28 +145,28 @@ struct DOTGraphTraits : public DOTGraphTraits { namespace { struct RegionViewer - : public DOTGraphTraitsViewer { + : public DOTGraphTraitsViewer { static char ID; - RegionViewer() : DOTGraphTraitsViewer("reg", ID){ + RegionViewer() : DOTGraphTraitsViewer("reg", ID){ initializeRegionViewerPass(*PassRegistry::getPassRegistry()); } }; char RegionViewer::ID = 0; struct RegionOnlyViewer - : public DOTGraphTraitsViewer { + : public DOTGraphTraitsViewer { static char ID; - RegionOnlyViewer() : DOTGraphTraitsViewer("regonly", ID) { + RegionOnlyViewer() : DOTGraphTraitsViewer("regonly", ID) { initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry()); } }; char RegionOnlyViewer::ID = 0; struct RegionPrinter - : public DOTGraphTraitsPrinter { + : public DOTGraphTraitsPrinter { static char ID; RegionPrinter() : - DOTGraphTraitsPrinter("reg", ID) { + DOTGraphTraitsPrinter("reg", ID) { initializeRegionPrinterPass(*PassRegistry::getPassRegistry()); } }; @@ -175,7 +178,7 @@ INITIALIZE_PASS(RegionPrinter, "dot-regions", INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function", true, true) - + INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", "View regions of function (with no function bodies)", true, true) @@ -183,10 +186,10 @@ INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", namespace { struct RegionOnlyPrinter - : public DOTGraphTraitsPrinter { + : public DOTGraphTraitsPrinter { static char ID; RegionOnlyPrinter() : - DOTGraphTraitsPrinter("reg", ID) { + DOTGraphTraitsPrinter("reg", ID) { initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry()); } }; diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 77f16663f07..b71b30cc1cc 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -65,6 +65,7 @@ add_llvm_library(LLVMCodeGen MachinePassRegistry.cpp MachinePostDominators.cpp MachineRegisterInfo.cpp + MachineRegionInfo.cpp MachineSSAUpdater.cpp MachineScheduler.cpp MachineSink.cpp diff --git a/lib/CodeGen/MachineRegionInfo.cpp b/lib/CodeGen/MachineRegionInfo.cpp new file mode 100644 index 00000000000..c54a794d75c --- /dev/null +++ b/lib/CodeGen/MachineRegionInfo.cpp @@ -0,0 +1,137 @@ + +#include "llvm/CodeGen/MachineRegionInfo.h" +#include "llvm/CodeGen/MachinePostDominators.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/RegionInfoImpl.h" + +using namespace llvm; + +STATISTIC(numMachineRegions, "The # of machine regions"); +STATISTIC(numMachineSimpleRegions, "The # of simple machine regions"); + +namespace llvm { +template class RegionBase>; +template class RegionNodeBase>; +template class RegionInfoBase>; +} + +//===----------------------------------------------------------------------===// +// MachineRegion implementation +// + +MachineRegion::MachineRegion(MachineBasicBlock *Entry, MachineBasicBlock *Exit, + MachineRegionInfo* RI, + MachineDominatorTree *DT, MachineRegion *Parent) : + RegionBase>(Entry, Exit, RI, DT, Parent) { + +} + +MachineRegion::~MachineRegion() { } + +//===----------------------------------------------------------------------===// +// MachineRegionInfo implementation +// + +MachineRegionInfo::MachineRegionInfo() : + RegionInfoBase>() { + +} + +MachineRegionInfo::~MachineRegionInfo() { + +} + +void MachineRegionInfo::updateStatistics(MachineRegion *R) { + ++numMachineRegions; + + // TODO: Slow. Should only be enabled if -stats is used. + if (R->isSimple()) + ++numMachineSimpleRegions; +} + +void MachineRegionInfo::MachineRegionInfo::recalculate( + MachineFunction &F, + MachineDominatorTree *DT_, + MachinePostDominatorTree *PDT_, + MachineDominanceFrontier *DF_) { + DT = DT_; + PDT = PDT_; + DF = DF_; + + MachineBasicBlock *Entry = GraphTraits::getEntryNode(&F); + + TopLevelRegion = new MachineRegion(Entry, nullptr, this, DT, nullptr); + updateStatistics(TopLevelRegion); + calculate(F); +} + +//===----------------------------------------------------------------------===// +// MachineRegionInfoPass implementation +// + +MachineRegionInfoPass::MachineRegionInfoPass() : MachineFunctionPass(ID) { + initializeMachineRegionInfoPassPass(*PassRegistry::getPassRegistry()); +} + +MachineRegionInfoPass::~MachineRegionInfoPass() { + +} + +bool MachineRegionInfoPass::runOnMachineFunction(MachineFunction &F) { + releaseMemory(); + + auto DT = &getAnalysis(); + auto PDT = &getAnalysis(); + auto DF = &getAnalysis(); + + RI.recalculate(F, DT, PDT, DF); + return false; +} + +void MachineRegionInfoPass::releaseMemory() { + RI.releaseMemory(); +} + +void MachineRegionInfoPass::verifyAnalysis() const { + // Only do verification when user wants to, otherwise this expensive check + // will be invoked by PMDataManager::verifyPreservedAnalysis when + // a regionpass (marked PreservedAll) finish. + if (MachineRegionInfo::VerifyRegionInfo) + RI.verifyAnalysis(); +} + +void MachineRegionInfoPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequired(); + AU.addRequired(); +} + +void MachineRegionInfoPass::print(raw_ostream &OS, const Module *) const { + RI.print(OS); +} + +void MachineRegionInfoPass::dump() const { + RI.dump(); +} + +char MachineRegionInfoPass::ID = 0; + +INITIALIZE_PASS_BEGIN(MachineRegionInfoPass, "regions", + "Detect single entry single exit regions", true, true) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier) +INITIALIZE_PASS_END(MachineRegionInfoPass, "regions", + "Detect single entry single exit regions", true, true) + +// Create methods available outside of this file, to use them +// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by +// the link time optimization. + +namespace llvm { + FunctionPass *createMachineRegionInfoPass() { + return new MachineRegionInfoPass(); + } +} + diff --git a/lib/Transforms/Scalar/StructurizeCFG.cpp b/lib/Transforms/Scalar/StructurizeCFG.cpp index 7b77ae1de1b..b9673ed655e 100644 --- a/lib/Transforms/Scalar/StructurizeCFG.cpp +++ b/lib/Transforms/Scalar/StructurizeCFG.cpp @@ -260,7 +260,7 @@ INITIALIZE_PASS_BEGIN(StructurizeCFG, "structurizecfg", "Structurize the CFG", false, false) INITIALIZE_PASS_DEPENDENCY(LowerSwitch) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_DEPENDENCY(RegionInfo) +INITIALIZE_PASS_DEPENDENCY(RegionInfoPass) INITIALIZE_PASS_END(StructurizeCFG, "structurizecfg", "Structurize the CFG", false, false) @@ -406,11 +406,11 @@ void StructurizeCFG::gatherPredicates(RegionNode *N) { } else { // It's an exit from a sub region - while(R->getParent() != ParentRegion) + while (R->getParent() != ParentRegion) R = R->getParent(); // Edge from inside a subregion to its entry, ignore it - if (R == N) + if (*R == *N) continue; BasicBlock *Entry = R->getEntry();