forked from OSchip/llvm-project
Define MC data tables for the new scheduling machine model.
llvm-svn: 163933
This commit is contained in:
parent
39cf40a2ae
commit
ac36af470c
|
@ -16,17 +16,102 @@
|
||||||
#define LLVM_MC_MCSCHEDMODEL_H
|
#define LLVM_MC_MCSCHEDMODEL_H
|
||||||
|
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
struct InstrItinerary;
|
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.
|
/// Machine model for scheduling, bundling, and heuristics.
|
||||||
///
|
///
|
||||||
/// The machine model directly provides basic information about the
|
/// The machine model directly provides basic information about the
|
||||||
/// microarchitecture to the scheduler in the form of properties. It also
|
/// microarchitecture to the scheduler in the form of properties. It also
|
||||||
/// optionally refers to scheduler resources tables and itinerary
|
/// optionally refers to scheduler resource tables and itinerary
|
||||||
/// tables. Scheduler resources tables model the latency and cost for each
|
/// tables. Scheduler resource tables model the latency and cost for each
|
||||||
/// instruction type. Itinerary tables are an independant mechanism that
|
/// instruction type. Itinerary tables are an independant mechanism that
|
||||||
/// provides a detailed reservation table describing each cycle of instruction
|
/// provides a detailed reservation table describing each cycle of instruction
|
||||||
/// execution. Subtargets may define any or all of the above categories of data
|
/// execution. Subtargets may define any or all of the above categories of data
|
||||||
|
@ -84,7 +169,12 @@ public:
|
||||||
static const unsigned DefaultMispredictPenalty = 10;
|
static const unsigned DefaultMispredictPenalty = 10;
|
||||||
|
|
||||||
private:
|
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.
|
// Instruction itinerary tables used by InstrItineraryData.
|
||||||
friend class InstrItineraryData;
|
friend class InstrItineraryData;
|
||||||
|
@ -100,13 +190,38 @@ public:
|
||||||
LoadLatency(DefaultLoadLatency),
|
LoadLatency(DefaultLoadLatency),
|
||||||
HighLatency(DefaultHighLatency),
|
HighLatency(DefaultHighLatency),
|
||||||
MispredictPenalty(DefaultMispredictPenalty),
|
MispredictPenalty(DefaultMispredictPenalty),
|
||||||
InstrItineraries(0) {}
|
ProcID(0), InstrItineraries(0) {}
|
||||||
|
|
||||||
// Table-gen driven ctor.
|
// Table-gen driven ctor.
|
||||||
MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned mp,
|
MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned mp,
|
||||||
const InstrItinerary *ii):
|
const InstrItinerary *ii):
|
||||||
IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl),
|
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
|
} // End llvm namespace
|
||||||
|
|
|
@ -30,7 +30,13 @@ class MCSubtargetInfo {
|
||||||
std::string TargetTriple; // Target triple
|
std::string TargetTriple; // Target triple
|
||||||
const SubtargetFeatureKV *ProcFeatures; // Processor feature list
|
const SubtargetFeatureKV *ProcFeatures; // Processor feature list
|
||||||
const SubtargetFeatureKV *ProcDesc; // Processor descriptions
|
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 InstrStage *Stages; // Instruction itinerary stages
|
||||||
const unsigned *OperandCycles; // Itinerary operand cycles
|
const unsigned *OperandCycles; // Itinerary operand cycles
|
||||||
const unsigned *ForwardingPaths; // Forwarding paths
|
const unsigned *ForwardingPaths; // Forwarding paths
|
||||||
|
@ -74,6 +80,41 @@ public:
|
||||||
///
|
///
|
||||||
const MCSchedModel *getSchedModelForCPU(StringRef CPU) const;
|
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.
|
/// getInstrItineraryForCPU - Get scheduling itinerary of a CPU.
|
||||||
///
|
///
|
||||||
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const;
|
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const;
|
||||||
|
|
|
@ -31,7 +31,7 @@ MCSubtargetInfo::InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS,
|
||||||
TargetTriple = TT;
|
TargetTriple = TT;
|
||||||
ProcFeatures = PF;
|
ProcFeatures = PF;
|
||||||
ProcDesc = PD;
|
ProcDesc = PD;
|
||||||
ProcSchedModel = ProcSched;
|
ProcSchedModels = ProcSched;
|
||||||
Stages = IS;
|
Stages = IS;
|
||||||
OperandCycles = OC;
|
OperandCycles = OC;
|
||||||
ForwardingPaths = FP;
|
ForwardingPaths = FP;
|
||||||
|
@ -72,11 +72,11 @@ uint64_t MCSubtargetInfo::ToggleFeature(StringRef FS) {
|
||||||
|
|
||||||
const MCSchedModel *
|
const MCSchedModel *
|
||||||
MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
|
MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
|
||||||
assert(ProcSchedModel && "Processor machine model not available!");
|
assert(ProcSchedModels && "Processor machine model not available!");
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for (size_t i = 1; i < NumProcs; i++) {
|
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");
|
"Processor machine model table is not sorted");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -85,8 +85,8 @@ MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
|
||||||
SubtargetInfoKV KV;
|
SubtargetInfoKV KV;
|
||||||
KV.Key = CPU.data();
|
KV.Key = CPU.data();
|
||||||
const SubtargetInfoKV *Found =
|
const SubtargetInfoKV *Found =
|
||||||
std::lower_bound(ProcSchedModel, ProcSchedModel+NumProcs, KV);
|
std::lower_bound(ProcSchedModels, ProcSchedModels+NumProcs, KV);
|
||||||
if (Found == ProcSchedModel+NumProcs || StringRef(Found->Key) != CPU) {
|
if (Found == ProcSchedModels+NumProcs || StringRef(Found->Key) != CPU) {
|
||||||
errs() << "'" << CPU
|
errs() << "'" << CPU
|
||||||
<< "' is not a recognized processor for this target"
|
<< "' is not a recognized processor for this target"
|
||||||
<< " (ignoring processor)\n";
|
<< " (ignoring processor)\n";
|
||||||
|
|
Loading…
Reference in New Issue