Allow CodeGen (llc) command line options to work as expected.
authorAndrew Trick <atrick@apple.com>
Wed, 15 Feb 2012 03:21:51 +0000 (03:21 +0000)
committerAndrew Trick <atrick@apple.com>
Wed, 15 Feb 2012 03:21:51 +0000 (03:21 +0000)
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
lib/CodeGen/Passes.cpp

index 2e4fb990812a01e2d74fac1fe35f00d555eb22c5..87835a58659df1942eacfdd7e5b5b0471ab46d7c 100644 (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 &PM;
index 427e4ac327ff217a8b5097dfb51c180e76b91f6f..ec1f2b4c3b23d598ad5554660420c4d9db6d494c 100644 (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.");
   }
 }