diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index dca1e9c2e26..2c49bb1a3d5 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -31,6 +31,8 @@ namespace llvm { namespace llvm { +extern char &NoPassID; // Allow targets to choose not to run a pass. + /// Target-Independent Code Generator Pass Configuration Options. /// /// This is an ImmutablePass solely for the purpose of exposing CodeGen options @@ -136,10 +138,26 @@ protected: /// LLVMTargetMachine provides standard regalloc passes for most targets. virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass); - /// addPostRegAlloc - This method may be implemented by targets that want - /// to run passes after register allocation but before prolog-epilog - /// insertion. This should return true if -print-machineinstrs should print - /// after these passes. + /// getSchedPass - This method may be implemented by target that want to + /// completely override the MachineScheduler pass with a new pass, rather than + /// inheriting from ScheduleDAGInstrs. + virtual char &getSchedPass() { return NoPassID; } + + /// addFinalizeRegAlloc - This method may be implemented by targets that want + /// to run passes within the regalloc pipeline, immediately after the register + /// allocation pass itself. These passes run as soon as virtual regisiters + /// have been rewritten to physical registers but before and other postRA + /// optimization happens. Targets that have marked instructions for bundling + /// must have finalized those bundles by the time these passes have run, + /// because subsequent passes are not guaranteed to be bundle-aware. + virtual bool addFinalizeRegAlloc() { + return false; + } + + /// addPostRegAlloc - This method may be implemented by targets that want to + /// run passes after register allocation pass pipeline but before + /// prolog-epilog insertion. This should return true if -print-machineinstrs + /// should print after these passes. virtual bool addPostRegAlloc() { return false; } diff --git a/lib/CodeGen/Passes.cpp b/lib/CodeGen/Passes.cpp index abf677825c3..285d5df6346 100644 --- a/lib/CodeGen/Passes.cpp +++ b/lib/CodeGen/Passes.cpp @@ -54,7 +54,8 @@ static cl::opt DisableMachineCSE("disable-machine-cse", cl::Hidden, static cl::opt OptimizeRegAlloc("optimize-regalloc", cl::Hidden, cl::desc("Enable optimized register allocation compilation path.")); -static cl::opt EnableMachineSched("enable-misched", cl::Hidden, +static cl::opt +EnableMachineSched("enable-misched", cl::Hidden, cl::desc("Enable the machine instruction scheduling pass.")); static cl::opt EnableStrongPHIElim("strong-phi-elim", cl::Hidden, cl::desc("Use strong PHI elimination.")); @@ -79,6 +80,30 @@ 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) { + switch (Override) { + case cl::BOU_UNSET: + return DefaultID; + case cl::BOU_TRUE: + if (&DefaultID != &NoPassID) + return DefaultID; + if (OptionalIDPtr == &NoPassID) + report_fatal_error("Target cannot enable pass"); + return *OptionalIDPtr; + case cl::BOU_FALSE: + return NoPassID; + } + llvm_unreachable("Invalid command line option state"); +} + //===---------------------------------------------------------------------===// /// TargetPassConfig //===---------------------------------------------------------------------===// @@ -87,6 +112,9 @@ INITIALIZE_PASS(TargetPassConfig, "targetpassconfig", "Target Pass Configuration", false, false) char TargetPassConfig::ID = 0; +static char NoPassIDAnchor = 0; +char &llvm::NoPassID = NoPassIDAnchor; + // Out of line virtual method. TargetPassConfig::~TargetPassConfig() {} @@ -122,6 +150,9 @@ void TargetPassConfig::setOpt(bool &Opt, bool Val) { } void TargetPassConfig::addPass(char &ID) { + if (&ID == &NoPassID) + return; + // FIXME: check user overrides Pass *P = Pass::createPass(ID); if (!P) @@ -427,13 +458,20 @@ void TargetPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) { addPass(RegisterCoalescerID); // PreRA instruction scheduling. - if (EnableMachineSched) - addPass(MachineSchedulerID); + addPass(enablePass(getSchedPass(), EnableMachineSched, &MachineSchedulerID)); // Add the selected register allocation pass. PM.add(RegAllocPass); printAndVerify("After Register Allocation"); + // FinalizeRegAlloc is convenient until MachineInstrBundles is more mature, + // but eventually, all users of it should probably be moved to addPostRA and + // it can go away. Currently, it's the intended place for targets to run + // FinalizeMachineBundles, because passes other than MachineScheduling an + // RegAlloc itself may not be aware of bundles. + if (addFinalizeRegAlloc()) + printAndVerify("After RegAlloc finalization"); + // Perform stack slot coloring and post-ra machine LICM. // // FIXME: Re-enable coloring with register when it's capable of adding