From c174eaf9481e3f7a6695d4f19e62e2b6f005c4e9 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Thu, 8 Mar 2012 01:41:12 +0000 Subject: [PATCH] misched interface: Expose the MachineScheduler pass. Allow targets to provide their own schedulers (subclass of ScheduleDAGInstrs) to the misched pass. Select schedulers using -misched=... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152278 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineScheduler.h | 86 +++++++ lib/CodeGen/MachineScheduler.cpp | 286 ++++++++++-------------- 2 files changed, 208 insertions(+), 164 deletions(-) create mode 100644 include/llvm/CodeGen/MachineScheduler.h diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h new file mode 100644 index 00000000000..aded11fb658 --- /dev/null +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -0,0 +1,86 @@ +//==- MachineScheduler.h - MachineInstr Scheduling Pass ----------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a MachineSchedRegistry for registering alternative machine +// schedulers. A Target may provide an alternative scheduler implementation by +// implementing the following boilerplate: +// +// static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) { +// return new CustomMachineScheduler(C); +// } +// static MachineSchedRegistry +// SchedDefaultRegistry("custom", "Run my target's custom scheduler", +// createCustomMachineSched); +// +//===----------------------------------------------------------------------===// + +#ifndef MACHINESCHEDULER_H +#define MACHINESCHEDULER_H + +#include "llvm/CodeGen/MachinePassRegistry.h" + +namespace llvm { + +class AliasAnalysis; +class LiveIntervals; +class MachineDominatorTree; +class MachineLoopInfo; +class ScheduleDAGInstrs; + +/// MachineSchedContext provides enough context from the MachineScheduler pass +/// for the target to instantiate a scheduler. +struct MachineSchedContext { + MachineFunction *MF; + const MachineLoopInfo *MLI; + const MachineDominatorTree *MDT; + AliasAnalysis *AA; + LiveIntervals *LIS; + + MachineSchedContext(): MF(0), MLI(0), MDT(0), AA(0), LIS(0) {} +}; + +/// MachineSchedRegistry provides a selection of available machine instruction +/// schedulers. +class MachineSchedRegistry : public MachinePassRegistryNode { +public: + typedef ScheduleDAGInstrs *(*ScheduleDAGCtor)(MachineSchedContext *); + + // RegisterPassParser requires a (misnamed) FunctionPassCtor type. + typedef ScheduleDAGCtor FunctionPassCtor; + + static MachinePassRegistry Registry; + + MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C) + : MachinePassRegistryNode(N, D, (MachinePassCtor)C) { + Registry.Add(this); + } + ~MachineSchedRegistry() { Registry.Remove(this); } + + // Accessors. + // + MachineSchedRegistry *getNext() const { + return (MachineSchedRegistry *)MachinePassRegistryNode::getNext(); + } + static MachineSchedRegistry *getList() { + return (MachineSchedRegistry *)Registry.getList(); + } + static ScheduleDAGCtor getDefault() { + return (ScheduleDAGCtor)Registry.getDefault(); + } + static void setDefault(ScheduleDAGCtor C) { + Registry.setDefault((MachinePassCtor)C); + } + static void setListener(MachinePassRegistryListener *L) { + Registry.setListener(L); + } +}; + +} // namespace llvm + +#endif diff --git a/lib/CodeGen/MachineScheduler.cpp b/lib/CodeGen/MachineScheduler.cpp index aff67ce09e8..203ddfd18bc 100644 --- a/lib/CodeGen/MachineScheduler.cpp +++ b/lib/CodeGen/MachineScheduler.cpp @@ -15,7 +15,7 @@ #define DEBUG_TYPE "misched" #include "llvm/CodeGen/LiveIntervalAnalysis.h" -#include "llvm/CodeGen/MachinePassRegistry.h" +#include "llvm/CodeGen/MachineScheduler.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -43,14 +43,9 @@ static bool ViewMISchedDAGs = false; namespace { /// MachineScheduler runs after coalescing and before register allocation. -class MachineScheduler : public MachineFunctionPass { +class MachineScheduler : public MachineSchedContext, + public MachineFunctionPass { public: - MachineFunction *MF; - const TargetInstrInfo *TII; - const MachineLoopInfo *MLI; - const MachineDominatorTree *MDT; - LiveIntervals *LIS; - MachineScheduler(); virtual void getAnalysisUsage(AnalysisUsage &AU) const; @@ -78,7 +73,7 @@ INITIALIZE_PASS_END(MachineScheduler, "misched", "Machine Instruction Scheduler", false, false) MachineScheduler::MachineScheduler() -: MachineFunctionPass(ID), MF(0), MLI(0), MDT(0) { +: MachineFunctionPass(ID) { initializeMachineSchedulerPass(*PassRegistry::getPassRegistry()); } @@ -95,47 +90,9 @@ void MachineScheduler::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } -namespace { -/// MachineSchedRegistry provides a selection of available machine instruction -/// schedulers. -class MachineSchedRegistry : public MachinePassRegistryNode { -public: - typedef ScheduleDAGInstrs *(*ScheduleDAGCtor)(MachineScheduler *); - - // RegisterPassParser requires a (misnamed) FunctionPassCtor type. - typedef ScheduleDAGCtor FunctionPassCtor; - - static MachinePassRegistry Registry; - - MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C) - : MachinePassRegistryNode(N, D, (MachinePassCtor)C) { - Registry.Add(this); - } - ~MachineSchedRegistry() { Registry.Remove(this); } - - // Accessors. - // - MachineSchedRegistry *getNext() const { - return (MachineSchedRegistry *)MachinePassRegistryNode::getNext(); - } - static MachineSchedRegistry *getList() { - return (MachineSchedRegistry *)Registry.getList(); - } - static ScheduleDAGCtor getDefault() { - return (ScheduleDAGCtor)Registry.getDefault(); - } - static void setDefault(ScheduleDAGCtor C) { - Registry.setDefault((MachinePassCtor)C); - } - static void setListener(MachinePassRegistryListener *L) { - Registry.setListener(L); - } -}; -} // namespace - MachinePassRegistry MachineSchedRegistry::Registry; -static ScheduleDAGInstrs *createDefaultMachineSched(MachineScheduler *P); +static ScheduleDAGInstrs *createDefaultMachineSched(MachineSchedContext *C); /// MachineSchedOpt allows command line selection of the scheduler. static cl::optMF, *P->MLI, *P->MDT, /*IsPostRA=*/false, P->LIS), - Pass(P) {} - - /// ScheduleDAGInstrs callback. - void schedule(); - - /// Interface implemented by the selected top-down liveinterval scheduler. - /// - /// Pick the next node to schedule, or return NULL. - virtual SUnit *pickNode() = 0; - - /// When all preceeding dependencies have been resolved, free this node for - /// scheduling. - virtual void releaseNode(SUnit *SU) = 0; - -protected: - void releaseSucc(SUnit *SU, SDep *SuccEdge); - void releaseSuccessors(SUnit *SU); -}; -} // namespace - -/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. When -/// NumPredsLeft reaches zero, release the successor node. -void ScheduleTopDownLive::releaseSucc(SUnit *SU, SDep *SuccEdge) { - SUnit *SuccSU = SuccEdge->getSUnit(); - -#ifndef NDEBUG - if (SuccSU->NumPredsLeft == 0) { - dbgs() << "*** Scheduling failed! ***\n"; - SuccSU->dump(this); - dbgs() << " has been released too many times!\n"; - llvm_unreachable(0); - } -#endif - --SuccSU->NumPredsLeft; - if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) - releaseNode(SuccSU); -} - -/// releaseSuccessors - Call releaseSucc on each of SU's successors. -void ScheduleTopDownLive::releaseSuccessors(SUnit *SU) { - for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); - I != E; ++I) { - releaseSucc(SU, &*I); - } -} - -/// schedule - This is called back from ScheduleDAGInstrs::Run() when it's -/// time to do some work. -void ScheduleTopDownLive::schedule() { - buildSchedGraph(&Pass->getAnalysis()); - - DEBUG(dbgs() << "********** MI Scheduling **********\n"); - DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) - SUnits[su].dumpAll(this)); - - if (ViewMISchedDAGs) viewGraph(); - - // Release any successors of the special Entry node. It is currently unused, - // but we keep up appearances. - releaseSuccessors(&EntrySU); - - // Release all DAG roots for scheduling. - for (std::vector::iterator I = SUnits.begin(), E = SUnits.end(); - I != E; ++I) { - // A SUnit is ready to schedule if it has no predecessors. - if (I->Preds.empty()) - releaseNode(&(*I)); - } - - MachineBasicBlock::iterator InsertPos = Begin; - while (SUnit *SU = pickNode()) { - DEBUG(dbgs() << "*** Scheduling Instruction:\n"; SU->dump(this)); - - // Move the instruction to its new location in the instruction stream. - MachineInstr *MI = SU->getInstr(); - if (&*InsertPos == MI) - ++InsertPos; - else { - BB->splice(InsertPos, BB, MI); - Pass->LIS->handleMove(MI); - if (Begin == InsertPos) - Begin = MI; - } - - // Release dependent instructions for scheduling. - releaseSuccessors(SU); - } -} - bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) { // Initialize the context of the pass. MF = &mf; MLI = &getAnalysis(); MDT = &getAnalysis(); + AA = &getAnalysis(); + LIS = &getAnalysis(); - TII = MF->getTarget().getInstrInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); // Select the scheduler, or set the default. MachineSchedRegistry::ScheduleDAGCtor Ctor = @@ -320,16 +177,118 @@ void MachineScheduler::print(raw_ostream &O, const Module* m) const { } //===----------------------------------------------------------------------===// -// Placeholder for extending the machine instruction scheduler. +// ScheduleTopeDownLive - Base class for basic top-down scheduling with +// LiveIntervals preservation. +// ===----------------------------------------------------------------------===// + +namespace { +/// ScheduleTopDownLive is an implementation of ScheduleDAGInstrs that schedules +/// machine instructions while updating LiveIntervals. +class ScheduleTopDownLive : public ScheduleDAGInstrs { + AliasAnalysis *AA; +public: + ScheduleTopDownLive(MachineSchedContext *C): + ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), + AA(C->AA) {} + + /// ScheduleDAGInstrs interface. + void schedule(); + + /// Interface implemented by the selected top-down liveinterval scheduler. + /// + /// Pick the next node to schedule, or return NULL. + virtual SUnit *pickNode() = 0; + + /// When all preceeding dependencies have been resolved, free this node for + /// scheduling. + virtual void releaseNode(SUnit *SU) = 0; + +protected: + void releaseSucc(SUnit *SU, SDep *SuccEdge); + void releaseSuccessors(SUnit *SU); +}; +} // namespace + +/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. When +/// NumPredsLeft reaches zero, release the successor node. +void ScheduleTopDownLive::releaseSucc(SUnit *SU, SDep *SuccEdge) { + SUnit *SuccSU = SuccEdge->getSUnit(); + +#ifndef NDEBUG + if (SuccSU->NumPredsLeft == 0) { + dbgs() << "*** Scheduling failed! ***\n"; + SuccSU->dump(this); + dbgs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --SuccSU->NumPredsLeft; + if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) + releaseNode(SuccSU); +} + +/// releaseSuccessors - Call releaseSucc on each of SU's successors. +void ScheduleTopDownLive::releaseSuccessors(SUnit *SU) { + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + releaseSucc(SU, &*I); + } +} + +/// schedule - This is called back from ScheduleDAGInstrs::Run() when it's +/// time to do some work. +void ScheduleTopDownLive::schedule() { + buildSchedGraph(AA); + + DEBUG(dbgs() << "********** MI Scheduling **********\n"); + DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + SUnits[su].dumpAll(this)); + + if (ViewMISchedDAGs) viewGraph(); + + // Release any successors of the special Entry node. It is currently unused, + // but we keep up appearances. + releaseSuccessors(&EntrySU); + + // Release all DAG roots for scheduling. + for (std::vector::iterator I = SUnits.begin(), E = SUnits.end(); + I != E; ++I) { + // A SUnit is ready to schedule if it has no predecessors. + if (I->Preds.empty()) + releaseNode(&(*I)); + } + + MachineBasicBlock::iterator InsertPos = Begin; + while (SUnit *SU = pickNode()) { + DEBUG(dbgs() << "*** Scheduling Instruction:\n"; SU->dump(this)); + + // Move the instruction to its new location in the instruction stream. + MachineInstr *MI = SU->getInstr(); + if (&*InsertPos == MI) + ++InsertPos; + else { + BB->splice(InsertPos, BB, MI); + LIS->handleMove(MI); + if (Begin == InsertPos) + Begin = MI; + } + + // Release dependent instructions for scheduling. + releaseSuccessors(SU); + } +} + +//===----------------------------------------------------------------------===// +// Placeholder for the default machine instruction scheduler. //===----------------------------------------------------------------------===// namespace { class DefaultMachineScheduler : public ScheduleDAGInstrs { - MachineScheduler *Pass; + AliasAnalysis *AA; public: - DefaultMachineScheduler(MachineScheduler *P): - ScheduleDAGInstrs(*P->MF, *P->MLI, *P->MDT, /*IsPostRA=*/false, P->LIS), - Pass(P) {} + DefaultMachineScheduler(MachineSchedContext *C): + ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), + AA(C->AA) {} /// schedule - This is called back from ScheduleDAGInstrs::Run() when it's /// time to do some work. @@ -337,19 +296,18 @@ public: }; } // namespace -static ScheduleDAGInstrs *createDefaultMachineSched(MachineScheduler *P) { - return new DefaultMachineScheduler(P); +static ScheduleDAGInstrs *createDefaultMachineSched(MachineSchedContext *C) { + return new DefaultMachineScheduler(C); } static MachineSchedRegistry SchedDefaultRegistry("default", "Activate the scheduler pass, " "but don't reorder instructions", createDefaultMachineSched); - /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's /// time to do some work. void DefaultMachineScheduler::schedule() { - buildSchedGraph(&Pass->getAnalysis()); + buildSchedGraph(AA); DEBUG(dbgs() << "********** MI Scheduling **********\n"); DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) @@ -382,8 +340,8 @@ struct ShuffleSUnitOrder { class InstructionShuffler : public ScheduleTopDownLive { std::priority_queue, ShuffleSUnitOrder> Queue; public: - InstructionShuffler(MachineScheduler *P): - ScheduleTopDownLive(P) {} + InstructionShuffler(MachineSchedContext *C): + ScheduleTopDownLive(C) {} /// ScheduleTopDownLive Interface @@ -400,8 +358,8 @@ public: }; } // namespace -static ScheduleDAGInstrs *createInstructionShuffler(MachineScheduler *P) { - return new InstructionShuffler(P); +static ScheduleDAGInstrs *createInstructionShuffler(MachineSchedContext *C) { + return new InstructionShuffler(C); } static MachineSchedRegistry ShufflerRegistry("shuffle", "Shuffle machine instructions",