Introducing plugable register allocators and instruction schedulers.

llvm-svn: 29434
This commit is contained in:
Jim Laskey 2006-08-01 14:21:23 +00:00
parent 95035cf001
commit 95eda5b1f3
14 changed files with 138 additions and 224 deletions

View File

@ -221,29 +221,35 @@ namespace llvm {
std::map<SDNode*, unsigned> &VRBaseMap);
};
ScheduleDAG *createBFS_DAGScheduler(SelectionDAG &DAG, MachineBasicBlock *BB);
/// createBFS_DAGScheduler - This creates a simple breadth first instruction
/// scheduler.
ScheduleDAG *createBFS_DAGScheduler(SelectionDAG *DAG, MachineBasicBlock *BB);
/// createSimpleDAGScheduler - This creates a simple two pass instruction
/// scheduler.
ScheduleDAG* createSimpleDAGScheduler(bool NoItins, SelectionDAG &DAG,
/// scheduler using instruction itinerary.
ScheduleDAG* createSimpleDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB);
/// createNoItinsDAGScheduler - This creates a simple two pass instruction
/// scheduler without using instruction itinerary.
ScheduleDAG* createNoItinsDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB);
/// createBURRListDAGScheduler - This creates a bottom up register usage
/// reduction list scheduler.
ScheduleDAG* createBURRListDAGScheduler(SelectionDAG &DAG,
ScheduleDAG* createBURRListDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB);
/// createTDRRListDAGScheduler - This creates a top down register usage
/// reduction list scheduler.
ScheduleDAG* createTDRRListDAGScheduler(SelectionDAG &DAG,
ScheduleDAG* createTDRRListDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB);
/// createTDListDAGScheduler - This creates a top-down list scheduler with
/// the specified hazard recognizer. This takes ownership of the hazard
/// recognizer and deletes it when done.
ScheduleDAG* createTDListDAGScheduler(SelectionDAG &DAG,
MachineBasicBlock *BB,
HazardRecognizer *HR);
/// a hazard recognizer.
ScheduleDAG* createTDListDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB);
}
#endif

View File

@ -67,10 +67,6 @@ public:
/// folded during instruction selection?
virtual bool CanBeFoldedBy(SDNode *N, SDNode *U) { return true; }
/// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer
/// to use for this target when scheduling the DAG.
virtual HazardRecognizer *CreateTargetHazardRecognizer();
/// CaseBlock - This structure is used to communicate between SDLowering and
/// SDISel for the code generation of additional basic blocks needed by multi-
/// case switch statements.

View File

@ -369,75 +369,6 @@ struct PassRegistrationListener {
};
//===---------------------------------------------------------------------===//
///
/// RegisterRegAlloc class - Track the registration of register allocators.
///
class RegisterRegAlloc {
public:
typedef FunctionPass *(*FunctionPassCtor)();
private:
static RegisterRegAlloc *List; // Linked list of register allocators.
RegisterRegAlloc *Next; // Next allocation scheme in list.
const char *Name; // Name of register allocator.
const char *Description; // Description string.
FunctionPassCtor Ctor; // Function to construct register
// allocator pass.
public:
RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C)
: Name(N)
, Description(D)
, Ctor(C) {
Add();
}
~RegisterRegAlloc() {
Remove();
}
// Accessors
const char *getName() const { return Name; }
const char *getDescription() const { return Description; }
FunctionPassCtor getCtor() const { return Ctor; }
/// Add - Adds a register allocator to the registration list.
///
void Add() {
Next = List;
List = this;
}
/// Remove - Removes a register allocator from the registration list.
///
void Remove() {
for (RegisterRegAlloc **RA = &List; *RA; RA = &(*RA)->Next) {
if (*RA == this) {
*RA = Next;
break;
}
}
}
/// Find - Finds a register allocator in registration list.
///
static FunctionPassCtor Find(const char *N);
#ifndef NDEBUG
static void print();
#endif
};
} // End llvm namespace
#endif

View File

@ -110,7 +110,7 @@ namespace {
(void) llvm::createRSProfilingPass();
(void) llvm::createIndMemRemPass();
}
} ForcePassLinking;
} ForcePassLinking; // Force link by creating a global definition.
}
#endif

View File

