mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-05 13:09:10 +00:00
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:
parent
0303d92b73
commit
72d048b697
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user