Allow CodeGen (llc) command line options to work as expected.

The llc command line options for enabling/disabling passes are local to CodeGen/Passes.cpp. This patch associates those options with standard pass IDs so they work regardless of how the target configures the passes.

A target has two ways of overriding standard passes:
1) Redefine the pass pipeline (override TargetPassConfig::add%Stage)
2) Replace or suppress individiual passes with TargetPassConfig::substitutePass.

In both cases, the command line options associated with the pass override the target default.

For example, say a target wants to disable machine instruction scheduling by default:

- The target calls disablePass(MachineSchedulerID) but otherwise does not override any TargetPassConfig methods.

- Without any llc options, no scheduler is run.

- With -enable-misched, the standard machine scheduler is run and honors the -misched=... flag to select the scheduler variant, which may be used for performance evaluation or testing.

Sorry overridePass is ugly. I haven't thought of a better way without replacing the cl::opt framework. I hope to do that one day...

I haven't figured out why CodeGen uses char& for pass IDs. AnalysisID is much easier to use and less bug prone. I'm using it wherever I can for internal implementation. Maybe later we can change the global pass ID definitions as well.

llvm-svn: 150563
This commit is contained in:
Andrew Trick 2012-02-15 03:21:51 +00:00
parent c9ce9d2315
commit e9a951c00b
2 changed files with 128 additions and 52 deletions

View File

