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
This commit is contained in:
Tobias Grosser 2010-10-20 01:54:44 +00:00
parent 3e26c3c7d4
commit 6551360535
8 changed files with 535 additions and 1 deletions

View File

@ -51,6 +51,14 @@
<li><a href="#doFinalization_loop">The <tt>doFinalization() <li><a href="#doFinalization_loop">The <tt>doFinalization()
</tt> method</a></li> </tt> method</a></li>
</ul></li> </ul></li>
<li><a href="#RegionPass">The <tt>RegionPass</tt> class</a>
<ul>
<li><a href="#doInitialization_region">The <tt>doInitialization(Region *,
RGPassManager &amp;)</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> <li><a href="#BasicBlockPass">The <tt>BasicBlockPass</tt> class</a>
<ul> <ul>
<li><a href="#doInitialization_fn">The <tt>doInitialization(Function <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="#CallGraphSCCPass">CallGraphSCCPass</a></tt>, <tt><a
href="#FunctionPass">FunctionPass</a></tt>, or <tt><a href="#FunctionPass">FunctionPass</a></tt>, or <tt><a
href="#LoopPass">LoopPass</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 href="#BasicBlockPass">BasicBlockPass</a></tt> classes, which gives the system
more information about what your pass does, and how it can be combined with 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 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>
<!-- ======================================================================= -->
<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 &amp;)</tt>
method</a>
</div>
<div class="doc_text">
<div class="doc_code"><pre>
<b>virtual bool</b> doInitialization(Region *, RGPassManager &amp;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 &amp;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>
<!-- ======================================================================= --> <!-- ======================================================================= -->

View File

@ -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

View File

@ -57,6 +57,7 @@ enum PassManagerType {
PMT_CallGraphPassManager, ///< CGPassManager PMT_CallGraphPassManager, ///< CGPassManager
PMT_FunctionPassManager, ///< FPPassManager PMT_FunctionPassManager, ///< FPPassManager
PMT_LoopPassManager, ///< LPPassManager PMT_LoopPassManager, ///< LPPassManager
PMT_RegionPassManager, ///< RGPassManager
PMT_BasicBlockPassManager, ///< BBPassManager PMT_BasicBlockPassManager, ///< BBPassManager
PMT_Last PMT_Last
}; };
@ -64,13 +65,14 @@ enum PassManagerType {
// Different types of passes. // Different types of passes.
enum PassKind { enum PassKind {
PT_BasicBlock, PT_BasicBlock,
PT_Region,
PT_Loop, PT_Loop,
PT_Function, PT_Function,
PT_CallGraphSCC, PT_CallGraphSCC,
PT_Module, PT_Module,
PT_PassManager PT_PassManager
}; };
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// Pass interface - Implemented by all 'passes'. Subclass this if you are an /// Pass interface - Implemented by all 'passes'. Subclass this if you are an
/// interprocedural optimization or you do not fit into any of the more /// interprocedural optimization or you do not fit into any of the more

View File

@ -106,6 +106,7 @@ enum PassDebuggingString {
ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n" ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n"
ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n"
ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n"
ON_REGION_MSG, // " 'on Region ...\n'"
ON_LOOP_MSG, // " 'on Loop ...\n'" ON_LOOP_MSG, // " 'on Loop ...\n'"
ON_CG_MSG // "' on Call Graph ...\n'" ON_CG_MSG // "' on Call Graph ...\n'"
}; };

View File

@ -40,6 +40,7 @@ add_llvm_library(LLVMAnalysis
ProfileInfoLoaderPass.cpp ProfileInfoLoaderPass.cpp
ProfileVerifierPass.cpp ProfileVerifierPass.cpp
RegionInfo.cpp RegionInfo.cpp
RegionPass.cpp
RegionPrinter.cpp RegionPrinter.cpp
ScalarEvolution.cpp ScalarEvolution.cpp
ScalarEvolutionAliasAnalysis.cpp ScalarEvolutionAliasAnalysis.cpp

276
lib/Analysis/RegionPass.cpp Normal file
View File

@ -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);
}

View File

@ -1087,6 +1087,9 @@ void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1,
case ON_MODULE_MSG: case ON_MODULE_MSG:
dbgs() << "' on Module '" << Msg << "'...\n"; dbgs() << "' on Module '" << Msg << "'...\n";
break; break;
case ON_REGION_MSG:
dbgs() << "' on Region '" << Msg << "'...\n";
break;
case ON_LOOP_MSG: case ON_LOOP_MSG:
dbgs() << "' on Loop '" << Msg << "'...\n"; dbgs() << "' on Loop '" << Msg << "'...\n";
break; break;

View File

@ -20,6 +20,7 @@
#include "llvm/Assembly/PrintModulePass.h" #include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CallGraph.h"
#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
@ -267,6 +268,40 @@ struct LoopPassPrinter : public LoopPass {
char LoopPassPrinter::ID = 0; 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 { struct BasicBlockPassPrinter : public BasicBlockPass {
const PassInfo *PassToPrint; const PassInfo *PassToPrint;
raw_ostream &Out; raw_ostream &Out;
@ -526,6 +561,9 @@ int main(int argc, char **argv) {
case PT_BasicBlock: case PT_BasicBlock:
Passes.add(new BasicBlockPassPrinter(PassInf, Out->os())); Passes.add(new BasicBlockPassPrinter(PassInf, Out->os()));
break; break;
case PT_Region:
Passes.add(new RegionPassPrinter(PassInf, Out->os()));
break;
case PT_Loop: case PT_Loop:
Passes.add(new LoopPassPrinter(PassInf, Out->os())); Passes.add(new LoopPassPrinter(PassInf, Out->os()));
break; break;