@ -12,74 +12,31 @@
//
//===---------------------------------------------------------------------===//
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include <iostream>
using namespace llvm;
namespace {
enum RegAllocName { simple, local, linearscan };
static cl::opt<RegAllocName>
RegAlloc(
"regalloc",
cl::desc("Register allocator to use: (default = linearscan)"),
cl::Prefix,
cl::values(
clEnumVal(simple, " simple register allocator"),
clEnumVal(local, " local register allocator"),
clEnumVal(linearscan, " linear scan register allocator"),
clEnumValEnd),
cl::init(linearscan));
cl::opt<const char *, false, RegisterPassParser<RegisterRegAlloc> >
RegAlloc("regalloc",
cl::init("linearscan"),
cl::desc("Register allocator to use: (default = linearscan)"));
}
RegisterRegAlloc *RegisterRegAlloc::List = NULL;
/// Find - Finds a register allocator in registration list.
///
RegisterRegAlloc::FunctionPassCtor RegisterRegAlloc::Find(const char *N) {
for (RegisterRegAlloc *RA = List; RA; RA = RA->Next) {
if (strcmp(N, RA->Name) == 0) return RA->Ctor;
}
return NULL;
}
#ifndef NDEBUG
void RegisterRegAlloc::print() {
for (RegisterRegAlloc *RA = List; RA; RA = RA->Next) {
std::cerr << "RegAlloc:" << RA->Name << "\n";
}
}
#endif
static RegisterRegAlloc
simpleRegAlloc("simple", " simple register allocator",
createSimpleRegisterAllocator);
static RegisterRegAlloc
localRegAlloc("local", " local register allocator",
createLocalRegisterAllocator);
static RegisterRegAlloc
linearscanRegAlloc("linearscan", "linear scan register allocator",
createLinearScanRegisterAllocator);
FunctionPass *llvm::createRegisterAllocator() {
const char *Names[] = {"simple", "local", "linearscan"};
const char *DefltName = "linearscan";
RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getCache();
if (!Ctor) {
Ctor = RegisterRegAlloc::FindCtor(RegAlloc);
assert(Ctor && "No register allocator found");
if (!Ctor) Ctor = RegisterRegAlloc::FirstCtor();
RegisterRegAlloc::setCache(Ctor);
}
RegisterRegAlloc::FunctionPassCtor Ctor =
RegisterRegAlloc::Find(Names[RegAlloc]);
if (!Ctor) Ctor = RegisterRegAlloc::Find(DefltName);
assert(Ctor && "No register allocator found");
return Ctor();
}

View File

