mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[MCSched] Bind PFM Counters to the CPUs instead of the SchedModel.
Summary: The pfm counters are now in the ExegesisTarget rather than the MCSchedModel (PR39165). This also compresses the pfm counter tables (PR37068). Reviewers: RKSimon, gchatelet Subscribers: mgrang, llvm-commits Differential Revision: https://reviews.llvm.org/D52932 llvm-svn: 345243
This commit is contained in:
parent
69b2652665
commit
dc9ae03db9
@ -224,6 +224,10 @@ OPTIONS
|
||||
|
||||
If set, ignore instructions that do not have a sched class (class idx = 0).
|
||||
|
||||
.. option:: -mcpu=<cpu name>
|
||||
|
||||
If set, measure the cpu characteristics using the counters for this CPU. This
|
||||
is useful when creating new sched models (the host CPU is unknown to LLVM).
|
||||
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
@ -130,6 +130,10 @@ OPTIONS
|
||||
|
||||
Generate enhanced disassembly info.
|
||||
|
||||
.. option:: -gen-exegesis
|
||||
|
||||
Generate llvm-exegesis tables.
|
||||
|
||||
.. option:: -version
|
||||
|
||||
Show the version number of this program.
|
||||
|
@ -183,22 +183,6 @@ struct MCExtraProcessorInfo {
|
||||
unsigned NumRegisterFiles;
|
||||
const MCRegisterCostEntry *RegisterCostTable;
|
||||
unsigned NumRegisterCostEntries;
|
||||
|
||||
struct PfmCountersInfo {
|
||||
// An optional name of a performance counter that can be used to measure
|
||||
// cycles.
|
||||
const char *CycleCounter;
|
||||
|
||||
// An optional name of a performance counter that can be used to measure
|
||||
// uops.
|
||||
const char *UopsCounter;
|
||||
|
||||
// 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.
|
||||
|
@ -1555,3 +1555,8 @@ include "llvm/Target/GlobalISel/Target.td"
|
||||
// Pull in the common support for the Global ISel DAG-based selector generation.
|
||||
//
|
||||
include "llvm/Target/GlobalISel/SelectionDAGCompat.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pull in the common support for Pfm Counters generation.
|
||||
//
|
||||
include "llvm/Target/TargetPfmCounters.td"
|
||||
|
46
include/llvm/Target/TargetPfmCounters.td
Normal file
46
include/llvm/Target/TargetPfmCounters.td
Normal file
@ -0,0 +1,46 @@
|
||||
//===- TargetPfmCounters.td - Target Pfm Counters -*- tablegen ----------*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the target-independent interfaces for performance counters.
|
||||
|
||||
// Definition of a hardware counters from libpfm identifiers.
|
||||
class PfmCounter<string counter> {
|
||||
// The name of the counter that measures events.
|
||||
// The name can be "some_counter + some_other_counter", in which case the
|
||||
// measured value is the sum of events on these counters.
|
||||
string Counter = counter;
|
||||
}
|
||||
|
||||
// Issue counters can be tied to a ProcResource
|
||||
class PfmIssueCounter<string resource_name, string counter>
|
||||
: PfmCounter<counter> {
|
||||
// The name of the ProcResource on which uops are issued. This is used by
|
||||
// llvm-exegesis to compare measurements with values in the SchedModels.
|
||||
// If the CPU has a sched model, this should correspond to the name of a
|
||||
// ProcResource.
|
||||
string ResourceName = resource_name;
|
||||
}
|
||||
|
||||
def NoPfmCounter : PfmCounter <""> {}
|
||||
|
||||
// Set of PfmCounters for measuring sched model characteristics.
|
||||
class ProcPfmCounters {
|
||||
// Processors can define how to measure cycles by defining a CycleCounter.
|
||||
PfmCounter CycleCounter = NoPfmCounter;
|
||||
// Processors can define how to measure uops by defining a UopsCounter.
|
||||
PfmCounter UopsCounter = NoPfmCounter;
|
||||
// Processors can define how to measure issued uops by defining IssueCounters.
|
||||
list<PfmIssueCounter> IssueCounters = [];
|
||||
}
|
||||
|
||||
// A binding of a set of counters to a CPU.
|
||||
class PfmCountersBinding<string cpu_name, ProcPfmCounters counters> {
|
||||
string CpuName = cpu_name;
|
||||
ProcPfmCounters Counters = counters;
|
||||
}
|
@ -557,31 +557,3 @@ class RetireControlUnit<int bufferSize, int retirePerCycle> {
|
||||
int MaxRetirePerCycle = retirePerCycle;
|
||||
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;
|
||||
}
|
||||
|
||||
// Each processor can define how to measure NumMicroOps by defining a
|
||||
// PfmUopsCounter.
|
||||
class PfmUopsCounter<string counter> : PfmCounter {
|
||||
string Counter = counter;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ tablegen(LLVM X86GenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank)
|
||||
tablegen(LLVM X86GenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
|
||||
tablegen(LLVM X86GenExegesis.inc -gen-exegesis)
|
||||
|
||||
if (X86_GEN_FOLD_TABLES)
|
||||
tablegen(LLVM X86GenFoldTables.inc -gen-x86-fold-tables)
|
||||
|
@ -11,73 +11,92 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
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"]>;
|
||||
def SBUopsCounter : PfmUopsCounter<"uops_issued:any">;
|
||||
}
|
||||
def UnhaltedCoreCyclesPfmCounter : PfmCounter<"unhalted_core_cycles">;
|
||||
def UopsIssuedPfmCounter : PfmCounter<"uops_issued:any">;
|
||||
|
||||
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"]>;
|
||||
def HWUopsCounter : PfmUopsCounter<"uops_issued:any">;
|
||||
def SandyBridgePfmCounters : ProcPfmCounters {
|
||||
let CycleCounter = UnhaltedCoreCyclesPfmCounter;
|
||||
let UopsCounter = UopsIssuedPfmCounter;
|
||||
let IssueCounters = [
|
||||
PfmIssueCounter<"SBPort0", "uops_dispatched_port:port_0">,
|
||||
PfmIssueCounter<"SBPort1", "uops_dispatched_port:port_1">,
|
||||
PfmIssueCounter<"SBPort23", "uops_dispatched_port:port_2 + uops_dispatched_port:port_3">,
|
||||
PfmIssueCounter<"SBPort4", "uops_dispatched_port:port_4">,
|
||||
PfmIssueCounter<"SBPort5", "uops_dispatched_port:port_5">
|
||||
];
|
||||
}
|
||||
def : PfmCountersBinding<"sandybridge", SandyBridgePfmCounters>;
|
||||
|
||||
let SchedModel = BroadwellModel in {
|
||||
def BWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
|
||||
def BWPort0Counter : PfmIssueCounter<BWPort0, ["uops_executed_port:port_0"]>;
|
||||
def BWPort1Counter : PfmIssueCounter<BWPort1, ["uops_executed_port:port_1"]>;
|
||||
def BWPort2Counter : PfmIssueCounter<BWPort2, ["uops_executed_port:port_2"]>;
|
||||
def BWPort3Counter : PfmIssueCounter<BWPort3, ["uops_executed_port:port_3"]>;
|
||||
def BWPort4Counter : PfmIssueCounter<BWPort4, ["uops_executed_port:port_4"]>;
|
||||
def BWPort5Counter : PfmIssueCounter<BWPort5, ["uops_executed_port:port_5"]>;
|
||||
def BWPort6Counter : PfmIssueCounter<BWPort6, ["uops_executed_port:port_6"]>;
|
||||
def BWPort7Counter : PfmIssueCounter<BWPort7, ["uops_executed_port:port_7"]>;
|
||||
def BWUopsCounter : PfmUopsCounter<"uops_issued:any">;
|
||||
def HaswellPfmCounters : ProcPfmCounters {
|
||||
let CycleCounter = UnhaltedCoreCyclesPfmCounter;
|
||||
let UopsCounter = UopsIssuedPfmCounter;
|
||||
let IssueCounters = [
|
||||
PfmIssueCounter<"HWPort0", "uops_dispatched_port:port_0">,
|
||||
PfmIssueCounter<"HWPort1", "uops_dispatched_port:port_1">,
|
||||
PfmIssueCounter<"HWPort2", "uops_dispatched_port:port_2">,
|
||||
PfmIssueCounter<"HWPort3", "uops_dispatched_port:port_3">,
|
||||
PfmIssueCounter<"HWPort4", "uops_dispatched_port:port_4">,
|
||||
PfmIssueCounter<"HWPort5", "uops_dispatched_port:port_5">,
|
||||
PfmIssueCounter<"HWPort6", "uops_dispatched_port:port_6">,
|
||||
PfmIssueCounter<"HWPort7", "uops_dispatched_port:port_7">
|
||||
];
|
||||
}
|
||||
def : PfmCountersBinding<"haswell", HaswellPfmCounters>;
|
||||
|
||||
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"]>;
|
||||
def SKLUopsCounter : PfmUopsCounter<"uops_issued:any">;
|
||||
def BroadwellPfmCounters : ProcPfmCounters {
|
||||
let CycleCounter = UnhaltedCoreCyclesPfmCounter;
|
||||
let UopsCounter = UopsIssuedPfmCounter;
|
||||
let IssueCounters = [
|
||||
PfmIssueCounter<"BWPort0", "uops_executed_port:port_0">,
|
||||
PfmIssueCounter<"BWPort1", "uops_executed_port:port_1">,
|
||||
PfmIssueCounter<"BWPort2", "uops_executed_port:port_2">,
|
||||
PfmIssueCounter<"BWPort3", "uops_executed_port:port_3">,
|
||||
PfmIssueCounter<"BWPort4", "uops_executed_port:port_4">,
|
||||
PfmIssueCounter<"BWPort5", "uops_executed_port:port_5">,
|
||||
PfmIssueCounter<"BWPort6", "uops_executed_port:port_6">,
|
||||
PfmIssueCounter<"BWPort7", "uops_executed_port:port_7">
|
||||
];
|
||||
}
|
||||
def : PfmCountersBinding<"broadwell", BroadwellPfmCounters>;
|
||||
|
||||
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"]>;
|
||||
def SKXUopsCounter : PfmUopsCounter<"uops_issued:any">;
|
||||
def SkylakeClientPfmCounters : ProcPfmCounters {
|
||||
let CycleCounter = UnhaltedCoreCyclesPfmCounter;
|
||||
let UopsCounter = UopsIssuedPfmCounter;
|
||||
let IssueCounters = [
|
||||
PfmIssueCounter<"SKLPort0", "uops_dispatched_port:port_0">,
|
||||
PfmIssueCounter<"SKLPort1", "uops_dispatched_port:port_1">,
|
||||
PfmIssueCounter<"SKLPort2", "uops_dispatched_port:port_2">,
|
||||
PfmIssueCounter<"SKLPort3", "uops_dispatched_port:port_3">,
|
||||
PfmIssueCounter<"SKLPort4", "uops_dispatched_port:port_4">,
|
||||
PfmIssueCounter<"SKLPort5", "uops_dispatched_port:port_5">,
|
||||
PfmIssueCounter<"SKLPort6", "uops_dispatched_port:port_6">,
|
||||
PfmIssueCounter<"SKLPort7", "uops_dispatched_port:port_7">
|
||||
];
|
||||
}
|
||||
def : PfmCountersBinding<"skylake", SkylakeClientPfmCounters>;
|
||||
|
||||
let SchedModel = BtVer2Model in {
|
||||
def JCycleCounter : PfmCycleCounter<"cpu_clk_unhalted">;
|
||||
def JUopsCounter : PfmUopsCounter<"retired_uops">;
|
||||
def JFPU0Counter : PfmIssueCounter<JFPU0, ["dispatched_fpu:pipe0"]>;
|
||||
def JFPU1Counter : PfmIssueCounter<JFPU1, ["dispatched_fpu:pipe1"]>;
|
||||
def SkylakeServerPfmCounters : ProcPfmCounters {
|
||||
let CycleCounter = UnhaltedCoreCyclesPfmCounter;
|
||||
let UopsCounter = UopsIssuedPfmCounter;
|
||||
let IssueCounters = [
|
||||
PfmIssueCounter<"SKXPort0", "uops_dispatched_port:port_0">,
|
||||
PfmIssueCounter<"SKXPort1", "uops_dispatched_port:port_1">,
|
||||
PfmIssueCounter<"SKXPort2", "uops_dispatched_port:port_2">,
|
||||
PfmIssueCounter<"SKXPort3", "uops_dispatched_port:port_3">,
|
||||
PfmIssueCounter<"SKXPort4", "uops_dispatched_port:port_4">,
|
||||
PfmIssueCounter<"SKXPort5", "uops_dispatched_port:port_5">,
|
||||
PfmIssueCounter<"SKXPort6", "uops_dispatched_port:port_6">,
|
||||
PfmIssueCounter<"SKXPort7", "uops_dispatched_port:port_7">
|
||||
];
|
||||
}
|
||||
def : PfmCountersBinding<"skylake-avx512", SkylakeServerPfmCounters>;
|
||||
|
||||
def BtVer2PfmCounters : ProcPfmCounters {
|
||||
let CycleCounter = PfmCounter<"cpu_clk_unhalted">;
|
||||
let UopsCounter = PfmCounter<"retired_uops">;
|
||||
let IssueCounters = [
|
||||
PfmIssueCounter<"JFPU0", "dispatched_fpu:pipe0">,
|
||||
PfmIssueCounter<"JFPU1", "dispatched_fpu:pipe1">
|
||||
];
|
||||
}
|
||||
def : PfmCountersBinding<"btver2", BtVer2PfmCounters>;
|
||||
|
@ -53,6 +53,10 @@ static llvm::MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
|
||||
} // namespace
|
||||
|
||||
class ExegesisAArch64Target : public ExegesisTarget {
|
||||
public:
|
||||
ExegesisAArch64Target() : ExegesisTarget({}) {}
|
||||
|
||||
private:
|
||||
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
|
||||
unsigned Reg,
|
||||
const llvm::APInt &Value) const override {
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "Assembler.h"
|
||||
#include "BenchmarkRunner.h"
|
||||
#include "MCInstrDescView.h"
|
||||
#include "PerfHelper.h"
|
||||
#include "Target.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstBuilder.h"
|
||||
@ -165,12 +167,7 @@ LatencySnippetGenerator::generateCodeTemplates(const Instruction &Instr) const {
|
||||
}
|
||||
|
||||
const char *LatencyBenchmarkRunner::getCounterName() const {
|
||||
if (!State.getSubtargetInfo().getSchedModel().hasExtraProcessorInfo())
|
||||
llvm::report_fatal_error("sched model is missing extra processor info!");
|
||||
const char *CounterName = State.getSubtargetInfo()
|
||||
.getSchedModel()
|
||||
.getExtraProcessorInfo()
|
||||
.PfmCounters.CycleCounter;
|
||||
const char *CounterName = State.getPfmCounters().CycleCounter;
|
||||
if (!CounterName)
|
||||
llvm::report_fatal_error("sched model does not define a cycle counter");
|
||||
return CounterName;
|
||||
|
@ -36,14 +36,17 @@ LLVMState::LLVMState(const std::string &Triple, const std::string &CpuName) {
|
||||
llvm::errs() << "no exegesis target for " << Triple << ", using default\n";
|
||||
TheExegesisTarget = &ExegesisTarget::getDefault();
|
||||
}
|
||||
PfmCounters = &TheExegesisTarget->getPfmCounters(CpuName);
|
||||
|
||||
RATC.reset(new RegisterAliasingTrackerCache(
|
||||
getRegInfo(), getFunctionReservedRegs(getTargetMachine())));
|
||||
IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
|
||||
}
|
||||
|
||||
LLVMState::LLVMState()
|
||||
LLVMState::LLVMState(const std::string &CpuName)
|
||||
: LLVMState(llvm::sys::getProcessTriple(),
|
||||
llvm::sys::getHostCPUName().str()) {}
|
||||
CpuName.empty() ? llvm::sys::getHostCPUName().str() : CpuName) {
|
||||
}
|
||||
|
||||
std::unique_ptr<llvm::LLVMTargetMachine>
|
||||
LLVMState::createTargetMachine() const {
|
||||
|
@ -30,12 +30,14 @@ namespace llvm {
|
||||
namespace exegesis {
|
||||
|
||||
class ExegesisTarget;
|
||||
class PfmCountersInfo;
|
||||
|
||||
// An object to initialize LLVM and prepare objects needed to run the
|
||||
// measurements.
|
||||
class LLVMState {
|
||||
public:
|
||||
LLVMState();
|
||||
// Uses the host triple. If CpuName is empty, uses the host CPU.
|
||||
LLVMState(const std::string &CpuName);
|
||||
|
||||
LLVMState(const std::string &Triple,
|
||||
const std::string &CpuName); // For tests.
|
||||
@ -57,14 +59,18 @@ public:
|
||||
const llvm::MCSubtargetInfo &getSubtargetInfo() const {
|
||||
return *TargetMachine->getMCSubtargetInfo();
|
||||
}
|
||||
|
||||
const RegisterAliasingTrackerCache &getRATC() const { return *RATC; }
|
||||
const InstructionsCache &getIC() const { return *IC; }
|
||||
|
||||
const PfmCountersInfo &getPfmCounters() const { return *PfmCounters; }
|
||||
|
||||
private:
|
||||
const ExegesisTarget *TheExegesisTarget;
|
||||
std::unique_ptr<const llvm::TargetMachine> TargetMachine;
|
||||
std::unique_ptr<const RegisterAliasingTrackerCache> RATC;
|
||||
std::unique_ptr<const InstructionsCache> IC;
|
||||
const PfmCountersInfo *PfmCounters;
|
||||
};
|
||||
|
||||
} // namespace exegesis
|
||||
|
@ -85,10 +85,37 @@ ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const {
|
||||
return llvm::make_unique<UopsBenchmarkRunner>(State);
|
||||
}
|
||||
|
||||
static_assert(std::is_pod<PfmCountersInfo>::value,
|
||||
"We shouldn't have dynamic initialization here");
|
||||
const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr};
|
||||
|
||||
const PfmCountersInfo &
|
||||
ExegesisTarget::getPfmCounters(llvm::StringRef CpuName) const {
|
||||
assert(std::is_sorted(
|
||||
CpuPfmCounters.begin(), CpuPfmCounters.end(),
|
||||
[](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
|
||||
return strcmp(LHS.CpuName, RHS.CpuName) < 0;
|
||||
}) &&
|
||||
"CpuPfmCounters table is not sorted");
|
||||
|
||||
// Find entry
|
||||
auto Found =
|
||||
std::lower_bound(CpuPfmCounters.begin(), CpuPfmCounters.end(), CpuName);
|
||||
if (Found == CpuPfmCounters.end() ||
|
||||
llvm::StringRef(Found->CpuName) != CpuName) {
|
||||
return PfmCountersInfo::Default;
|
||||
}
|
||||
assert(Found->PCI && "Missing counters");
|
||||
return *Found->PCI;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Default implementation.
|
||||
class ExegesisDefaultTarget : public ExegesisTarget {
|
||||
public:
|
||||
ExegesisDefaultTarget() : ExegesisTarget({}) {}
|
||||
|
||||
private:
|
||||
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
|
||||
unsigned Reg,
|
||||
|
@ -31,8 +31,42 @@
|
||||
namespace llvm {
|
||||
namespace exegesis {
|
||||
|
||||
struct PfmCountersInfo {
|
||||
// An optional name of a performance counter that can be used to measure
|
||||
// cycles.
|
||||
const char *const CycleCounter;
|
||||
|
||||
// An optional name of a performance counter that can be used to measure
|
||||
// uops.
|
||||
const char *const UopsCounter;
|
||||
|
||||
// An IssueCounter specifies how to measure uops issued to specific proc
|
||||
// resources.
|
||||
struct IssueCounter {
|
||||
const char *const Counter;
|
||||
// The name of the ProcResource that this counter measures.
|
||||
const char *const ProcResName;
|
||||
};
|
||||
// An optional list of IssueCounters.
|
||||
const IssueCounter *const IssueCounters;
|
||||
const unsigned NumIssueCounters;
|
||||
|
||||
static const PfmCountersInfo Default;
|
||||
};
|
||||
|
||||
struct CpuAndPfmCounters {
|
||||
const char *const CpuName;
|
||||
const PfmCountersInfo *const PCI;
|
||||
bool operator<(llvm::StringRef S) const {
|
||||
return llvm::StringRef(CpuName) < S;
|
||||
}
|
||||
};
|
||||
|
||||
class ExegesisTarget {
|
||||
public:
|
||||
explicit ExegesisTarget(llvm::ArrayRef<CpuAndPfmCounters> CpuPfmCounters)
|
||||
: CpuPfmCounters(CpuPfmCounters) {}
|
||||
|
||||
// Targets can use this to add target-specific passes in assembleToStream();
|
||||
virtual void addTargetSpecificPasses(llvm::PassManagerBase &PM) const {}
|
||||
|
||||
@ -83,6 +117,10 @@ public:
|
||||
|
||||
virtual ~ExegesisTarget();
|
||||
|
||||
// Returns the Pfm counters for the given CPU (or the default if no pfm
|
||||
// counters are defined for this CPU).
|
||||
const PfmCountersInfo &getPfmCounters(llvm::StringRef CpuName) const;
|
||||
|
||||
private:
|
||||
virtual bool matchesArch(llvm::Triple::ArchType Arch) const = 0;
|
||||
|
||||
@ -98,6 +136,7 @@ private:
|
||||
const LLVMState &State) const;
|
||||
|
||||
const ExegesisTarget *Next = nullptr;
|
||||
const llvm::ArrayRef<CpuAndPfmCounters> CpuPfmCounters;
|
||||
};
|
||||
|
||||
} // namespace exegesis
|
||||
|
@ -223,24 +223,22 @@ UopsSnippetGenerator::generateCodeTemplates(const Instruction &Instr) const {
|
||||
|
||||
llvm::Expected<std::vector<BenchmarkMeasure>>
|
||||
UopsBenchmarkRunner::runMeasurements(const FunctionExecutor &Executor) const {
|
||||
const auto &SchedModel = State.getSubtargetInfo().getSchedModel();
|
||||
|
||||
std::vector<BenchmarkMeasure> Result;
|
||||
const auto &PfmCounters = SchedModel.getExtraProcessorInfo().PfmCounters;
|
||||
const PfmCountersInfo &PCI = State.getPfmCounters();
|
||||
// Uops per port.
|
||||
for (unsigned ProcResIdx = 1;
|
||||
ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
|
||||
const char *const Counters = PfmCounters.IssueCounters[ProcResIdx];
|
||||
if (!Counters)
|
||||
for (const auto *IssueCounter = PCI.IssueCounters,
|
||||
*IssueCounterEnd = PCI.IssueCounters + PCI.NumIssueCounters;
|
||||
IssueCounter != IssueCounterEnd; ++IssueCounter) {
|
||||
if (!IssueCounter->Counter)
|
||||
continue;
|
||||
auto ExpectedCounterValue = Executor.runAndMeasure(Counters);
|
||||
auto ExpectedCounterValue = Executor.runAndMeasure(IssueCounter->Counter);
|
||||
if (!ExpectedCounterValue)
|
||||
return ExpectedCounterValue.takeError();
|
||||
Result.push_back(BenchmarkMeasure::Create(
|
||||
SchedModel.getProcResource(ProcResIdx)->Name, *ExpectedCounterValue));
|
||||
Result.push_back(BenchmarkMeasure::Create(IssueCounter->ProcResName,
|
||||
*ExpectedCounterValue));
|
||||
}
|
||||
// NumMicroOps.
|
||||
if (const char *const UopsCounter = PfmCounters.UopsCounter) {
|
||||
if (const char *const UopsCounter = PCI.UopsCounter) {
|
||||
auto ExpectedCounterValue = Executor.runAndMeasure(UopsCounter);
|
||||
if (!ExpectedCounterValue)
|
||||
return ExpectedCounterValue.takeError();
|
||||
|
@ -329,7 +329,13 @@ private:
|
||||
std::vector<llvm::MCInst> Instructions;
|
||||
};
|
||||
|
||||
#include "X86GenExegesis.inc"
|
||||
|
||||
class ExegesisX86Target : public ExegesisTarget {
|
||||
public:
|
||||
ExegesisX86Target() : ExegesisTarget(X86CpuPfmCounters) {}
|
||||
|
||||
private:
|
||||
void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override {
|
||||
// Lowers FP pseudo-instructions, e.g. ABS_Fp32 -> ABS_F.
|
||||
PM.add(llvm::createX86FloatingPointStackifierPass());
|
||||
|
@ -94,6 +94,13 @@ static cl::opt<std::string>
|
||||
AnalysisInconsistenciesOutputFile("analysis-inconsistencies-output-file",
|
||||
cl::desc(""), cl::init("-"));
|
||||
|
||||
static cl::opt<std::string>
|
||||
CpuName("mcpu",
|
||||
cl::desc(
|
||||
"cpu name to use for pfm counters, leave empty to autodetect"),
|
||||
cl::init(""));
|
||||
|
||||
|
||||
static ExitOnError ExitOnErr;
|
||||
|
||||
#ifdef LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET
|
||||
@ -321,7 +328,7 @@ void benchmarkMain() {
|
||||
LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET();
|
||||
#endif
|
||||
|
||||
const LLVMState State;
|
||||
const LLVMState State(CpuName);
|
||||
const auto Opcodes = getOpcodesOrDie(State.getInstrInfo());
|
||||
|
||||
std::vector<BenchmarkCode> Configurations;
|
||||
@ -399,7 +406,7 @@ static void analysisMain() {
|
||||
llvm::InitializeNativeTargetAsmPrinter();
|
||||
llvm::InitializeNativeTargetDisassembler();
|
||||
// Read benchmarks.
|
||||
const LLVMState State;
|
||||
const LLVMState State("");
|
||||
const std::vector<InstructionBenchmark> Points =
|
||||
ExitOnErr(InstructionBenchmark::readYamls(State, BenchmarkFile));
|
||||
llvm::outs() << "Parsed " << Points.size() << " benchmark points\n";
|
||||
|
@ -21,6 +21,7 @@ add_tablegen(llvm-tblgen LLVM
|
||||
DAGISelMatcher.cpp
|
||||
DFAPacketizerEmitter.cpp
|
||||
DisassemblerEmitter.cpp
|
||||
ExegesisEmitter.cpp
|
||||
FastISelEmitter.cpp
|
||||
FixedLenDecoderEmitter.cpp
|
||||
GlobalISelEmitter.cpp
|
||||
|
@ -350,7 +350,7 @@ processSTIPredicate(STIPredicateFunction &Fn,
|
||||
unsigned OpcodeIdx = Opcode2Index[Opcode];
|
||||
if (OpcodeMasks[OpcodeIdx].first[ProcIndex]) {
|
||||
std::string Message =
|
||||
"Opcode " + Opcode->getName().str() +
|
||||
"Opcode " + Opcode->getName().str() +
|
||||
" used by multiple InstructionEquivalenceClass definitions.";
|
||||
PrintFatalError(EC->getLoc(), Message);
|
||||
}
|
||||
@ -487,9 +487,6 @@ void CodeGenSchedModels::collectOptionalProcessorInfo() {
|
||||
// Collect processor RetireControlUnit descriptors if available.
|
||||
collectRetireControlUnits();
|
||||
|
||||
// Find pfm counter definitions for each processor.
|
||||
collectPfmCounters();
|
||||
|
||||
checkCompleteness();
|
||||
}
|
||||
|
||||
@ -1789,32 +1786,6 @@ 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;
|
||||
}
|
||||
for (Record *Def : Records.getAllDerivedDefinitions("PfmUopsCounter")) {
|
||||
CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
|
||||
if (PM.PfmUopsCounterDef) {
|
||||
PrintFatalError(Def->getLoc(),
|
||||
"multiple uops counters for " +
|
||||
Def->getValueAsDef("SchedModel")->getName());
|
||||
}
|
||||
PM.PfmUopsCounterDef = Def;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect and sort WriteRes, ReadAdvance, and ProcResources.
|
||||
void CodeGenSchedModels::collectProcResources() {
|
||||
ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits");
|
||||
|
@ -246,11 +246,6 @@ struct CodeGenProcModel {
|
||||
// Optional Retire Control Unit definition.
|
||||
Record *RetireControlUnit;
|
||||
|
||||
// List of PfmCounters.
|
||||
RecVec PfmIssueCounterDefs;
|
||||
Record *PfmCycleCounterDef = nullptr;
|
||||
Record *PfmUopsCounterDef = nullptr;
|
||||
|
||||
CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
|
||||
Record *IDef) :
|
||||
Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
|
||||
@ -265,10 +260,7 @@ struct CodeGenProcModel {
|
||||
}
|
||||
|
||||
bool hasExtraProcessorInfo() const {
|
||||
return RetireControlUnit || !RegisterFiles.empty() ||
|
||||
!PfmIssueCounterDefs.empty() ||
|
||||
PfmCycleCounterDef != nullptr ||
|
||||
PfmUopsCounterDef != nullptr;
|
||||
return RetireControlUnit || !RegisterFiles.empty();
|
||||
}
|
||||
|
||||
unsigned getProcResourceIdx(Record *PRDef) const;
|
||||
@ -593,8 +585,6 @@ private:
|
||||
|
||||
void collectRegisterFiles();
|
||||
|
||||
void collectPfmCounters();
|
||||
|
||||
void collectOptionalProcessorInfo();
|
||||
|
||||
std::string createSchedClassName(Record *ItinClassDef,
|
||||
|
@ -711,4 +711,3 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
|
||||
// Sort the argument attributes for later benefit.
|
||||
llvm::sort(ArgumentAttributes);
|
||||
}
|
||||
|
||||
|
212
utils/TableGen/ExegesisEmitter.cpp
Normal file
212
utils/TableGen/ExegesisEmitter.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
//===- ExegesisEmitter.cpp - Generate exegesis target data ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend emits llvm-exegesis information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "exegesis-emitter"
|
||||
|
||||
namespace {
|
||||
|
||||
class ExegesisEmitter {
|
||||
public:
|
||||
ExegesisEmitter(RecordKeeper &RK);
|
||||
|
||||
void run(raw_ostream &OS) const;
|
||||
|
||||
private:
|
||||
unsigned getPfmCounterId(llvm::StringRef Name) const {
|
||||
const auto It = PfmCounterNameTable.find(Name);
|
||||
if (It == PfmCounterNameTable.end())
|
||||
PrintFatalError("no pfm counter id for " + Name);
|
||||
return It->second;
|
||||
}
|
||||
|
||||
// Collects all the ProcPfmCounters definitions available in this target.
|
||||
void emitPfmCounters(raw_ostream &OS) const;
|
||||
|
||||
void emitPfmCountersInfo(const Record &Def,
|
||||
unsigned &IssueCountersTableOffset,
|
||||
raw_ostream &OS) const;
|
||||
|
||||
void emitPfmCountersLookupTable(raw_ostream &OS) const;
|
||||
|
||||
RecordKeeper &Records;
|
||||
std::string Target;
|
||||
|
||||
// Table of counter name -> counter index.
|
||||
const std::map<llvm::StringRef, unsigned> PfmCounterNameTable;
|
||||
};
|
||||
|
||||
static std::map<llvm::StringRef, unsigned>
|
||||
collectPfmCounters(const RecordKeeper &Records) {
|
||||
std::map<llvm::StringRef, unsigned> PfmCounterNameTable;
|
||||
const auto AddPfmCounterName = [&PfmCounterNameTable](
|
||||
const Record *PfmCounterDef) {
|
||||
const llvm::StringRef Counter = PfmCounterDef->getValueAsString("Counter");
|
||||
if (!Counter.empty())
|
||||
PfmCounterNameTable.emplace(Counter, 0);
|
||||
};
|
||||
for (Record *Def : Records.getAllDerivedDefinitions("ProcPfmCounters")) {
|
||||
// Check that ResourceNames are unique.
|
||||
llvm::SmallSet<llvm::StringRef, 16> Seen;
|
||||
for (const Record *IssueCounter :
|
||||
Def->getValueAsListOfDefs("IssueCounters")) {
|
||||
const llvm::StringRef ResourceName =
|
||||
IssueCounter->getValueAsString("ResourceName");
|
||||
if (ResourceName.empty())
|
||||
PrintFatalError(IssueCounter->getLoc(), "invalid empty ResourceName");
|
||||
if (!Seen.insert(ResourceName).second)
|
||||
PrintFatalError(IssueCounter->getLoc(),
|
||||
"duplicate ResourceName " + ResourceName);
|
||||
AddPfmCounterName(IssueCounter);
|
||||
}
|
||||
AddPfmCounterName(Def->getValueAsDef("CycleCounter"));
|
||||
AddPfmCounterName(Def->getValueAsDef("UopsCounter"));
|
||||
}
|
||||
unsigned Index = 0;
|
||||
for (auto &NameAndIndex : PfmCounterNameTable)
|
||||
NameAndIndex.second = Index++;
|
||||
return PfmCounterNameTable;
|
||||
}
|
||||
|
||||
ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
|
||||
: Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {
|
||||
std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
|
||||
if (Targets.size() == 0)
|
||||
PrintFatalError("ERROR: No 'Target' subclasses defined!");
|
||||
if (Targets.size() != 1)
|
||||
PrintFatalError("ERROR: Multiple subclasses of Target defined!");
|
||||
Target = Targets[0]->getName();
|
||||
}
|
||||
|
||||
void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
|
||||
unsigned &IssueCountersTableOffset,
|
||||
raw_ostream &OS) const {
|
||||
const auto CycleCounter =
|
||||
Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");
|
||||
const auto UopsCounter =
|
||||
Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
|
||||
const size_t NumIssueCounters =
|
||||
Def.getValueAsListOfDefs("IssueCounters").size();
|
||||
|
||||
// This is the default, do not emit.
|
||||
if (CycleCounter.empty() && UopsCounter.empty() && NumIssueCounters == 0)
|
||||
return;
|
||||
|
||||
OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
|
||||
<< " = {\n";
|
||||
|
||||
// Cycle Counter.
|
||||
if (CycleCounter.empty())
|
||||
OS << " nullptr, // No cycle counter.\n";
|
||||
else
|
||||
OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
|
||||
<< "], // Cycle counter\n";
|
||||
|
||||
// Uops Counter.
|
||||
if (UopsCounter.empty())
|
||||
OS << " nullptr, // No uops counter.\n";
|
||||
else
|
||||
OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)
|
||||
<< "], // Uops counter\n";
|
||||
|
||||
// Issue Counters
|
||||
if (NumIssueCounters == 0)
|
||||
OS << " nullptr, // No issue counters.\n 0\n";
|
||||
else
|
||||
OS << " " << Target << "PfmIssueCounters + " << IssueCountersTableOffset
|
||||
<< ", " << NumIssueCounters << " // Issue counters.\n";
|
||||
|
||||
OS << "};\n";
|
||||
IssueCountersTableOffset += NumIssueCounters;
|
||||
}
|
||||
|
||||
void ExegesisEmitter::emitPfmCounters(raw_ostream &OS) const {
|
||||
// Emit the counter name table.
|
||||
OS << "\nstatic const char* " << Target << "PfmCounterNames[] = {\n";
|
||||
for (const auto &NameAndIndex : PfmCounterNameTable)
|
||||
OS << " \"" << NameAndIndex.first << "\", // " << NameAndIndex.second
|
||||
<< "\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
// Emit the IssueCounters table.
|
||||
const auto PfmCounterDefs =
|
||||
Records.getAllDerivedDefinitions("ProcPfmCounters");
|
||||
OS << "static const PfmCountersInfo::IssueCounter " << Target
|
||||
<< "PfmIssueCounters[] = {\n";
|
||||
for (const Record *Def : PfmCounterDefs) {
|
||||
for (const Record *ICDef : Def->getValueAsListOfDefs("IssueCounters"))
|
||||
OS << " { " << Target << "PfmCounterNames["
|
||||
<< getPfmCounterId(ICDef->getValueAsString("Counter")) << "], \""
|
||||
<< ICDef->getValueAsString("ResourceName") << "\"},\n";
|
||||
}
|
||||
|
||||
OS << "};\n";
|
||||
|
||||
// Now generate the PfmCountersInfo.
|
||||
unsigned IssueCountersTableOffset = 0;
|
||||
for (const Record *Def : PfmCounterDefs)
|
||||
emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);
|
||||
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {
|
||||
std::vector<Record *> Bindings =
|
||||
Records.getAllDerivedDefinitions("PfmCountersBinding");
|
||||
llvm::sort(Bindings, [](const Record *L, const Record *R) {
|
||||
return L->getValueAsString("CpuName") < R->getValueAsString("CpuName");
|
||||
});
|
||||
|
||||
OS << "// Sorted (by CpuName) array of pfm counters.\n"
|
||||
<< "static const CpuAndPfmCounters " << Target << "CpuPfmCounters[] = {\n";
|
||||
for (Record *Binding : Bindings) {
|
||||
// Emit as { "cpu", procinit },
|
||||
OS << " { \"" //
|
||||
<< Binding->getValueAsString("CpuName") << "\"," //
|
||||
<< " &" << Target << Binding->getValueAsDef("Counters")->getName() //
|
||||
<< " },\n";
|
||||
}
|
||||
OS << "};\n\n";
|
||||
}
|
||||
|
||||
void ExegesisEmitter::run(raw_ostream &OS) const {
|
||||
emitSourceFileHeader("Exegesis Tables", OS);
|
||||
emitPfmCounters(OS);
|
||||
emitPfmCountersLookupTable(OS);
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitExegesis(RecordKeeper &RK, raw_ostream &OS) {
|
||||
ExegesisEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
@ -697,80 +697,12 @@ SubtargetEmitter::EmitRegisterFileTables(const CodeGenProcModel &ProcModel,
|
||||
return CostTblIndex;
|
||||
}
|
||||
|
||||
static bool EmitPfmIssueCountersTable(const CodeGenProcModel &ProcModel,
|
||||
raw_ostream &OS) {
|
||||
unsigned NumCounterDefs = 1 + ProcModel.ProcResourceDefs.size();
|
||||
std::vector<const Record *> CounterDefs(NumCounterDefs);
|
||||
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 (unsigned i = 0; i != NumCounterDefs; ++i) {
|
||||
const Record *CounterDef = CounterDefs[i];
|
||||
if (CounterDef) {
|
||||
const auto PfmCounters = CounterDef->getValueAsListOfStrings("Counters");
|
||||
if (PfmCounters.empty())
|
||||
PrintFatalError(CounterDef->getLoc(), "empty counter list");
|
||||
OS << " \"" << PfmCounters[0];
|
||||
for (unsigned p = 1, e = PfmCounters.size(); p != e; ++p)
|
||||
OS << ",\" \"" << PfmCounters[p];
|
||||
OS << "\", // #" << i << " = ";
|
||||
OS << CounterDef->getValueAsDef("Resource")->getName() << "\n";
|
||||
} else {
|
||||
OS << " nullptr, // #" << i << "\n";
|
||||
}
|
||||
}
|
||||
OS << "};\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
static void EmitPfmCounters(const CodeGenProcModel &ProcModel,
|
||||
const bool HasPfmIssueCounters, raw_ostream &OS) {
|
||||
OS << " {\n";
|
||||
// Emit the cycle counter.
|
||||
if (ProcModel.PfmCycleCounterDef)
|
||||
OS << " \"" << ProcModel.PfmCycleCounterDef->getValueAsString("Counter")
|
||||
<< "\", // Cycle counter.\n";
|
||||
else
|
||||
OS << " nullptr, // No cycle counter.\n";
|
||||
|
||||
// Emit the uops counter.
|
||||
if (ProcModel.PfmUopsCounterDef)
|
||||
OS << " \"" << ProcModel.PfmUopsCounterDef->getValueAsString("Counter")
|
||||
<< "\", // Uops counter.\n";
|
||||
else
|
||||
OS << " nullptr, // No uops counter.\n";
|
||||
|
||||
// Emit a reference to issue counters table.
|
||||
if (HasPfmIssueCounters)
|
||||
OS << " " << ProcModel.ModelName << "PfmIssueCounters\n";
|
||||
else
|
||||
OS << " nullptr // No issue counters.\n";
|
||||
OS << " }\n";
|
||||
}
|
||||
|
||||
void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
||||
raw_ostream &OS) {
|
||||
// Generate a table of register file descriptors (one entry per each user
|
||||
// defined register file), and a table of register costs.
|
||||
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.
|
||||
OS << "\nstatic const llvm::MCExtraProcessorInfo " << ProcModel.ModelName
|
||||
<< "ExtraInfo = {\n ";
|
||||
@ -783,8 +715,6 @@ void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
|
||||
EmitRegisterFileInfo(ProcModel, ProcModel.RegisterFiles.size(),
|
||||
NumCostEntries, OS);
|
||||
|
||||
EmitPfmCounters(ProcModel, HasPfmIssueCounters, OS);
|
||||
|
||||
OS << "};\n";
|
||||
}
|
||||
|
||||
@ -1410,7 +1340,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
|
||||
}
|
||||
|
||||
//
|
||||
// EmitProcessorLookup - generate cpu name to itinerary lookup table.
|
||||
// EmitProcessorLookup - generate cpu name to sched model lookup tables.
|
||||
//
|
||||
void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
|
||||
// Gather and sort processor information
|
||||
@ -1418,12 +1348,11 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
|
||||
Records.getAllDerivedDefinitions("Processor");
|
||||
llvm::sort(ProcessorList, LessRecordFieldName());
|
||||
|
||||
// Begin processor table
|
||||
// Begin processor->sched model table
|
||||
OS << "\n";
|
||||
OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
|
||||
<< "extern const llvm::SubtargetInfoKV "
|
||||
<< Target << "ProcSchedKV[] = {\n";
|
||||
|
||||
OS << "// Sorted (by key) array of sched model for CPU subtype.\n"
|
||||
<< "extern const llvm::SubtargetInfoKV " << Target
|
||||
<< "ProcSchedKV[] = {\n";
|
||||
// For each processor
|
||||
for (Record *Processor : ProcessorList) {
|
||||
StringRef Name = Processor->getValueAsString("Name");
|
||||
@ -1433,8 +1362,7 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
|
||||
// Emit as { "cpu", procinit },
|
||||
OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " },\n";
|
||||
}
|
||||
|
||||
// End processor table
|
||||
// End processor->sched model table
|
||||
OS << "};\n";
|
||||
}
|
||||
|
||||
@ -1675,7 +1603,7 @@ void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
|
||||
|
||||
// Emit target predicates.
|
||||
emitSchedModelHelpersImpl(OS);
|
||||
|
||||
|
||||
OS << "} // " << ClassName << "::resolveSchedClass\n\n";
|
||||
|
||||
OS << "unsigned " << ClassName
|
||||
|
@ -53,6 +53,7 @@ enum ActionType {
|
||||
GenX86EVEX2VEXTables,
|
||||
GenX86FoldTables,
|
||||
GenRegisterBank,
|
||||
GenExegesis,
|
||||
};
|
||||
|
||||
namespace {
|
||||
@ -117,7 +118,9 @@ namespace {
|
||||
clEnumValN(GenX86FoldTables, "gen-x86-fold-tables",
|
||||
"Generate X86 fold tables"),
|
||||
clEnumValN(GenRegisterBank, "gen-register-bank",
|
||||
"Generate registers bank descriptions")));
|
||||
"Generate registers bank descriptions"),
|
||||
clEnumValN(GenExegesis, "gen-exegesis",
|
||||
"Generate llvm-exegesis tables")));
|
||||
|
||||
cl::OptionCategory PrintEnumsCat("Options for -print-enums");
|
||||
cl::opt<std::string>
|
||||
@ -231,6 +234,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
||||
case GenX86FoldTables:
|
||||
EmitX86FoldTables(Records, OS);
|
||||
break;
|
||||
case GenExegesis:
|
||||
EmitExegesis(Records, OS);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -89,6 +89,7 @@ void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitX86EVEX2VEXTables(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitExegesis(RecordKeeper &RK, raw_ostream &OS);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user