Extend TargetPassConfig to allow running only a subset of the normal passes.

This is still a work in progress but I believe it is currently good enough
to fix PR13122 "Need unit test driver for codegen IR passes".  For example,
you can run llc with -stop-after=loop-reduce to have it dump out the IR after
running LSR.  Serializing machine-level IR is not yet supported but we have
some patches in progress for that.

The plan is to serialize the IR to a YAML file, containing separate sections
for the LLVM IR, machine-level IR, and whatever other info is needed.  Chad
suggested that we stash the stop-after pass in the YAML file and use that
instead of the start-after option to figure out where to restart the
compilation.  I think that's a great idea, but since it's not implemented yet
I put the -start-after option into this patch for testing purposes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159570 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bob Wilson 2012-07-02 19:48:45 +00:00
parent 6b2bb15bf7
commit 30a507a1f5
9 changed files with 118 additions and 23 deletions

View File

@ -55,6 +55,10 @@ public:
private:
PassManagerBase *PM;
AnalysisID StartAfter;
AnalysisID StopAfter;
bool Started;
bool Stopped;
protected:
TargetMachine *TM;
@ -92,6 +96,18 @@ public:
CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); }
/// setStartStopPasses - Set the StartAfter and StopAfter passes to allow
/// running only a portion of the normal code-gen pass sequence. If the
/// Start pass ID is zero, then compilation will begin at the normal point;
/// otherwise, clear the Started flag to indicate that passes should not be
/// added until the starting pass is seen. If the Stop pass ID is zero,
/// then compilation will continue to the end.
void setStartStopPasses(AnalysisID Start, AnalysisID Stop) {
StartAfter = Start;
StopAfter = Stop;
Started = (StartAfter == 0);
}
void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
bool getEnableTailMerge() const { return EnableTailMerge; }
@ -238,7 +254,8 @@ protected:
/// Return the pass that was added, or zero if no pass was added.
AnalysisID addPass(AnalysisID PassID);
/// Add a pass to the PassManager.
/// Add a pass to the PassManager if that pass is supposed to be run, as
/// determined by the StartAfter and StopAfter options.
void addPass(Pass *P);
/// addMachinePasses helper to create the target-selected or overriden

View File

@ -14,6 +14,7 @@
#ifndef LLVM_TARGET_TARGETMACHINE_H
#define LLVM_TARGET_TARGETMACHINE_H
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/StringRef.h"
@ -247,7 +248,9 @@ public:
virtual bool addPassesToEmitFile(PassManagerBase &,
formatted_raw_ostream &,
CodeGenFileType,
bool /*DisableVerify*/ = true) {
bool /*DisableVerify*/ = true,
AnalysisID StartAfter = 0,
AnalysisID StopAfter = 0) {
return true;
}
@ -297,7 +300,9 @@ public:
virtual bool addPassesToEmitFile(PassManagerBase &PM,
formatted_raw_ostream &Out,
CodeGenFileType FileType,
bool DisableVerify = true);
bool DisableVerify = true,
AnalysisID StartAfter = 0,
AnalysisID StopAfter = 0);
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to
/// get machine code emitted. This uses a JITCodeEmitter object to handle

View File