@ -18,6 +18,7 @@
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
@ -42,6 +43,10 @@ namespace {
static Statistic<> NumBacktracks
("regalloc", "Number of times we had to backtrack");
static RegisterRegAlloc
linearscanRegAlloc("linearscan", " linear scan register allocator",
createLinearScanRegisterAllocator);
static unsigned numIterations = 0;
static unsigned numIntervals = 0;

View File

@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
@ -35,6 +36,12 @@ namespace {
static Statistic<> NumLoads ("ra-local", "Number of loads added");
static Statistic<> NumFolded("ra-local", "Number of loads/stores folded "
"into instructions");
static RegisterRegAlloc
localRegAlloc("local", " local register allocator",
createLocalRegisterAllocator);
class VISIBILITY_HIDDEN RA : public MachineFunctionPass {
const TargetMachine *TM;
MachineFunction *MF;

View File

@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
@ -33,6 +34,10 @@ namespace {
static Statistic<> NumStores("ra-simple", "Number of stores added");
static Statistic<> NumLoads ("ra-simple", "Number of loads added");
static RegisterRegAlloc
simpleRegAlloc("simple", " simple register allocator",
createSimpleRegisterAllocator);
class VISIBILITY_HIDDEN RegAllocSimple : public MachineFunctionPass {
MachineFunction *MF;
const TargetMachine *TM;

View File

@ -19,6 +19,7 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sched"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
@ -38,6 +39,10 @@ namespace {
static Statistic<> NumStalls("scheduler", "Number of pipeline stalls");
}
static RegisterScheduler
tdListDAGScheduler("list-td", " Top-down list scheduler",
createTDListDAGScheduler);
namespace {
//===----------------------------------------------------------------------===//
/// ScheduleDAGList - The actual list scheduler implementation. This supports
@ -511,12 +516,12 @@ void LatencyPriorityQueue::AdjustPriorityOfUnscheduledPreds(SUnit *SU) {
// Public Constructor Functions
//===----------------------------------------------------------------------===//
/// createTDListDAGScheduler - This creates a top-down list scheduler with the
/// specified hazard recognizer.
ScheduleDAG* llvm::createTDListDAGScheduler(SelectionDAG &DAG,
MachineBasicBlock *BB,
HazardRecognizer *HR) {
return new ScheduleDAGList(DAG, BB, DAG.getTarget(),
/// createTDListDAGScheduler - This creates a top-down list scheduler with a
/// new hazard recognizer. This scheduler takes ownership of the hazard
/// recognizer and deletes it when done.
ScheduleDAG* llvm::createTDListDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGList(*DAG, BB, DAG->getTarget(),
new LatencyPriorityQueue(),
HR);
new HazardRecognizer());
}

View File

@ -16,6 +16,7 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sched"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
@ -31,6 +32,15 @@
#include "llvm/Support/CommandLine.h"
using namespace llvm;
static RegisterScheduler
burrListDAGScheduler("list-burr",
" Bottom-up register reduction list scheduling",
createBURRListDAGScheduler);
static RegisterScheduler
tdrListrDAGScheduler("list-tdrr",
" Top-down register reduction list scheduling",
createTDRRListDAGScheduler);
namespace {
//===----------------------------------------------------------------------===//
/// ScheduleDAGRRList - The actual register reduction list scheduler
@ -876,15 +886,15 @@ void TDRegReductionPriorityQueue<SF>::CalculatePriorities() {
// Public Constructor Functions
//===----------------------------------------------------------------------===//
llvm::ScheduleDAG* llvm::createBURRListDAGScheduler(SelectionDAG &DAG,
llvm::ScheduleDAG* llvm::createBURRListDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGRRList(DAG, BB, DAG.getTarget(), true,
return new ScheduleDAGRRList(*DAG, BB, DAG->getTarget(), true,
new BURegReductionPriorityQueue<bu_ls_rr_sort>());
}
llvm::ScheduleDAG* llvm::createTDRRListDAGScheduler(SelectionDAG &DAG,
llvm::ScheduleDAG* llvm::createTDRRListDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGRRList(DAG, BB, DAG.getTarget(), false,
return new ScheduleDAGRRList(*DAG, BB, DAG->getTarget(), false,
new TDRegReductionPriorityQueue<td_ls_rr_sort>());
}

View File

@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sched"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetData.h"
@ -25,7 +26,23 @@
#include <iostream>
using namespace llvm;
namespace {
static RegisterScheduler
bfsDAGScheduler("none", " No scheduling: breadth first sequencing",
createBFS_DAGScheduler);
static RegisterScheduler
simpleDAGScheduler("simple",
" Simple two pass scheduling: minimize critical path "
"and maximize processor utilization",
createSimpleDAGScheduler);
static RegisterScheduler
noitinDAGScheduler("simple-noitin",
" Simple two pass scheduling: Same as simple "
"except using generic latency",
createNoItinsDAGScheduler);
class NodeInfo;
typedef NodeInfo *NodeInfoPtr;
typedef std::vector<NodeInfoPtr> NIVector;
@ -1102,14 +1119,22 @@ void ScheduleDAGSimple::Schedule() {
/// createSimpleDAGScheduler - This creates a simple two pass instruction
/// scheduler.
llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(bool NoItins,
SelectionDAG &DAG,
/// scheduler using instruction itinerary.
llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGSimple(false, NoItins, DAG, BB, DAG.getTarget());
return new ScheduleDAGSimple(false, false, *DAG, BB, DAG->getTarget());
}
llvm::ScheduleDAG* llvm::createBFS_DAGScheduler(SelectionDAG &DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGSimple(true, false, DAG, BB, DAG.getTarget());
/// createNoItinsDAGScheduler - This creates a simple two pass instruction
/// scheduler without using instruction itinerary.
llvm::ScheduleDAG* llvm::createNoItinsDAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGSimple(false, true, *DAG, BB, DAG->getTarget());
}
/// createBFS_DAGScheduler - This creates a simple breadth first instruction
/// scheduler.
llvm::ScheduleDAG* llvm::createBFS_DAGScheduler(SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGSimple(true, false, *DAG, BB, DAG->getTarget());
}

View File

@ -29,6 +29,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachinePassRegistry.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
@ -60,41 +61,14 @@ ViewSchedDAGs("view-sched-dags", cl::Hidden,
static const bool ViewISelDAGs = 0, ViewSchedDAGs = 0;
#endif
// Scheduling heuristics
enum SchedHeuristics {
defaultScheduling, // Let the target specify its preference.
noScheduling, // No scheduling, emit breadth first sequence.
simpleScheduling, // Two pass, min. critical path, max. utilization.
simpleNoItinScheduling, // Same as above exact using generic latency.
listSchedulingBURR, // Bottom-up reg reduction list scheduling.
listSchedulingTDRR, // Top-down reg reduction list scheduling.
listSchedulingTD // Top-down list scheduler.
};
namespace {
cl::opt<SchedHeuristics>
ISHeuristic(
"sched",
cl::desc("Choose scheduling style"),
cl::init(defaultScheduling),
cl::values(
clEnumValN(defaultScheduling, "default",
"Target preferred scheduling style"),
clEnumValN(noScheduling, "none",
"No scheduling: breadth first sequencing"),
clEnumValN(simpleScheduling, "simple",
"Simple two pass scheduling: minimize critical path "
"and maximize processor utilization"),
clEnumValN(simpleNoItinScheduling, "simple-noitin",
"Simple two pass scheduling: Same as simple "
"except using generic latency"),
clEnumValN(listSchedulingBURR, "list-burr",
"Bottom-up register reduction list scheduling"),
clEnumValN(listSchedulingTDRR, "list-tdrr",
"Top-down register reduction list scheduling"),
clEnumValN(listSchedulingTD, "list-td",
"Top-down list scheduler"),
clEnumValEnd));
cl::opt<const char *, false, RegisterPassParser<RegisterScheduler> >
ISHeuristic("sched",
cl::init("default"),
cl::desc("Instruction schedulers available:"));
RegisterScheduler
defaultListDAGScheduler("default", " Best scheduler for the target", NULL);
} // namespace
namespace {
@ -3629,50 +3603,41 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
}
}
//===----------------------------------------------------------------------===//
/// ScheduleAndEmitDAG - Pick a safe ordering and emit instructions for each
/// target node in the graph.
void SelectionDAGISel::ScheduleAndEmitDAG(SelectionDAG &DAG) {
if (ViewSchedDAGs) DAG.viewGraph();
ScheduleDAG *SL = NULL;
switch (ISHeuristic) {
default: assert(0 && "Unrecognized scheduling heuristic");
case defaultScheduling:
if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency)
SL = createTDListDAGScheduler(DAG, BB, CreateTargetHazardRecognizer());
else {
assert(TLI.getSchedulingPreference() ==
static RegisterScheduler::FunctionPassCtor Ctor =
RegisterScheduler::getCache();
if (!Ctor) {
if (std::string("default") == std::string(ISHeuristic)) {
if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency)
Ctor = RegisterScheduler::FindCtor("list-td");
else {
assert(TLI.getSchedulingPreference() ==
TargetLowering::SchedulingForRegPressure && "Unknown sched type!");
SL = createBURRListDAGScheduler(DAG, BB);
Ctor = RegisterScheduler::FindCtor("list-burr");
}
assert(Ctor && "Default instruction scheduler not present");
if (!Ctor) Ctor = RegisterScheduler::FindCtor("none");
} else {
Ctor = RegisterScheduler::FindCtor(ISHeuristic);
}
break;
case noScheduling:
SL = createBFS_DAGScheduler(DAG, BB);
break;
case simpleScheduling:
SL = createSimpleDAGScheduler(false, DAG, BB);
break;
case simpleNoItinScheduling:
SL = createSimpleDAGScheduler(true, DAG, BB);
break;
case listSchedulingBURR:
SL = createBURRListDAGScheduler(DAG, BB);
break;
case listSchedulingTDRR:
SL = createTDRRListDAGScheduler(DAG, BB);
break;
case listSchedulingTD:
SL = createTDListDAGScheduler(DAG, BB, CreateTargetHazardRecognizer());
break;
RegisterScheduler::setCache(Ctor);
}
assert(Ctor && "No instruction scheduler found");
ScheduleDAG *SL = Ctor(&DAG, BB);
BB = SL->Run();
delete SL;
}
HazardRecognizer *SelectionDAGISel::CreateTargetHazardRecognizer() {
return new HazardRecognizer();
}
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
/// by tblgen. Others should not call it.

View File

@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Bytecode/Reader.h"
#include "llvm/Codegen/LinkAllCodegenComponents.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"

View File

@ -17,6 +17,7 @@
#include "llvm/ModuleProvider.h"
#include "llvm/Type.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Codegen/LinkAllCodegenComponents.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/GenericValue.h"