From 79bf288584215f3f3c49050ac1691a6b29c56fec Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Wed, 15 Feb 2012 03:21:51 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150563 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/Passes.h | 14 +++ lib/CodeGen/Passes.cpp | 166 +++++++++++++++++++++++----------- 2 files changed, 128 insertions(+), 52 deletions(-) diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 2e4fb990812..87835a58659 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -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 ± diff --git a/lib/CodeGen/Passes.cpp b/lib/CodeGen/Passes.cpp index 427e4ac327f..ec1f2b4c3b2 100644 --- a/lib/CodeGen/Passes.cpp +++ b/lib/CodeGen/Passes.cpp @@ -80,30 +80,95 @@ static cl::opt 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."); } } -- 2.34.1