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
This commit is contained in:
Andrew Trick 2012-03-08 01:41:12 +00:00
parent fd03ccdded
commit c174eaf948
2 changed files with 208 additions and 164 deletions

View File

@ -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

View File

@ -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<MachineSchedRegistry::ScheduleDAGCtor, false,
@ -144,115 +101,15 @@ MachineSchedOpt("misched",
cl::init(&createDefaultMachineSched), cl::Hidden,
cl::desc("Machine instruction scheduler to use"));
//===----------------------------------------------------------------------===//
// Machine Instruction Scheduling Common Implementation
//===----------------------------------------------------------------------===//
namespace {
/// ScheduleTopDownLive is an implementation of ScheduleDAGInstrs that schedules
/// machine instructions while updating LiveIntervals.
class ScheduleTopDownLive : public ScheduleDAGInstrs {
protected:
MachineScheduler *Pass;
public:
ScheduleTopDownLive(MachineScheduler *P):
ScheduleDAGInstrs(*P->MF, *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<AliasAnalysis>());
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<SUnit>::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<MachineLoopInfo>();
MDT = &getAnalysis<MachineDominatorTree>();
AA = &getAnalysis<AliasAnalysis>();
LIS = &getAnalysis<LiveIntervals>();
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<SUnit>::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<AliasAnalysis>());
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<SUnit*, std::vector<SUnit*>, 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",