Define MC data tables for the new scheduling machine model.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163933 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2012-09-14 20:26:41 +00:00
parent 0303d92b73
commit 72d048b697
3 changed files with 167 additions and 11 deletions

View File

@ -16,17 +16,102 @@
#define LLVM_MC_MCSCHEDMODEL_H
#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace llvm {
struct InstrItinerary;
/// Define a kind of processor resource that will be modeled by the scheduler.
struct MCProcResourceDesc {
#ifndef NDEBUG
const char *Name;
#endif
unsigned Count; // Number of resource of this kind
unsigned SuperIdx; // Index of the resources kind that contains this kind.
bool operator==(const MCProcResourceDesc &Other) const {
return Count == Other.Count && SuperIdx == Other.SuperIdx;
}
};
/// Identify one of the processor resource kinds consumed by a particular
/// scheduling class for the specified number of cycles.
struct MCWriteProcResEntry {
unsigned ProcResourceIdx;
unsigned Cycles;
bool operator==(const MCWriteProcResEntry &Other) const {
return ProcResourceIdx == Other.ProcResourceIdx && Cycles == Other.Cycles;
}
};
/// Specify the latency in cpu cycles for a particular scheduling class and def
/// index. Also identify the WriteResources of this def. When the operand
/// expands to a sequence of writes, this ID is the last write in the sequence.
struct MCWriteLatencyEntry {
unsigned Cycles;
unsigned WriteResourceID;
bool operator==(const MCWriteLatencyEntry &Other) const {
return Cycles == Other.Cycles && WriteResourceID == Other.WriteResourceID;
}
};
/// Specify the number of cycles allowed after instruction issue before a
/// particular use operand reads its registers. This effectively reduces the
/// write's latency. Here we allow negative cycles for corner cases where
/// latency increases. This rule only applies when the entry's WriteResource
/// matches the write's WriteResource.
///
/// MCReadAdvanceEntries are sorted first by operand index (UseIdx), then by
/// WriteResourceIdx.
struct MCReadAdvanceEntry {
unsigned UseIdx;
unsigned WriteResourceID;
int Cycles;
bool operator==(const MCReadAdvanceEntry &Other) const {
return UseIdx == Other.UseIdx && WriteResourceID == Other.WriteResourceID
&& Cycles == Other.Cycles;
}
};
/// Summarize the scheduling resources required for an instruction of a
/// particular scheduling class.
///
/// Defined as an aggregate struct for creating tables with initializer lists.
struct MCSchedClassDesc {
static const unsigned short InvalidNumMicroOps = UINT16_MAX;
static const unsigned short VariantNumMicroOps = UINT16_MAX - 1;
#ifndef NDEBUG
const char* Name;
#endif
unsigned short NumMicroOps;
bool BeginGroup;
bool EndGroup;
unsigned WriteProcResIdx; // First index into WriteProcResTable.
unsigned NumWriteProcResEntries;
unsigned WriteLatencyIdx; // First index into WriteLatencyTable.
unsigned NumWriteLatencyEntries;
unsigned ReadAdvanceIdx; // First index into ReadAdvanceTable.
unsigned NumReadAdvanceEntries;
bool isValid() const {
return NumMicroOps != InvalidNumMicroOps;
}
bool isVariant() const {
return NumMicroOps == VariantNumMicroOps;
}
};
/// Machine model for scheduling, bundling, and heuristics.
///
/// The machine model directly provides basic information about the
/// microarchitecture to the scheduler in the form of properties. It also
/// optionally refers to scheduler resources tables and itinerary
/// tables. Scheduler resources tables model the latency and cost for each
/// optionally refers to scheduler resource tables and itinerary
/// tables. Scheduler resource tables model the latency and cost for each
/// instruction type. Itinerary tables are an independant mechanism that
/// provides a detailed reservation table describing each cycle of instruction
/// execution. Subtargets may define any or all of the above categories of data
@ -84,7 +169,12 @@ public:
static const unsigned DefaultMispredictPenalty = 10;
private:
// TODO: Add a reference to proc resource types and sched resource tables.
unsigned ProcID;
const MCProcResourceDesc *ProcResourceTable;
const MCSchedClassDesc *SchedClassTable;
unsigned NumProcResourceKinds;
unsigned NumSchedClasses;
// Instruction itinerary tables used by InstrItineraryData.
friend class InstrItineraryData;
@ -100,13 +190,38 @@ public:
LoadLatency(DefaultLoadLatency),
HighLatency(DefaultHighLatency),
MispredictPenalty(DefaultMispredictPenalty),
InstrItineraries(0) {}
ProcID(0), InstrItineraries(0) {}
// Table-gen driven ctor.
MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned mp,
const InstrItinerary *ii):
IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl),
MispredictPenalty(mp), InstrItineraries(ii){}
MispredictPenalty(mp), ProcID(0), ProcResourceTable(0),
SchedClassTable(0), InstrItineraries(ii) {}
/// Does this machine model include instruction-level scheduling.
bool hasInstrSchedModel() const {
return SchedClassTable;
}
/// Does this machine model include cycle-to-cycle itineraries.
bool hasInstrItineraries() const {
return InstrItineraries;
}
const MCProcResourceDesc *getProcResource(unsigned ProcResourceIdx) const {
assert(hasInstrSchedModel() && "No scheduling machine model");
assert(ProcResourceIdx < NumProcResourceKinds && "bad proc resource idx");
return &ProcResourceTable[ProcResourceIdx];
}
const MCSchedClassDesc *getSchedClassDesc(unsigned SchedClassIdx) const {
assert(hasInstrSchedModel() && "No scheduling machine model");
assert(SchedClassIdx < NumSchedClasses && "bad scheduling class idx");
return &SchedClassTable[SchedClassIdx];
}
};
} // End llvm namespace