@ -13,6 +13,7 @@
#include "llvm/Transforms/Scalar.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
@ -81,9 +82,12 @@ LLVMTargetMachine::LLVMTargetMachine(const Target &T, StringRef Triple,
/// addPassesToX helper drives creation and initialization of TargetPassConfig.
static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM,
PassManagerBase &PM,
bool DisableVerify) {
bool DisableVerify,
AnalysisID StartAfter,
AnalysisID StopAfter) {
// Targets may override createPassConfig to provide a target-specific sublass.
TargetPassConfig *PassConfig = TM->createPassConfig(PM);
PassConfig->setStartStopPasses(StartAfter, StopAfter);
// Set PassConfig options provided by TargetMachine.
PassConfig->setDisableVerify(DisableVerify);
@ -127,12 +131,25 @@ static MCContext *addPassesToGenerateCode(LLVMTargetMachine *TM,
bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
formatted_raw_ostream &Out,
CodeGenFileType FileType,
bool DisableVerify) {
bool DisableVerify,
AnalysisID StartAfter,
AnalysisID StopAfter) {
// Add common CodeGen passes.
MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify);
MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,
StartAfter, StopAfter);
if (!Context)
return true;
if (StopAfter) {
// FIXME: The intent is that this should eventually write out a YAML file,
// containing the LLVM IR, the machine-level IR (when stopping after a
// machine-level pass), and whatever other information is needed to
// deserialize the code and resume compilation. For now, just write the
// LLVM IR.
PM.add(createPrintModulePass(&Out));
return false;
}
if (hasMCSaveTempLabels())
Context->setAllowTemporaryLabels(false);
@ -216,7 +233,7 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
JITCodeEmitter &JCE,
bool DisableVerify) {
// Add common CodeGen passes.
MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify);
MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0);
if (!Context)
return true;
@ -236,7 +253,7 @@ bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
raw_ostream &Out,
bool DisableVerify) {
// Add common CodeGen passes.
Ctx = addPassesToGenerateCode(this, PM, DisableVerify);
Ctx = addPassesToGenerateCode(this, PM, DisableVerify, 0, 0);
if (!Ctx)
return true;

View File

@ -213,7 +213,8 @@ TargetPassConfig::~TargetPassConfig() {
// Out of line constructor provides default values for pass options and
// registers all common codegen passes.
TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
: ImmutablePass(ID), PM(&pm), TM(tm), Impl(0), Initialized(false),
: ImmutablePass(ID), PM(&pm), StartAfter(0), StopAfter(0),
Started(true), Stopped(false), TM(tm), Impl(0), Initialized(false),
DisableVerify(false),
EnableTailMerge(true) {
@ -271,11 +272,22 @@ AnalysisID TargetPassConfig::getPassSubstitution(AnalysisID ID) const {
return I->second;
}
/// Add a pass to the PassManager.
/// Add a pass to the PassManager if that pass is supposed to be run. If the
/// Started/Stopped flags indicate either that the compilation should start at
/// a later pass or that it should stop after an earlier pass, then do not add
/// the pass. Finally, compare the current pass against the StartAfter
/// and StopAfter options and change the Started/Stopped flags accordingly.
void TargetPassConfig::addPass(Pass *P) {
assert(!Initialized && "PassConfig is immutable");
PM->add(P);
if (Started && !Stopped)
PM->add(P);
if (StopAfter == P->getPassID())
Stopped = true;
if (StartAfter == P->getPassID())
Started = true;
if (Stopped && !Started)
report_fatal_error("Cannot stop compilation after pass that is not run");
}
/// Add a CodeGen pass at this point in the pipeline after checking for target

View File

@ -2101,7 +2101,9 @@ char CppWriter::ID = 0;
bool CPPTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
formatted_raw_ostream &o,
CodeGenFileType FileType,
bool DisableVerify) {
bool DisableVerify,
AnalysisID StartAfter,
AnalysisID StopAfter) {
if (FileType != TargetMachine::CGFT_AssemblyFile) return true;
PM.add(new CppWriter(o));
return false;

View File

@ -31,7 +31,9 @@ struct CPPTargetMachine : public TargetMachine {
virtual bool addPassesToEmitFile(PassManagerBase &PM,
formatted_raw_ostream &Out,
CodeGenFileType FileType,
bool DisableVerify);
bool DisableVerify,
AnalysisID StartAfter,
AnalysisID StopAfter);
virtual const TargetData *getTargetData() const { return 0; }
};

View File

@ -48,12 +48,6 @@ class NVPTXTargetMachine : public LLVMTargetMachine {
// bool DisableVerify, MCContext *&OutCtx);
public:
//virtual bool addPassesToEmitFile(PassManagerBase &PM,
// formatted_raw_ostream &Out,
// CodeGenFileType FileType,
// CodeGenOpt::Level OptLevel,
// bool DisableVerify = true) ;
NVPTXTargetMachine(const Target &T, StringRef TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
Reloc::Model RM, CodeModel::Model CM,

View File

@ -0,0 +1,10 @@
; RUN: llc < %s -debug-pass=Structure -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP
; RUN: llc < %s -debug-pass=Structure -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START
; STOP: -loop-reduce -print-module
; STOP: Loop Strength Reduction
; STOP-NEXT: Machine Function Analysis
; START: -machine-branch-prob -gc-lowering
; START: FunctionPass Manager
; START-NEXT: Lower Garbage Collection Instructions

View File

@ -18,6 +18,7 @@
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/IRReader.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
@ -257,6 +258,15 @@ UseInitArray("use-init-array",
cl::desc("Use .init_array instead of .ctors."),
cl::init(false));
static cl::opt<std::string> StopAfter("stop-after",
cl::desc("Stop compilation after a specific pass"),
cl::value_desc("pass-name"),
cl::init(""));
static cl::opt<std::string> StartAfter("start-after",
cl::desc("Resume compilation after a specific pass"),
cl::value_desc("pass-name"),
cl::init(""));
// GetFileNameRoot - Helper function to get the basename of a filename.
static inline std::string
GetFileNameRoot(const std::string &InputFilename) {
@ -353,9 +363,14 @@ int main(int argc, char **argv) {
InitializeAllAsmPrinters();
InitializeAllAsmParsers();
// Initialize codegen so that the -print-after and -print-before options
// work.
initializeCodeGen(*PassRegistry::getPassRegistry());
// Initialize codegen and IR passes used by llc so that the -print-after,
// -print-before, and -stop-after options work.
PassRegistry *Registry = PassRegistry::getPassRegistry();
initializeCore(*Registry);
initializeCodeGen(*Registry);
initializeLoopStrengthReducePass(*Registry);
initializeLowerIntrinsicsPass(*Registry);
initializeUnreachableBlockElimPass(*Registry);
// Register the target printer for --version.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
@ -498,8 +513,29 @@ int main(int argc, char **argv) {
{
formatted_raw_ostream FOS(Out->os());
AnalysisID StartAfterID = 0;
AnalysisID StopAfterID = 0;
const PassRegistry *PR = PassRegistry::getPassRegistry();
if (!StartAfter.empty()) {
const PassInfo *PI = PR->getPassInfo(StartAfter);
if (!PI) {
errs() << argv[0] << ": start-after pass is not registered.\n";
return 1;
}
StartAfterID = PI->getTypeInfo();
}
if (!StopAfter.empty()) {
const PassInfo *PI = PR->getPassInfo(StopAfter);
if (!PI) {
errs() << argv[0] << ": stop-after pass is not registered.\n";
return 1;
}
StopAfterID = PI->getTypeInfo();
}
// Ask the target to add backend passes as necessary.
if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify)) {
if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify,
StartAfterID, StopAfterID)) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
return 1;