mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-04 11:17:31 +00:00
[MC][TableGen] Add optional libpfm counter names for ProcResUnits.
Summary: Subtargets can define the libpfm counter names that can be used to measure cycles and uops issued on ProcResUnits. This allows making llvm-exegesis available on more targets. Fixes PR36984. Reviewers: gchatelet, RKSimon, andreadb, craig.topper Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D45360 llvm-svn: 329675
This commit is contained in:
parent
c9308fd1bc
commit
221e6ccd99
@ -172,6 +172,18 @@ struct MCExtraProcessorInfo {
|
|||||||
unsigned NumRegisterFiles;
|
unsigned NumRegisterFiles;
|
||||||
const MCRegisterCostEntry *RegisterCostTable;
|
const MCRegisterCostEntry *RegisterCostTable;
|
||||||
unsigned NumRegisterCostEntries;
|
unsigned NumRegisterCostEntries;
|
||||||
|
|
||||||
|
struct PfmCountersInfo {
|
||||||
|
// An optional name of a performance counter that can be used to measure
|
||||||
|
// cycles.
|
||||||
|
const char *CycleCounter;
|
||||||
|
|
||||||
|
// For each MCProcResourceDesc defined by the processor, an optional list of
|
||||||
|
// names of performance counters that can be used to measure the resource
|
||||||
|
// utilization.
|
||||||
|
const char **IssueCounters;
|
||||||
|
};
|
||||||
|
PfmCountersInfo PfmCounters;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Machine model for scheduling, bundling, and heuristics.
|
/// Machine model for scheduling, bundling, and heuristics.
|
||||||
|
@ -182,7 +182,8 @@ class ProcResourceKind;
|
|||||||
//
|
//
|
||||||
// SchedModel ties these units to a processor for any stand-alone defs
|
// SchedModel ties these units to a processor for any stand-alone defs
|
||||||
// of this class.
|
// of this class.
|
||||||
class ProcResourceUnits<ProcResourceKind kind, int num> {
|
class ProcResourceUnits<ProcResourceKind kind, int num,
|
||||||
|
list<string> pfmCounters> {
|
||||||
ProcResourceKind Kind = kind;
|
ProcResourceKind Kind = kind;
|
||||||
int NumUnits = num;
|
int NumUnits = num;
|
||||||
ProcResourceKind Super = ?;
|
ProcResourceKind Super = ?;
|
||||||
@ -197,8 +198,8 @@ def EponymousProcResourceKind : ProcResourceKind;
|
|||||||
|
|
||||||
// Subtargets typically define processor resource kind and number of
|
// Subtargets typically define processor resource kind and number of
|
||||||
// units in one place.
|
// units in one place.
|
||||||
class ProcResource<int num> : ProcResourceKind,
|
class ProcResource<int num, list<string> pfmCounters = []> : ProcResourceKind,
|
||||||
ProcResourceUnits<EponymousProcResourceKind, num>;
|
ProcResourceUnits<EponymousProcResourceKind, num, pfmCounters>;
|
||||||
|
|
||||||
class ProcResGroup<list<ProcResource> resources> : ProcResourceKind {
|
class ProcResGroup<list<ProcResource> resources> : ProcResourceKind {
|
||||||
list<ProcResource> Resources = resources;
|
list<ProcResource> Resources = resources;
|
||||||
@ -476,3 +477,23 @@ class RetireControlUnit<int bufferSize, int retirePerCycle> {
|
|||||||
SchedMachineModel SchedModel = ?;
|
SchedMachineModel SchedModel = ?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow the definition of hardware counters.
|
||||||
|
class PfmCounter {
|
||||||
|
SchedMachineModel SchedModel = ?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each processor can define how to measure cycles by defining a
|
||||||
|
// PfmCycleCounter.
|
||||||
|
class PfmCycleCounter<string counter> : PfmCounter {
|
||||||
|
string Counter = counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each ProcResourceUnits can define how to measure issued uops by defining
|
||||||
|
// a PfmIssueCounter.
|
||||||
|
class PfmIssueCounter<ProcResourceUnits resource, list<string> counters>
|
||||||
|
: PfmCounter{
|
||||||
|
// The resource units on which uops are issued.
|
||||||
|
ProcResourceUnits Resource = resource;
|
||||||
|
// The list of counters that measure issue events.
|
||||||
|
list<string> Counters = counters;
|
||||||
|
}
|
||||||
|
@ -1132,3 +1132,9 @@ def X86 : Target {
|
|||||||
let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter];
|
let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter];
|
||||||
let AllowRegisterRenaming = 1;
|
let AllowRegisterRenaming = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Pfm Counters
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
include "X86PfmCounters.td"
|
||||||
|
71
lib/Target/X86/X86PfmCounters.td
Normal file
71
lib/Target/X86/X86PfmCounters.td
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
//===-- X86PfmCounters.td - X86 Hardware Counters ----------*- tablegen -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This describes the available hardware counters for various subtargets.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
let SchedModel = SandyBridgeModel in {
|
||||||
|
def SBCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||||
|
def SBPort0Counter : PfmIssueCounter<SBPort0, ["uops_dispatched_port:port_0"]>;
|
||||||
|
def SBPort1Counter : PfmIssueCounter<SBPort1, ["uops_dispatched_port:port_1"]>;
|
||||||
|
def SBPort23Counter : PfmIssueCounter<SBPort23,
|
||||||
|
["uops_dispatched_port:port_2",
|
||||||
|
"uops_dispatched_port:port_3"]>;
|
||||||
|
def SBPort4Counter : PfmIssueCounter<SBPort4, ["uops_dispatched_port:port_4"]>;
|
||||||
|
def SBPort5Counter : PfmIssueCounter<SBPort5, ["uops_dispatched_port:port_5"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let SchedModel = HaswellModel in {
|
||||||
|
def HWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||||
|
def HWPort0Counter : PfmIssueCounter<HWPort0, ["uops_dispatched_port:port_0"]>;
|
||||||
|
def HWPort1Counter : PfmIssueCounter<HWPort1, ["uops_dispatched_port:port_1"]>;
|
||||||
|
def HWPort2Counter : PfmIssueCounter<HWPort2, ["uops_dispatched_port:port_2"]>;
|
||||||
|
def HWPort3Counter : PfmIssueCounter<HWPort3, ["uops_dispatched_port:port_3"]>;
|
||||||
|
def HWPort4Counter : PfmIssueCounter<HWPort4, ["uops_dispatched_port:port_4"]>;
|
||||||
|
def HWPort5Counter : PfmIssueCounter<HWPort5, ["uops_dispatched_port:port_5"]>;
|
||||||
|
def HWPort6Counter : PfmIssueCounter<HWPort6, ["uops_dispatched_port:port_6"]>;
|
||||||
|
def HWPort7Counter : PfmIssueCounter<HWPort7, ["uops_dispatched_port:port_7"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let SchedModel = BroadwellModel in {
|
||||||
|
def BWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||||
|
def BWPort0Counter : PfmIssueCounter<BWPort0, ["uops_dispatched_port:port_0"]>;
|
||||||
|
def BWPort1Counter : PfmIssueCounter<BWPort1, ["uops_dispatched_port:port_1"]>;
|
||||||
|
def BWPort2Counter : PfmIssueCounter<BWPort2, ["uops_dispatched_port:port_2"]>;
|
||||||
|
def BWPort3Counter : PfmIssueCounter<BWPort3, ["uops_dispatched_port:port_3"]>;
|
||||||
|
def BWPort4Counter : PfmIssueCounter<BWPort4, ["uops_dispatched_port:port_4"]>;
|
||||||
|
def BWPort5Counter : PfmIssueCounter<BWPort5, ["uops_dispatched_port:port_5"]>;
|
||||||
|
def BWPort6Counter : PfmIssueCounter<BWPort6, ["uops_dispatched_port:port_6"]>;
|
||||||
|
def BWPort7Counter : PfmIssueCounter<BWPort7, ["uops_dispatched_port:port_7"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let SchedModel = SkylakeClientModel in {
|
||||||
|
def SKLCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||||
|
def SKLPort0Counter : PfmIssueCounter<SKLPort0, ["uops_dispatched_port:port_0"]>;
|
||||||
|
def SKLPort1Counter : PfmIssueCounter<SKLPort1, ["uops_dispatched_port:port_1"]>;
|
||||||
|
def SKLPort2Counter : PfmIssueCounter<SKLPort2, ["uops_dispatched_port:port_2"]>;
|
||||||
|
def SKLPort3Counter : PfmIssueCounter<SKLPort3, ["uops_dispatched_port:port_3"]>;
|
||||||
|
def SKLPort4Counter : PfmIssueCounter<SKLPort4, ["uops_dispatched_port:port_4"]>;
|
||||||
|
def SKLPort5Counter : PfmIssueCounter<SKLPort5, ["uops_dispatched_port:port_5"]>;
|
||||||
|
def SKLPort6Counter : PfmIssueCounter<SKLPort6, ["uops_dispatched_port:port_6"]>;
|
||||||
|
def SKLPort7Counter : PfmIssueCounter<SKLPort7, ["uops_dispatched_port:port_7"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let SchedModel = SkylakeServerModel in {
|
||||||
|
def SKXCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||||
|
def SKXPort0Counter : PfmIssueCounter<SKXPort0, ["uops_dispatched_port:port_0"]>;
|
||||||
|
def SKXPort1Counter : PfmIssueCounter<SKXPort1, ["uops_dispatched_port:port_1"]>;
|
||||||
|
def SKXPort2Counter : PfmIssueCounter<SKXPort2, ["uops_dispatched_port:port_2"]>;
|
||||||
|
def SKXPort3Counter : PfmIssueCounter<SKXPort3, ["uops_dispatched_port:port_3"]>;
|
||||||
|
def SKXPort4Counter : PfmIssueCounter<SKXPort4, ["uops_dispatched_port:port_4"]>;
|
||||||
|
def SKXPort5Counter : PfmIssueCounter<SKXPort5, ["uops_dispatched_port:port_5"]>;
|
||||||
|
def SKXPort6Counter : PfmIssueCounter<SKXPort6, ["uops_dispatched_port:port_6"]>;
|
||||||
|
def SKXPort7Counter : PfmIssueCounter<SKXPort7, ["uops_dispatched_port:port_7"]>;
|
||||||
|
}
|
@ -76,10 +76,15 @@ LatencyBenchmarkRunner::runMeasurements(const LLVMState &State,
|
|||||||
// measure several times and take the minimum value.
|
// measure several times and take the minimum value.
|
||||||
constexpr const int NumMeasurements = 30;
|
constexpr const int NumMeasurements = 30;
|
||||||
int64_t MinLatency = std::numeric_limits<int64_t>::max();
|
int64_t MinLatency = std::numeric_limits<int64_t>::max();
|
||||||
// FIXME: Read the perf event from the MCSchedModel (see PR36984).
|
const char *CounterName = State.getSubtargetInfo()
|
||||||
const pfm::PerfEvent CyclesPerfEvent("UNHALTED_CORE_CYCLES");
|
.getSchedModel()
|
||||||
|
.getExtraProcessorInfo()
|
||||||
|
.PfmCounters.CycleCounter;
|
||||||
|
if (!CounterName)
|
||||||
|
llvm::report_fatal_error("sched model does not define a cycle counter");
|
||||||
|
const pfm::PerfEvent CyclesPerfEvent(CounterName);
|
||||||
if (!CyclesPerfEvent.valid())
|
if (!CyclesPerfEvent.valid())
|
||||||
llvm::report_fatal_error("invalid perf event 'UNHALTED_CORE_CYCLES'");
|
llvm::report_fatal_error("invalid perf event");
|
||||||
for (size_t I = 0; I < NumMeasurements; ++I) {
|
for (size_t I = 0; I < NumMeasurements; ++I) {
|
||||||
pfm::Counter Counter(CyclesPerfEvent);
|
pfm::Counter Counter(CyclesPerfEvent);
|
||||||
Counter.start();
|
Counter.start();
|
||||||
|
@ -38,43 +38,6 @@ static llvm::Error makeError(llvm::Twine Msg) {
|
|||||||
llvm::inconvertibleErrorCode());
|
llvm::inconvertibleErrorCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Read the counter names from the ProcResourceUnits when PR36984 is
|
|
||||||
// fixed.
|
|
||||||
static const std::string *getEventNameFromProcResName(const char *ProcResName) {
|
|
||||||
static const std::unordered_map<std::string, std::string> Entries = {
|
|
||||||
{"SBPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
|
||||||
{"SBPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
|
||||||
{"SBPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
|
||||||
{"SBPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
|
||||||
{"HWPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
|
||||||
{"HWPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
|
||||||
{"HWPort2", "UOPS_DISPATCHED_PORT:PORT_2"},
|
|
||||||
{"HWPort3", "UOPS_DISPATCHED_PORT:PORT_3"},
|
|
||||||
{"HWPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
|
||||||
{"HWPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
|
||||||
{"HWPort6", "UOPS_DISPATCHED_PORT:PORT_6"},
|
|
||||||
{"HWPort7", "UOPS_DISPATCHED_PORT:PORT_7"},
|
|
||||||
{"SKLPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
|
||||||
{"SKLPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
|
||||||
{"SKLPort2", "UOPS_DISPATCHED_PORT:PORT_2"},
|
|
||||||
{"SKLPort3", "UOPS_DISPATCHED_PORT:PORT_3"},
|
|
||||||
{"SKLPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
|
||||||
{"SKLPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
|
||||||
{"SKLPort6", "UOPS_DISPATCHED_PORT:PORT_6"},
|
|
||||||
{"SKXPort7", "UOPS_DISPATCHED_PORT:PORT_7"},
|
|
||||||
{"SKXPort0", "UOPS_DISPATCHED_PORT:PORT_0"},
|
|
||||||
{"SKXPort1", "UOPS_DISPATCHED_PORT:PORT_1"},
|
|
||||||
{"SKXPort2", "UOPS_DISPATCHED_PORT:PORT_2"},
|
|
||||||
{"SKXPort3", "UOPS_DISPATCHED_PORT:PORT_3"},
|
|
||||||
{"SKXPort4", "UOPS_DISPATCHED_PORT:PORT_4"},
|
|
||||||
{"SKXPort5", "UOPS_DISPATCHED_PORT:PORT_5"},
|
|
||||||
{"SKXPort6", "UOPS_DISPATCHED_PORT:PORT_6"},
|
|
||||||
{"SKXPort7", "UOPS_DISPATCHED_PORT:PORT_7"},
|
|
||||||
};
|
|
||||||
const auto It = Entries.find(ProcResName);
|
|
||||||
return It == Entries.end() ? nullptr : &It->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<llvm::MCInst> generateIndependentAssignments(
|
static std::vector<llvm::MCInst> generateIndependentAssignments(
|
||||||
const LLVMState &State, const llvm::MCInstrDesc &InstrDesc,
|
const LLVMState &State, const llvm::MCInstrDesc &InstrDesc,
|
||||||
llvm::SmallVector<Variable, 8> Vars, int MaxAssignments) {
|
llvm::SmallVector<Variable, 8> Vars, int MaxAssignments) {
|
||||||
@ -228,19 +191,19 @@ UopsBenchmarkRunner::runMeasurements(const LLVMState &State,
|
|||||||
std::vector<BenchmarkMeasure> Result;
|
std::vector<BenchmarkMeasure> Result;
|
||||||
for (unsigned ProcResIdx = 1;
|
for (unsigned ProcResIdx = 1;
|
||||||
ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
|
ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
|
||||||
const llvm::MCProcResourceDesc &ProcRes =
|
const char *const PfmCounters = SchedModel.getExtraProcessorInfo()
|
||||||
*SchedModel.getProcResource(ProcResIdx);
|
.PfmCounters.IssueCounters[ProcResIdx];
|
||||||
const std::string *const EventName =
|
if (!PfmCounters)
|
||||||
getEventNameFromProcResName(ProcRes.Name);
|
|
||||||
if (!EventName)
|
|
||||||
continue;
|
continue;
|
||||||
pfm::Counter Counter{pfm::PerfEvent(*EventName)};
|
// FIXME: Sum results when there are several counters for a single ProcRes
|
||||||
|
// (e.g. P23 on SandyBridge).
|
||||||
|
pfm::Counter Counter{pfm::PerfEvent(PfmCounters)};
|
||||||
Counter.start();
|
Counter.start();
|
||||||
Function();
|
Function();
|
||||||
Counter.stop();
|
Counter.stop();
|
||||||
Result.push_back({llvm::itostr(ProcResIdx),
|
Result.push_back({llvm::itostr(ProcResIdx),
|
||||||
static_cast<double>(Counter.read()) / NumRepetitions,
|
static_cast<double>(Counter.read()) / NumRepetitions,
|
||||||
ProcRes.Name});
|
SchedModel.getProcResource(ProcResIdx)->Name});
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
@ -239,6 +239,11 @@ void CodeGenSchedModels::collectOptionalProcessorInfo() {
|
|||||||
|
|
||||||
// Collect processor RetireControlUnit descriptors if available.
|
// Collect processor RetireControlUnit descriptors if available.
|
||||||
collectRetireControlUnits();
|
collectRetireControlUnits();
|
||||||
|
|
||||||
|
// Find pfm counter definitions for each processor.
|
||||||
|
collectPfmCounters();
|
||||||
|
|
||||||
|
checkCompleteness();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gather all processor models.
|
/// Gather all processor models.
|
||||||
@ -1537,6 +1542,23 @@ void CodeGenSchedModels::collectRegisterFiles() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect all the RegisterFile definitions available in this target.
|
||||||
|
void CodeGenSchedModels::collectPfmCounters() {
|
||||||
|
for (Record *Def : Records.getAllDerivedDefinitions("PfmIssueCounter")) {
|
||||||
|
CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
|
||||||
|
PM.PfmIssueCounterDefs.emplace_back(Def);
|
||||||
|
}
|
||||||
|
for (Record *Def : Records.getAllDerivedDefinitions("PfmCycleCounter")) {
|
||||||
|
CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
|
||||||
|
if (PM.PfmCycleCounterDef) {
|
||||||
|
PrintFatalError(Def->getLoc(),
|
||||||
|
"multiple cycle counters for " +
|
||||||
|
Def->getValueAsDef("SchedModel")->getName());
|
||||||
|
}
|
||||||
|
PM.PfmCycleCounterDef = Def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect and sort WriteRes, ReadAdvance, and ProcResources.
|
// Collect and sort WriteRes, ReadAdvance, and ProcResources.
|
||||||
void CodeGenSchedModels::collectProcResources() {
|
void CodeGenSchedModels::collectProcResources() {
|
||||||
ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits");
|
ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits");
|
||||||
|
@ -238,6 +238,10 @@ struct CodeGenProcModel {
|
|||||||
// Optional Retire Control Unit definition.
|
// Optional Retire Control Unit definition.
|
||||||
Record *RetireControlUnit;
|
Record *RetireControlUnit;
|
||||||
|
|
||||||
|
// List of PfmCounters.
|
||||||
|
RecVec PfmIssueCounterDefs;
|
||||||
|
Record *PfmCycleCounterDef = nullptr;
|
||||||
|
|
||||||
CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
|
CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
|
||||||
Record *IDef) :
|
Record *IDef) :
|
||||||
Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
|
Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
|
||||||
@ -252,7 +256,9 @@ struct CodeGenProcModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool hasExtraProcessorInfo() const {
|
bool hasExtraProcessorInfo() const {
|
||||||
return RetireControlUnit || !RegisterFiles.empty();
|
return RetireControlUnit || !RegisterFiles.empty() ||
|
||||||
|
!PfmIssueCounterDefs.empty() ||
|
||||||
|
PfmCycleCounterDef != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getProcResourceIdx(Record *PRDef) const;
|
unsigned getProcResourceIdx(Record *PRDef) const;
|
||||||
@ -444,6 +450,8 @@ private:
|
|||||||
|
|
||||||
void collectRegisterFiles();
|
void collectRegisterFiles();
|
||||||
|
|
||||||
|
void collectPfmCounters();
|
||||||
|
|
||||||
void collectOptionalProcessorInfo();
|
void collectOptionalProcessorInfo();
|
||||||
|
|
||||||
std::string createSchedClassName(Record *ItinClassDef,
|
std::string createSchedClassName(Record *ItinClassDef,
|
||||||
|
@ -635,7 +635,7 @@ static void EmitRegisterFileInfo(const CodeGenProcModel &ProcModel,
|
|||||||
OS << ProcModel.ModelName << "RegisterCosts,\n ";
|
OS << ProcModel.ModelName << "RegisterCosts,\n ";
|
||||||
else
|
else
|
||||||
OS << "nullptr,\n ";
|
OS << "nullptr,\n ";
|
||||||
OS << NumCostEntries << " // Number of register cost entries.\n";
|
OS << NumCostEntries << ", // Number of register cost entries.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
@ -686,6 +686,57 @@ SubtargetEmitter::EmitRegisterFileTables(const CodeGenProcModel &ProcModel,
|
|||||||
|
|
||||||
return CostTblIndex;
|
return CostTblIndex;
|
||||||
}
|
}
|
||||||
|
static bool EmitPfmIssueCountersTable(const CodeGenProcModel &ProcModel,
|
||||||
|
raw_ostream &OS) {
|
||||||
|
std::vector<const Record *> CounterDefs(ProcModel.ProcResourceDefs.size());
|
||||||
|
bool HasCounters = false;
|
||||||
|
for (const Record *CounterDef : ProcModel.PfmIssueCounterDefs) {
|
||||||
|
const Record *&CD = CounterDefs[ProcModel.getProcResourceIdx(
|
||||||
|
CounterDef->getValueAsDef("Resource"))];
|
||||||
|
if (CD) {
|
||||||
|
PrintFatalError(CounterDef->getLoc(),
|
||||||
|
"multiple issue counters for " +
|
||||||
|
CounterDef->getValueAsDef("Resource")->getName());
|
||||||
|
}
|
||||||
|
CD = CounterDef;
|
||||||
|
HasCounters = true;
|
||||||
|
}
|
||||||
|
if (!HasCounters) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OS << "\nstatic const char* " << ProcModel.ModelName
|
||||||
|
<< "PfmIssueCounters[] = {\n";
|
||||||
|
for (const Record *CounterDef : CounterDefs) {
|
||||||
|
if (CounterDef) {
|
||||||
|
const auto PfmCounters = CounterDef->getValueAsListOfStrings("Counters");
|
||||||
|
if (PfmCounters.empty())
|
||||||
|
PrintFatalError(CounterDef->getLoc(), "empty counter list");
|
||||||
|
for (const StringRef CounterName : PfmCounters)
|
||||||
|
OS << " \"" << CounterName << ",\"";
|
||||||
|
OS << ", //" << CounterDef->getValueAsDef("Resource")->getName() << "\n";
|
||||||
|
} else {
|
||||||
|
OS << " nullptr,\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OS << "};\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EmitPfmCounters(const CodeGenProcModel &ProcModel,
|
||||||
|
const bool HasPfmIssueCounters, raw_ostream &OS) {
|
||||||
|
// Emit the cycle counter.
|
||||||
|
if (ProcModel.PfmCycleCounterDef)
|
||||||
|
OS << " \"" << ProcModel.PfmCycleCounterDef->getValueAsString("Counter")
|
||||||
|
<< "\", // Cycle counter.\n";
|
||||||
|
else
|
||||||
|
OS << " nullptr, // No cycle counter.\n";
|
||||||
|
|
||||||
|
// Emit a reference to issue counters table.
|
||||||
|
if (HasPfmIssueCounters)
|
||||||
|
OS << " " << ProcModel.ModelName << "PfmIssueCounters\n";
|
||||||
|
else
|
||||||
|
OS << " nullptr, // No issue counters.\n";
|
||||||
|
}
|
||||||
|
|
||||||
void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
||||||
raw_ostream &OS) {
|
raw_ostream &OS) {
|
||||||
@ -693,6 +744,9 @@ void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
|||||||
// defined register file), and a table of register costs.
|
// defined register file), and a table of register costs.
|
||||||
unsigned NumCostEntries = EmitRegisterFileTables(ProcModel, OS);
|
unsigned NumCostEntries = EmitRegisterFileTables(ProcModel, OS);
|
||||||
|
|
||||||
|
// Generate a table of ProcRes counter names.
|
||||||
|
const bool HasPfmIssueCounters = EmitPfmIssueCountersTable(ProcModel, OS);
|
||||||
|
|
||||||
// Now generate a table for the extra processor info.
|
// Now generate a table for the extra processor info.
|
||||||
OS << "\nstatic const llvm::MCExtraProcessorInfo " << ProcModel.ModelName
|
OS << "\nstatic const llvm::MCExtraProcessorInfo " << ProcModel.ModelName
|
||||||
<< "ExtraInfo = {\n ";
|
<< "ExtraInfo = {\n ";
|
||||||
@ -705,6 +759,8 @@ void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
|||||||
EmitRegisterFileInfo(ProcModel, ProcModel.RegisterFiles.size(),
|
EmitRegisterFileInfo(ProcModel, ProcModel.RegisterFiles.size(),
|
||||||
NumCostEntries, OS);
|
NumCostEntries, OS);
|
||||||
|
|
||||||
|
EmitPfmCounters(ProcModel, HasPfmIssueCounters, OS);
|
||||||
|
|
||||||
OS << "};\n";
|
OS << "};\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1308,7 +1364,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
|
|||||||
else
|
else
|
||||||
OS << " nullptr, // No Itinerary\n";
|
OS << " nullptr, // No Itinerary\n";
|
||||||
if (PM.hasExtraProcessorInfo())
|
if (PM.hasExtraProcessorInfo())
|
||||||
OS << " &" << PM.ModelName << "ExtraInfo\n";
|
OS << " &" << PM.ModelName << "ExtraInfo,\n";
|
||||||
else
|
else
|
||||||
OS << " nullptr // No extra processor descriptor\n";
|
OS << " nullptr // No extra processor descriptor\n";
|
||||||
OS << "};\n";
|
OS << "};\n";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user