@ -40,6 +40,20 @@ class PassConfigImpl;
/// This is an ImmutablePass solely for the purpose of exposing CodeGen options
/// to the internals of other CodeGen passes.
class TargetPassConfig : public ImmutablePass {
public:
/// Pseudo Pass IDs. These are defined within TargetPassConfig because they
/// are unregistered pass IDs. They are only useful for use with
/// TargetPassConfig APIs to identify multiple occurrences of the same pass.
///
/// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early
/// during codegen, on SSA form.
static char EarlyTailDuplicateID;
/// PostRAMachineLICM - A clone of the LICM pass that runs during late machine
/// optimization after regalloc.
static char PostRAMachineLICMID;
protected:
TargetMachine *TM;
PassManagerBase ±

View File

@ -80,30 +80,95 @@ static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden,
cl::desc("Verify generated machine code"),
cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL));
// Allow Pass selection to be overriden by command line options.
//
// DefaultID is the default pass to run which may be NoPassID, or may be
// overriden by the target.
//
// OptionalID is a pass that may be forcibly enabled by the user when the
// default is NoPassID.
char &enablePass(char &DefaultID, cl::boolOrDefault Override,
char *OptionalIDPtr = &NoPassID) {
/// Allow standard passes to be disabled by command line options. This supports
/// simple binary flags that either suppress the pass or do nothing.
/// i.e. -disable-mypass=false has no effect.
/// These should be converted to boolOrDefault in order to use applyOverride.
static AnalysisID applyDisable(AnalysisID ID, bool Override) {
if (Override)
return &NoPassID;
return ID;
}
/// Allow Pass selection to be overriden by command line options. This supports
/// flags with ternary conditions. TargetID is passed through by default. The
/// pass is suppressed when the option is false. When the option is true, the
/// StandardID is selected if the target provides no default.
static AnalysisID applyOverride(AnalysisID TargetID, cl::boolOrDefault Override,
AnalysisID StandardID) {
switch (Override) {
case cl::BOU_UNSET:
return DefaultID;
return TargetID;
case cl::BOU_TRUE:
if (&DefaultID != &NoPassID)
return DefaultID;
if (OptionalIDPtr == &NoPassID)
if (TargetID != &NoPassID)
return TargetID;
if (StandardID == &NoPassID)
report_fatal_error("Target cannot enable pass");
return *OptionalIDPtr;
return StandardID;
case cl::BOU_FALSE:
return NoPassID;
return &NoPassID;
}
llvm_unreachable("Invalid command line option state");
}
/// Allow standard passes to be disabled by the command line, regardless of who
/// is adding the pass.
///
/// StandardID is the pass identified in the standard pass pipeline and provided
/// to addPass(). It may be a target-specific ID in the case that the target
/// directly adds its own pass, but in that case we harmlessly fall through.
///
/// TargetID is the pass that the target has configured to override StandardID.
///
/// StandardID may be a pseudo ID. In that case TargetID is the name of the real
/// pass to run. This allows multiple options to control a single pass depending
/// on where in the pipeline that pass is added.
static AnalysisID overridePass(AnalysisID StandardID, AnalysisID TargetID) {
if (StandardID == &PostRASchedulerID)
return applyDisable(TargetID, DisablePostRA);
if (StandardID == &BranchFolderPassID)
return applyDisable(TargetID, DisableBranchFold);
if (StandardID == &TailDuplicateID)
return applyDisable(TargetID, DisableTailDuplicate);
if (StandardID == &TargetPassConfig::EarlyTailDuplicateID)
return applyDisable(TargetID, DisableEarlyTailDup);
if (StandardID == &MachineBlockPlacementID)
return applyDisable(TargetID, DisableCodePlace);
if (StandardID == &CodePlacementOptID)
return applyDisable(TargetID, DisableCodePlace);
if (StandardID == &StackSlotColoringID)
return applyDisable(TargetID, DisableSSC);
if (StandardID == &DeadMachineInstructionElimID)
return applyDisable(TargetID, DisableMachineDCE);
if (StandardID == &MachineLICMID)
return applyDisable(TargetID, DisableMachineLICM);
if (StandardID == &MachineCSEID)
return applyDisable(TargetID, DisableMachineCSE);
if (StandardID == &MachineSchedulerID)
return applyOverride(TargetID, EnableMachineSched, StandardID);
if (StandardID == &TargetPassConfig::PostRAMachineLICMID)
return applyDisable(TargetID, DisablePostRAMachineLICM);
if (StandardID == &MachineSinkingID)
return applyDisable(TargetID, DisableMachineSink);
if (StandardID == &MachineCopyPropagationID)
return applyDisable(TargetID, DisableCopyProp);
return TargetID;
}
//===---------------------------------------------------------------------===//
/// TargetPassConfig
//===---------------------------------------------------------------------===//
@ -115,6 +180,10 @@ char TargetPassConfig::ID = 0;
static char NoPassIDAnchor = 0;
char &llvm::NoPassID = NoPassIDAnchor;
// Pseudo Pass IDs.
char TargetPassConfig::EarlyTailDuplicateID = 0;
char TargetPassConfig::PostRAMachineLICMID = 0;
namespace llvm {
class PassConfigImpl {
public:
@ -146,6 +215,13 @@ TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
// Register all target independent codegen passes to activate their PassIDs,
// including this pass itself.
initializeCodeGen(*PassRegistry::getPassRegistry());
// Substitute Pseudo Pass IDs for real ones.
substitutePass(EarlyTailDuplicateID, TailDuplicateID);
substitutePass(PostRAMachineLICMID, MachineLICMID);
// Temporarily disable experimental passes.
substitutePass(MachineSchedulerID, NoPassID);
}
/// createPassConfig - Create a pass configuration object to be used by
@ -184,8 +260,8 @@ AnalysisID TargetPassConfig::getPassSubstitution(AnalysisID ID) const {
AnalysisID TargetPassConfig::addPass(char &ID) {
assert(!Initialized && "PassConfig is immutable");
AnalysisID FinalID = getPassSubstitution(&ID);
// FIXME: check user overrides
AnalysisID TargetID = getPassSubstitution(&ID);
AnalysisID FinalID = overridePass(&ID, TargetID);
if (FinalID == &NoPassID)
return FinalID;
@ -325,7 +401,7 @@ void TargetPassConfig::addMachinePasses() {
printNoVerify("After PreSched2 passes");
// Second pass scheduler.
if (getOptLevel() != CodeGenOpt::None && !DisablePostRA) {
if (getOptLevel() != CodeGenOpt::None) {
addPass(PostRASchedulerID);
printNoVerify("After PostRAScheduler");
}
@ -336,7 +412,7 @@ void TargetPassConfig::addMachinePasses() {
PM.add(createGCInfoPrinter(dbgs()));
// Basic block placement.
if (getOptLevel() != CodeGenOpt::None && !DisableCodePlace)
if (getOptLevel() != CodeGenOpt::None)
addBlockPlacement();
if (addPreEmitPass())
@ -346,10 +422,8 @@ void TargetPassConfig::addMachinePasses() {
/// Add passes that optimize machine instructions in SSA form.
void TargetPassConfig::addMachineSSAOptimization() {
// Pre-ra tail duplication.
if (!DisableEarlyTailDup) {
addPass(TailDuplicateID);
if (addPass(EarlyTailDuplicateID) != &NoPassID)
printAndVerify("After Pre-RegAlloc TailDuplicate");
}
// Optimize PHIs before DCE: removing dead PHI cycles may make more
// instructions dead.
@ -363,16 +437,12 @@ void TargetPassConfig::addMachineSSAOptimization() {
// there is one known exception: lowered code for arguments that are only
// used by tail calls, where the tail calls reuse the incoming stack
// arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
if (!DisableMachineDCE)
addPass(DeadMachineInstructionElimID);
addPass(DeadMachineInstructionElimID);
printAndVerify("After codegen DCE pass");
if (!DisableMachineLICM)
addPass(MachineLICMID);
if (!DisableMachineCSE)
addPass(MachineCSEID);
if (!DisableMachineSink)
addPass(MachineSinkingID);
addPass(MachineLICMID);
addPass(MachineCSEID);
addPass(MachineSinkingID);
printAndVerify("After Machine LICM, CSE and Sinking passes");
addPass(PeepholeOptimizerID);
@ -494,7 +564,7 @@ void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
addPass(RegisterCoalescerID);
// PreRA instruction scheduling.
addPass(enablePass(getSchedPass(), EnableMachineSched, &MachineSchedulerID));
addPass(MachineSchedulerID);
// Add the selected register allocation pass.
PM.add(RegAllocPass);
@ -512,14 +582,12 @@ void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
//
// FIXME: Re-enable coloring with register when it's capable of adding
// kill markers.
if (!DisableSSC)
addPass(StackSlotColoringID);
addPass(StackSlotColoringID);
// Run post-ra machine LICM to hoist reloads / remats.
//
// FIXME: can this move into MachineLateOptimization?
if (!DisablePostRAMachineLICM)
addPass(MachineLICMID);
addPass(PostRAMachineLICMID);
printAndVerify("After StackSlotColoring and postra Machine LICM");
}
@ -531,40 +599,34 @@ void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
/// Add passes that optimize machine instructions after register allocation.
void TargetPassConfig::addMachineLateOptimization() {
// Branch folding must be run after regalloc and prolog/epilog insertion.
if (!DisableBranchFold) {
addPass(BranchFolderPassID);
if (addPass(BranchFolderPassID) != &NoPassID)
printNoVerify("After BranchFolding");
}
// Tail duplication.
if (!DisableTailDuplicate) {
addPass(TailDuplicateID);
if (addPass(TailDuplicateID) != &NoPassID)
printNoVerify("After TailDuplicate");
}
// Copy propagation.
if (!DisableCopyProp) {
addPass(MachineCopyPropagationID);
if (addPass(MachineCopyPropagationID) != &NoPassID)
printNoVerify("After copy propagation pass");
}
}
/// Add standard basic block placement passes.
void TargetPassConfig::addBlockPlacement() {
AnalysisID ID = &NoPassID;
if (EnableBlockPlacement) {
// MachineBlockPlacement is an experimental pass which is disabled by
// default currently. Eventually it should subsume CodePlacementOpt, so
// when enabled, the other is disabled.
addPass(MachineBlockPlacementID);
printNoVerify("After MachineBlockPlacement");
ID = addPass(MachineBlockPlacementID);
} else {
addPass(CodePlacementOptID);
printNoVerify("After CodePlacementOpt");
ID = addPass(CodePlacementOptID);
}
if (ID != &NoPassID) {
// Run a separate pass to collect block placement statistics.
if (EnableBlockPlacementStats)
addPass(MachineBlockPlacementStatsID);
// Run a separate pass to collect block placement statistics.
if (EnableBlockPlacementStats) {
addPass(MachineBlockPlacementStatsID);
printNoVerify("After MachineBlockPlacementStats");
printNoVerify("After machine block placement.");
}
}