View File

@ -30,7 +30,13 @@ class MCSubtargetInfo {
std::string TargetTriple; // Target triple
const SubtargetFeatureKV *ProcFeatures; // Processor feature list
const SubtargetFeatureKV *ProcDesc; // Processor descriptions
const SubtargetInfoKV *ProcSchedModel; // Scheduler machine model
// Scheduler machine model
const SubtargetInfoKV *ProcSchedModels;
const MCWriteProcResEntry *WriteProcResTable;
const MCWriteLatencyEntry *WriteLatencyTable;
const MCReadAdvanceEntry *ReadAdvanceTable;
const InstrStage *Stages; // Instruction itinerary stages
const unsigned *OperandCycles; // Itinerary operand cycles
const unsigned *ForwardingPaths; // Forwarding paths
@ -74,6 +80,41 @@ public:
///
const MCSchedModel *getSchedModelForCPU(StringRef CPU) const;
/// Return an iterator at the first process resource consumed by the given
/// scheduling class.
const MCWriteProcResEntry *getWriteProcResBegin(
const MCSchedClassDesc *SC) const {
return &WriteProcResTable[SC->WriteProcResIdx];
}
const MCWriteProcResEntry *getWriteProcResEnd(
const MCSchedClassDesc *SC) const {
return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries;
}
const MCWriteLatencyEntry *getWriteLatencyEntry(const MCSchedClassDesc *SC,
unsigned DefIdx) const {
assert(DefIdx < SC->NumWriteLatencyEntries &&
"MachineModel does not specify a WriteResource for DefIdx");
return &WriteLatencyTable[SC->WriteLatencyIdx + DefIdx];
}
int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx,
unsigned WriteResID) const {
for (const MCReadAdvanceEntry *I = &ReadAdvanceTable[SC->ReadAdvanceIdx],
*E = I + SC->NumReadAdvanceEntries; I != E; ++I) {
if (I->UseIdx < UseIdx)
continue;
if (I->UseIdx > UseIdx)
break;
// Find the first WriteResIdx match, which has the highest cycle count.
if (!I->WriteResourceID || I->WriteResourceID == WriteResID) {
return I->Cycles;
}
}
return 0;
}
/// getInstrItineraryForCPU - Get scheduling itinerary of a CPU.
///
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const;

View File

@ -31,7 +31,7 @@ MCSubtargetInfo::InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS,
TargetTriple = TT;
ProcFeatures = PF;
ProcDesc = PD;
ProcSchedModel = ProcSched;
ProcSchedModels = ProcSched;
Stages = IS;
OperandCycles = OC;
ForwardingPaths = FP;
@ -72,11 +72,11 @@ uint64_t MCSubtargetInfo::ToggleFeature(StringRef FS) {
const MCSchedModel *
MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
assert(ProcSchedModel && "Processor machine model not available!");
assert(ProcSchedModels && "Processor machine model not available!");
#ifndef NDEBUG
for (size_t i = 1; i < NumProcs; i++) {
assert(strcmp(ProcSchedModel[i - 1].Key, ProcSchedModel[i].Key) < 0 &&
assert(strcmp(ProcSchedModels[i - 1].Key, ProcSchedModels[i].Key) < 0 &&
"Processor machine model table is not sorted");
}
#endif
@ -85,8 +85,8 @@ MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
SubtargetInfoKV KV;
KV.Key = CPU.data();
const SubtargetInfoKV *Found =
std::lower_bound(ProcSchedModel, ProcSchedModel+NumProcs, KV);
if (Found == ProcSchedModel+NumProcs || StringRef(Found->Key) != CPU) {
std::lower_bound(ProcSchedModels, ProcSchedModels+NumProcs, KV);
if (Found == ProcSchedModels+NumProcs || StringRef(Found->Key) != CPU) {
errs() << "'" << CPU
<< "' is not a recognized processor for this target"
<< " (ignoring processor)\n";