diff options
author | Tobias Grosser <grosser@fim.uni-passau.de> | 2010-10-20 01:54:44 +0000 |
---|---|---|
committer | Tobias Grosser <grosser@fim.uni-passau.de> | 2010-10-20 01:54:44 +0000 |
commit | 65513605353c7e3ee8be6fc92892f257ad399d92 (patch) | |
tree | 5ed1eadcd13601b914a22908e03ef41152586b4f | |
parent | 3e26c3c7d4c652811ab1ec5bd0f2a749c372709b (diff) | |
download | external_llvm-65513605353c7e3ee8be6fc92892f257ad399d92.zip external_llvm-65513605353c7e3ee8be6fc92892f257ad399d92.tar.gz external_llvm-65513605353c7e3ee8be6fc92892f257ad399d92.tar.bz2 |
Add RegionPass support.
A RegionPass is executed like a LoopPass but on the regions detected by the
RegionInfo pass instead of the loops detected by the LoopInfo pass.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116905 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/WritingAnLLVMPass.html | 87 | ||||
-rw-r--r-- | include/llvm/Analysis/RegionPass.h | 126 | ||||
-rw-r--r-- | include/llvm/Pass.h | 4 | ||||
-rw-r--r-- | include/llvm/PassManagers.h | 1 | ||||
-rw-r--r-- | lib/Analysis/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Analysis/RegionPass.cpp | 276 | ||||
-rw-r--r-- | lib/VMCore/PassManager.cpp | 3 | ||||
-rw-r--r-- | tools/opt/opt.cpp | 38 |
8 files changed, 535 insertions, 1 deletions
diff --git a/docs/WritingAnLLVMPass.html b/docs/WritingAnLLVMPass.html index 3cef2c9..a1d5564 100644 --- a/docs/WritingAnLLVMPass.html +++ b/docs/WritingAnLLVMPass.html @@ -51,6 +51,14 @@ <li><a href="#doFinalization_loop">The <tt>doFinalization() </tt> method</a></li> </ul></li> + <li><a href="#RegionPass">The <tt>RegionPass</tt> class</a> + <ul> + <li><a href="#doInitialization_region">The <tt>doInitialization(Region *, + RGPassManager &)</tt> method</a></li> + <li><a href="#runOnRegion">The <tt>runOnRegion</tt> method</a></li> + <li><a href="#doFinalization_region">The <tt>doFinalization() + </tt> method</a></li> + </ul></li> <li><a href="#BasicBlockPass">The <tt>BasicBlockPass</tt> class</a> <ul> <li><a href="#doInitialization_fn">The <tt>doInitialization(Function @@ -134,6 +142,7 @@ the <tt><a href="#ModulePass">ModulePass</a></tt>, <tt><a href="#CallGraphSCCPass">CallGraphSCCPass</a></tt>, <tt><a href="#FunctionPass">FunctionPass</a></tt>, or <tt><a href="#LoopPass">LoopPass</a></tt>, or <tt><a +href="#RegionPass">RegionPass</a></tt>, or <tt><a href="#BasicBlockPass">BasicBlockPass</a></tt> classes, which gives the system more information about what your pass does, and how it can be combined with other passes. One of the main features of the LLVM Pass Framework is that it @@ -805,6 +814,84 @@ program being compiled. </p> </div> +<!-- ======================================================================= --> +<div class="doc_subsection"> + <a name="RegionPass">The <tt>RegionPass</tt> class </a> +</div> + +<div class="doc_text"> + +<p> <tt>RegionPass</tt> is similar to <a href="#LoopPass"><tt>LoopPass</tt></a>, +but executes on each single entry single exit region in the function. +<tt>RegionPass</tt> processes regions in nested order such that the outer most +region is processed last. </p> + +<p> <tt>RegionPass</tt> subclasses are allowed to update the region tree by using +the <tt>RGPassManager</tt> interface. You may overload three virtual methods of +<tt>RegionPass</tt> to implementing your own region pass is usually. All these +methods should return true if they modified the program, or false if they didn not. +</p> +</div> + +<!-- _______________________________________________________________________ --> +<div class="doc_subsubsection"> + <a name="doInitialization_region">The <tt>doInitialization(Region *, + RGPassManager &)</tt> + method</a> +</div> + +<div class="doc_text"> + +<div class="doc_code"><pre> + <b>virtual bool</b> doInitialization(Region *, RGPassManager &RGM); +</pre></div> + +<p>The <tt>doInitialization</tt> method is designed to do simple initialization +type of stuff that does not depend on the functions being processed. The +<tt>doInitialization</tt> method call is not scheduled to overlap with any +other pass executions (thus it should be very fast). RPPassManager +interface should be used to access Function or Module level analysis +information.</p> + +</div> + + +<!-- _______________________________________________________________________ --> +<div class="doc_subsubsection"> + <a name="runOnRegion">The <tt>runOnRegion</tt> method</a> +</div> + +<div class="doc_text"> + +<div class="doc_code"><pre> + <b>virtual bool</b> runOnRegion(Region *, RGPassManager &RGM) = 0; +</pre></div><p> + +<p>The <tt>runOnRegion</tt> method must be implemented by your subclass to do +the transformation or analysis work of your pass. As usual, a true value should +be returned if the region is modified. <tt>RGPassManager</tt> interface +should be used to update region tree.</p> + +</div> + +<!-- _______________________________________________________________________ --> +<div class="doc_subsubsection"> + <a name="doFinalization_region">The <tt>doFinalization()</tt> method</a> +</div> + +<div class="doc_text"> + +<div class="doc_code"><pre> + <b>virtual bool</b> doFinalization(); +</pre></div> + +<p>The <tt>doFinalization</tt> method is an infrequently used method that is +called when the pass framework has finished calling <a +href="#runOnRegion"><tt>runOnRegion</tt></a> for every region in the +program being compiled. </p> + +</div> + <!-- ======================================================================= --> diff --git a/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h new file mode 100644 index 0000000..aedc06a --- /dev/null +++ b/include/llvm/Analysis/RegionPass.h @@ -0,0 +1,126 @@ +//===- RegionPass.h - RegionPass class ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the RegionPass class. All region based analysis, +// optimization and transformation passes are derived from RegionPass. +// This class is implemented following the some ideas of the LoopPass.h class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REGION_PASS_H +#define LLVM_REGION_PASS_H + +#include "llvm/Analysis/RegionInfo.h" + +#include "llvm/Pass.h" +#include "llvm/PassManagers.h" +#include "llvm/Function.h" + +#include <deque> + +namespace llvm { + +class RGPassManager; +class Function; + +//===----------------------------------------------------------------------===// +/// @brief A pass that runs on each Region in a function. +/// +/// RegionPass is managed by RGPassManager. +class RegionPass : public Pass { +public: + explicit RegionPass(char &pid) : Pass(PT_Region, pid) {} + + //===--------------------------------------------------------------------===// + /// @name To be implemented by every RegionPass + /// + //@{ + /// @brief Run the pass on a specific Region + /// + /// Accessing regions not contained in the current region is not allowed. + /// + /// @param R The region this pass is run on. + /// @param RGM The RegionPassManager that manages this Pass. + /// + /// @return True if the pass modifies this Region. + virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0; + + /// @brief Get a pass to print the LLVM IR in the region. + /// + /// @param O The ouput stream to print the Region. + /// @param Banner The banner to seperate different printed passes. + /// + /// @return The pass to print the LLVM IR in the region. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + virtual bool doInitialization(Region *R, RGPassManager &RGM) { return false; } + virtual bool doFinalization() { return false; } + //@} + + //===--------------------------------------------------------------------===// + /// @name PassManager API + /// + //@{ + void preparePassManager(PMStack &PMS); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_RegionPassManager); + + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_RegionPassManager; + } + //@} +}; + +/// @brief The pass manager to schedule RegionPasses. +class RGPassManager : public FunctionPass, public PMDataManager { + std::deque<Region*> RQ; + bool skipThisRegion; + bool redoThisRegion; + RegionInfo *RI; + Region *CurrentRegion; + +public: + static char ID; + explicit RGPassManager(int Depth); + + /// @brief Execute all of the passes scheduled for execution. + /// + /// @return True if any of the passes modifies the function. + bool runOnFunction(Function &F); + + /// Pass Manager itself does not invalidate any analysis info. + /// RGPassManager needs RegionInfo. + void getAnalysisUsage(AnalysisUsage &Info) const; + + virtual const char *getPassName() const { + return "Region Pass Manager"; + } + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + + /// @brief Print passes managed by this manager. + void dumpPassStructure(unsigned Offset); + + /// @brief Print passes contained by this manager. + Pass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + Pass *FP = static_cast<Pass *>(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_RegionPassManager; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index f4c6eed..ed0fb39 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -57,6 +57,7 @@ enum PassManagerType { PMT_CallGraphPassManager, ///< CGPassManager PMT_FunctionPassManager, ///< FPPassManager PMT_LoopPassManager, ///< LPPassManager + PMT_RegionPassManager, ///< RGPassManager PMT_BasicBlockPassManager, ///< BBPassManager PMT_Last }; @@ -64,13 +65,14 @@ enum PassManagerType { // Different types of passes. enum PassKind { PT_BasicBlock, + PT_Region, PT_Loop, PT_Function, PT_CallGraphSCC, PT_Module, PT_PassManager }; - + //===----------------------------------------------------------------------===// /// Pass interface - Implemented by all 'passes'. Subclass this if you are an /// interprocedural optimization or you do not fit into any of the more diff --git a/include/llvm/PassManagers.h b/include/llvm/PassManagers.h index ce34f31..c4f409e 100644 --- a/include/llvm/PassManagers.h +++ b/include/llvm/PassManagers.h @@ -106,6 +106,7 @@ enum PassDebuggingString { ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n" ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" + ON_REGION_MSG, // " 'on Region ...\n'" ON_LOOP_MSG, // " 'on Loop ...\n'" ON_CG_MSG // "' on Call Graph ...\n'" }; diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 5294550..d69ab59 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -40,6 +40,7 @@ add_llvm_library(LLVMAnalysis ProfileInfoLoaderPass.cpp ProfileVerifierPass.cpp RegionInfo.cpp + RegionPass.cpp RegionPrinter.cpp ScalarEvolution.cpp ScalarEvolutionAliasAnalysis.cpp diff --git a/lib/Analysis/RegionPass.cpp b/lib/Analysis/RegionPass.cpp new file mode 100644 index 0000000..a4145e1 --- /dev/null +++ b/lib/Analysis/RegionPass.cpp @@ -0,0 +1,276 @@ +//===- RegionPass.cpp - Region Pass and Region Pass Manager ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements RegionPass and RGPassManager. All region optimization +// and transformation passes are derived from RegionPass. RGPassManager is +// responsible for managing RegionPasses. +// most of these codes are COPY from LoopPass.cpp +// +//===----------------------------------------------------------------------===// +#include "llvm/Analysis/RegionPass.h" +#include "llvm/Analysis/RegionIterator.h" +#include "llvm/Support/Timer.h" + +#define DEBUG_TYPE "regionpassmgr" +#include "llvm/Support/Debug.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// RGPassManager +// + +char RGPassManager::ID = 0; + +RGPassManager::RGPassManager(int Depth) + : FunctionPass(ID), PMDataManager(Depth) { + skipThisRegion = false; + redoThisRegion = false; + RI = NULL; + CurrentRegion = NULL; +} + +// Recurse through all subregions and all regions into RQ. +static void addRegionIntoQueue(Region *R, std::deque<Region *> &RQ) { + RQ.push_back(R); + for (Region::iterator I = R->begin(), E = R->end(); I != E; ++I) + addRegionIntoQueue(*I, RQ); +} + +/// Pass Manager itself does not invalidate any analysis info. +void RGPassManager::getAnalysisUsage(AnalysisUsage &Info) const { + Info.addRequired<RegionInfo>(); + 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<RegionInfo>(); + bool Changed = false; + + // Collect inherited analysis from Module level pass manager. + populateInheritedAnalysis(TPM->activeStack); + + addRegionIntoQueue(RI->getTopLevelRegion(), RQ); + + if (RQ.empty()) // No regions, skip calling finalizers + return false; + + // Initialization + for (std::deque<Region *>::const_iterator I = RQ.begin(), E = RQ.end(); + I != E; ++I) { + Region *R = *I; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + RegionPass *RP = (RegionPass *)getContainedPass(Index); + Changed |= RP->doInitialization(R, *this); + } + } + + // Walk Regions + while (!RQ.empty()) { + + CurrentRegion = RQ.back(); + skipThisRegion = false; + redoThisRegion = false; + + // Run all passes on the current Region. + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + RegionPass *P = (RegionPass*)getContainedPass(Index); + + dumpPassInfo(P, EXECUTION_MSG, ON_REGION_MSG, + CurrentRegion->getNameStr()); + dumpRequiredSet(P); + + initializeAnalysisImpl(P); + + { + PassManagerPrettyStackEntry X(P, *CurrentRegion->getEntry()); + + TimeRegion PassTimer(getPassTimer(P)); + Changed |= P->runOnRegion(CurrentRegion, *this); + } + + if (Changed) + dumpPassInfo(P, MODIFICATION_MSG, ON_REGION_MSG, + skipThisRegion ? "<deleted>" : + CurrentRegion->getNameStr()); + dumpPreservedSet(P); + + if (!skipThisRegion) { + // Manually check that this region is still healthy. This is done + // instead of relying on RegionInfo::verifyRegion since RegionInfo + // is a function pass and it's really expensive to verify every + // Region in the function every time. That level of checking can be + // enabled with the -verify-region-info option. + { + TimeRegion PassTimer(getPassTimer(P)); + CurrentRegion->verifyRegion(); + } + + // Then call the regular verifyAnalysis functions. + verifyPreservedAnalysis(P); + } + + removeNotPreservedAnalysis(P); + recordAvailableAnalysis(P); + removeDeadPasses(P, + skipThisRegion ? "<deleted>" : + CurrentRegion->getNameStr(), + ON_REGION_MSG); + + if (skipThisRegion) + // Do not run other passes on this region. + break; + } + + // If the region was deleted, release all the region passes. This frees up + // some memory, and avoids trouble with the pass manager trying to call + // verifyAnalysis on them. + if (skipThisRegion) + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + freePass(P, "<deleted>", ON_REGION_MSG); + } + + // Pop the region from queue after running all passes. + RQ.pop_back(); + + if (redoThisRegion) + RQ.push_back(CurrentRegion); + + // Free all region nodes created in region passes. + RI->clearNodeCache(); + } + + // Finalization + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + RegionPass *P = (RegionPass*)getContainedPass(Index); + Changed |= P->doFinalization(); + } + + // Print the region tree after all pass. + DEBUG( + dbgs() << "\nRegion tree of function " << F.getName() + << " after all region Pass:\n"; + RI->dump(); + dbgs() << "\n"; + ); + + return Changed; +} + +/// Print passes managed by this manager +void RGPassManager::dumpPassStructure(unsigned Offset) { + errs().indent(Offset*2) << "Region Pass Manager\n"; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + P->dumpPassStructure(Offset + 1); + dumpLastUses(P, Offset+1); + } +} + +namespace { +//===----------------------------------------------------------------------===// +// PrintRegionPass +class PrintRegionPass : public RegionPass { +private: + std::string Banner; + raw_ostream &Out; // raw_ostream to print on. + +public: + static char ID; + PrintRegionPass() : RegionPass(ID), Out(dbgs()) {} + PrintRegionPass(const std::string &B, raw_ostream &o) + : RegionPass(ID), Banner(B), Out(o) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + virtual bool runOnRegion(Region *R, RGPassManager &RGM) { + Out << Banner; + for (Region::block_iterator I = R->block_begin(), E = R->block_end(); + I != E; ++I) + (*I)->getEntry()->print(Out); + + return false; + } +}; + +char PrintRegionPass::ID = 0; +} //end anonymous namespace + +//===----------------------------------------------------------------------===// +// RegionPass + +// Check if this pass is suitable for the current RGPassManager, if +// available. This pass P is not suitable for a RGPassManager if P +// is not preserving higher level analysis info used by other +// RGPassManager passes. In such case, pop RGPassManager from the +// stack. This will force assignPassManager() to create new +// LPPassManger as expected. +void RegionPass::preparePassManager(PMStack &PMS) { + + // Find RGPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_RegionPassManager) + PMS.pop(); + + + // If this pass is destroying high level information that is used + // by other passes that are managed by LPM then do not insert + // this pass in current LPM. Use new RGPassManager. + if (PMS.top()->getPassManagerType() == PMT_RegionPassManager && + !PMS.top()->preserveHigherLevelAnalysis(this)) + PMS.pop(); +} + +/// Assign pass manager to manage this pass. +void RegionPass::assignPassManager(PMStack &PMS, + PassManagerType PreferredType) { + // Find RGPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_RegionPassManager) + PMS.pop(); + + RGPassManager *RGPM; + + // Create new Region Pass Manager if it does not exist. + if (PMS.top()->getPassManagerType() == PMT_RegionPassManager) + RGPM = (RGPassManager*)PMS.top(); + else { + + assert (!PMS.empty() && "Unable to create Region Pass Manager"); + PMDataManager *PMD = PMS.top(); + + // [1] Create new Call Graph Pass Manager + RGPM = new RGPassManager(PMD->getDepth() + 1); + RGPM->populateInheritedAnalysis(PMS); + + // [2] Set up new manager's top level manager + PMTopLevelManager *TPM = PMD->getTopLevelManager(); + TPM->addIndirectPassManager(RGPM); + + // [3] Assign manager to manage this new manager. This may create + // and push new managers into PMS + Pass *P = dynamic_cast<Pass *>(RGPM); + TPM->schedulePass(P); + + // [4] Push new manager into PMS + PMS.push(RGPM); + } + + RGPM->add(this); +} + +/// Get the printer pass +Pass *RegionPass::createPrinterPass(raw_ostream &O, + const std::string &Banner) const { + return new PrintRegionPass(Banner, O); +} diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index 234dc6b..17612c9 100644 --- a/lib/VMCore/PassManager.cpp +++ b/lib/VMCore/PassManager.cpp @@ -1087,6 +1087,9 @@ void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1, case ON_MODULE_MSG: dbgs() << "' on Module '" << Msg << "'...\n"; break; + case ON_REGION_MSG: + dbgs() << "' on Region '" << Msg << "'...\n"; + break; case ON_LOOP_MSG: dbgs() << "' on Loop '" << Msg << "'...\n"; break; diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 1324285..50f327f 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -20,6 +20,7 @@ #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/RegionPass.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -267,6 +268,40 @@ struct LoopPassPrinter : public LoopPass { char LoopPassPrinter::ID = 0; +struct RegionPassPrinter : public RegionPass { + static char ID; + const PassInfo *PassToPrint; + raw_ostream &Out; + std::string PassName; + + RegionPassPrinter(const PassInfo *PI, raw_ostream &out) : RegionPass(ID), + PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "LoopPass Printer: " + PassToPrintName; + } + + virtual bool runOnRegion(Region *R, RGPassManager &RGM) { + if (!Quiet) { + Out << "Printing analysis '" << PassToPrint->getPassName() << "' for " + << "region: '" << R->getNameStr() << "' in function '" + << R->getEntry()->getParent()->getNameStr() << "':\n"; + } + // Get and print pass... + getAnalysisID<Pass>(PassToPrint->getTypeInfo()).print(Out, + R->getEntry()->getParent()->getParent()); + return false; + } + + virtual const char *getPassName() const { return "'Pass' Printer"; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char RegionPassPrinter::ID = 0; + struct BasicBlockPassPrinter : public BasicBlockPass { const PassInfo *PassToPrint; raw_ostream &Out; @@ -526,6 +561,9 @@ int main(int argc, char **argv) { case PT_BasicBlock: Passes.add(new BasicBlockPassPrinter(PassInf, Out->os())); break; + case PT_Region: + Passes.add(new RegionPassPrinter(PassInf, Out->os())); + break; case PT_Loop: Passes.add(new LoopPassPrinter(PassInf, Out->os())); break; |