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 | 246 ++++++++++-------------- 2 files changed, 188 insertions(+), 144 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::opt(); + MDT = &getAnalysis(); + AA = &getAnalysis(); + + LIS = &getAnalysis(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + // Select the scheduler, or set the default. + MachineSchedRegistry::ScheduleDAGCtor Ctor = + MachineSchedRegistry::getDefault(); + if (!Ctor) { + Ctor = MachineSchedOpt; + MachineSchedRegistry::setDefault(Ctor); + } + // Instantiate the selected scheduler. + OwningPtr Scheduler(Ctor(this)); + + // Visit all machine basic blocks. + for (MachineFunction::iterator MBB = MF->begin(), MBBEnd = MF->end(); + MBB != MBBEnd; ++MBB) { + + // Break the block into scheduling regions [I, RegionEnd), and schedule each + // region as soon as it is discovered. + unsigned RemainingCount = MBB->size(); + for(MachineBasicBlock::iterator RegionEnd = MBB->end(); + RegionEnd != MBB->begin();) { + Scheduler->startBlock(MBB); + // The next region starts above the previous region. Look backward in the + // instruction stream until we find the nearest boundary. + MachineBasicBlock::iterator I = RegionEnd; + for(;I != MBB->begin(); --I, --RemainingCount) { + if (TII->isSchedulingBoundary(llvm::prior(I), MBB, *MF)) + break; + } + // Notify the scheduler of the region, even if we may skip scheduling + // it. Perhaps it still needs to be bundled. + Scheduler->enterRegion(MBB, I, RegionEnd, RemainingCount); + + // Skip empty scheduling regions (0 or 1 schedulable instructions). + if (I == RegionEnd || I == llvm::prior(RegionEnd)) { + RegionEnd = llvm::prior(RegionEnd); + if (I != RegionEnd) + --RemainingCount; + // Close the current region. Bundle the terminator if needed. + Scheduler->exitRegion(); + continue; + } + DEBUG(dbgs() << "MachineScheduling " << MF->getFunction()->getName() + << ":BB#" << MBB->getNumber() << "\n From: " << *I << " To: "; + if (RegionEnd != MBB->end()) dbgs() << *RegionEnd; + else dbgs() << "End"; + dbgs() << " Remaining: " << RemainingCount << "\n"); + + // Inform ScheduleDAGInstrs of the region being scheduled. It calls back + // to our schedule() method. + Scheduler->schedule(); + Scheduler->exitRegion(); + + // Scheduling has invalidated the current iterator 'I'. Ask the + // scheduler for the top of it's scheduled region. + RegionEnd = Scheduler->begin(); + } + assert(RemainingCount == 0 && "Instruction count mismatch!"); + Scheduler->finishBlock(); + } + return true; +} + +void MachineScheduler::print(raw_ostream &O, const Module* m) const { + // unimplemented +} + //===----------------------------------------------------------------------===// -// Machine Instruction Scheduling Common Implementation -//===----------------------------------------------------------------------===// +// 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 { -protected: - MachineScheduler *Pass; + AliasAnalysis *AA; public: - ScheduleTopDownLive(MachineScheduler *P): - ScheduleDAGInstrs(*P->MF, *P->MLI, *P->MDT, /*IsPostRA=*/false, P->LIS), - Pass(P) {} + ScheduleTopDownLive(MachineSchedContext *C): + ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), + AA(C->AA) {} - /// ScheduleDAGInstrs callback. + /// ScheduleDAGInstrs interface. void schedule(); /// Interface implemented by the selected top-down liveinterval scheduler. @@ -206,7 +238,7 @@ void ScheduleTopDownLive::releaseSuccessors(SUnit *SU) { /// schedule - This is called back from ScheduleDAGInstrs::Run() when it's /// time to do some work. void ScheduleTopDownLive::schedule() { - buildSchedGraph(&Pass->getAnalysis()); + buildSchedGraph(AA); DEBUG(dbgs() << "********** MI Scheduling **********\n"); DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) @@ -236,7 +268,7 @@ void ScheduleTopDownLive::schedule() { ++InsertPos; else { BB->splice(InsertPos, BB, MI); - Pass->LIS->handleMove(MI); + LIS->handleMove(MI); if (Begin == InsertPos) Begin = MI; } @@ -246,90 +278,17 @@ void ScheduleTopDownLive::schedule() { } } -bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) { - // Initialize the context of the pass. - MF = &mf; - MLI = &getAnalysis(); - MDT = &getAnalysis(); - LIS = &getAnalysis(); - TII = MF->getTarget().getInstrInfo(); - - // Select the scheduler, or set the default. - MachineSchedRegistry::ScheduleDAGCtor Ctor = - MachineSchedRegistry::getDefault(); - if (!Ctor) { - Ctor = MachineSchedOpt; - MachineSchedRegistry::setDefault(Ctor); - } - // Instantiate the selected scheduler. - OwningPtr Scheduler(Ctor(this)); - - // Visit all machine basic blocks. - for (MachineFunction::iterator MBB = MF->begin(), MBBEnd = MF->end(); - MBB != MBBEnd; ++MBB) { - - // Break the block into scheduling regions [I, RegionEnd), and schedule each - // region as soon as it is discovered. - unsigned RemainingCount = MBB->size(); - for(MachineBasicBlock::iterator RegionEnd = MBB->end(); - RegionEnd != MBB->begin();) { - Scheduler->startBlock(MBB); - // The next region starts above the previous region. Look backward in the - // instruction stream until we find the nearest boundary. - MachineBasicBlock::iterator I = RegionEnd; - for(;I != MBB->begin(); --I, --RemainingCount) { - if (TII->isSchedulingBoundary(llvm::prior(I), MBB, *MF)) - break; - } - // Notify the scheduler of the region, even if we may skip scheduling - // it. Perhaps it still needs to be bundled. - Scheduler->enterRegion(MBB, I, RegionEnd, RemainingCount); - - // Skip empty scheduling regions (0 or 1 schedulable instructions). - if (I == RegionEnd || I == llvm::prior(RegionEnd)) { - RegionEnd = llvm::prior(RegionEnd); - if (I != RegionEnd) - --RemainingCount; - // Close the current region. Bundle the terminator if needed. - Scheduler->exitRegion(); - continue; - } - DEBUG(dbgs() << "MachineScheduling " << MF->getFunction()->getName() - << ":BB#" << MBB->getNumber() << "\n From: " << *I << " To: "; - if (RegionEnd != MBB->end()) dbgs() << *RegionEnd; - else dbgs() << "End"; - dbgs() << " Remaining: " << RemainingCount << "\n"); - - // Inform ScheduleDAGInstrs of the region being scheduled. It calls back - // to our schedule() method. - Scheduler->schedule(); - Scheduler->exitRegion(); - - // Scheduling has invalidated the current iterator 'I'. Ask the - // scheduler for the top of it's scheduled region. - RegionEnd = Scheduler->begin(); - } - assert(RemainingCount == 0 && "Instruction count mismatch!"); - Scheduler->finishBlock(); - } - return true; -} - -void MachineScheduler::print(raw_ostream &O, const Module* m) const { - // unimplemented -} - //===----------------------------------------------------------------------===// -// Placeholder for extending the machine instruction scheduler. +// 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", -- 2.34.1