llvm.org GIT mirror llvm / f4fb61b
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@345243 91177308-0d34-0410-b5e6-96231b3b80d8 Clement Courbet 11 months ago
25 changed file(s) with 477 addition(s) and 247 deletion(s). Raw diff Collapse all Expand all
223223
224224 If set, ignore instructions that do not have a sched class (class idx = 0).
225225
226 .. option:: -mcpu=
227
228 If set, measure the cpu characteristics using the counters for this CPU. This
229 is useful when creating new sched models (the host CPU is unknown to LLVM).
226230
227231 EXIT STATUS
228232 -----------
129129
130130 Generate enhanced disassembly info.
131131
132 .. option:: -gen-exegesis
133
134 Generate llvm-exegesis tables.
135
132136 .. option:: -version
133137
134138 Show the version number of this program.
182182 unsigned NumRegisterFiles;
183183 const MCRegisterCostEntry *RegisterCostTable;
184184 unsigned NumRegisterCostEntries;
185
186 struct PfmCountersInfo {
187 // An optional name of a performance counter that can be used to measure
188 // cycles.
189 const char *CycleCounter;
190
191 // An optional name of a performance counter that can be used to measure
192 // uops.
193 const char *UopsCounter;
194
195 // For each MCProcResourceDesc defined by the processor, an optional list of
196 // names of performance counters that can be used to measure the resource
197 // utilization.
198 const char **IssueCounters;
199 };
200 PfmCountersInfo PfmCounters;
201185 };
202186
203187 /// Machine model for scheduling, bundling, and heuristics.
15541554 // Pull in the common support for the Global ISel DAG-based selector generation.
15551555 //
15561556 include "llvm/Target/GlobalISel/SelectionDAGCompat.td"
1557
1558 //===----------------------------------------------------------------------===//
1559 // Pull in the common support for Pfm Counters generation.
1560 //
1561 include "llvm/Target/TargetPfmCounters.td"
0 //===- TargetPfmCounters.td - Target Pfm Counters -*- tablegen ----------*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the target-independent interfaces for performance counters.
10
11 // Definition of a hardware counters from libpfm identifiers.
12 class PfmCounter {
13 // The name of the counter that measures events.
14 // The name can be "some_counter + some_other_counter", in which case the
15 // measured value is the sum of events on these counters.
16 string Counter = counter;
17 }
18
19 // Issue counters can be tied to a ProcResource
20 class PfmIssueCounter
21 : PfmCounter {
22 // The name of the ProcResource on which uops are issued. This is used by
23 // llvm-exegesis to compare measurements with values in the SchedModels.
24 // If the CPU has a sched model, this should correspond to the name of a
25 // ProcResource.
26 string ResourceName = resource_name;
27 }
28
29 def NoPfmCounter : PfmCounter <""> {}
30
31 // Set of PfmCounters for measuring sched model characteristics.
32 class ProcPfmCounters {
33 // Processors can define how to measure cycles by defining a CycleCounter.
34 PfmCounter CycleCounter = NoPfmCounter;
35 // Processors can define how to measure uops by defining a UopsCounter.
36 PfmCounter UopsCounter = NoPfmCounter;
37 // Processors can define how to measure issued uops by defining IssueCounters.
38 list IssueCounters = [];
39 }
40
41 // A binding of a set of counters to a CPU.
42 class PfmCountersBinding {
43 string CpuName = cpu_name;
44 ProcPfmCounters Counters = counters;
45 }
556556 int MaxRetirePerCycle = retirePerCycle;
557557 SchedMachineModel SchedModel = ?;
558558 }
559
560 // Allow the definition of hardware counters.
561 class PfmCounter {
562 SchedMachineModel SchedModel = ?;
563 }
564
565 // Each processor can define how to measure cycles by defining a
566 // PfmCycleCounter.
567 class PfmCycleCounter : PfmCounter {
568 string Counter = counter;
569 }
570
571 // Each ProcResourceUnits can define how to measure issued uops by defining
572 // a PfmIssueCounter.
573 class PfmIssueCounter counters>
574 : PfmCounter{
575 // The resource units on which uops are issued.
576 ProcResourceUnits Resource = resource;
577 // The list of counters that measure issue events.
578 list Counters = counters;
579 }
580
581 // Each processor can define how to measure NumMicroOps by defining a
582 // PfmUopsCounter.
583 class PfmUopsCounter : PfmCounter {
584 string Counter = counter;
585 }
586
1212 tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank)
1313 tablegen(LLVM X86GenRegisterInfo.inc -gen-register-info)
1414 tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
15 tablegen(LLVM X86GenExegesis.inc -gen-exegesis)
1516
1617 if (X86_GEN_FOLD_TABLES)
1718 tablegen(LLVM X86GenFoldTables.inc -gen-x86-fold-tables)
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 let SchedModel = SandyBridgeModel in {
14 def SBCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
15 def SBPort0Counter : PfmIssueCounter;
16 def SBPort1Counter : PfmIssueCounter;
17 def SBPort23Counter : PfmIssueCounter
18 ["uops_dispatched_port:port_2",
19 "uops_dispatched_port:port_3"]>;
20 def SBPort4Counter : PfmIssueCounter;
21 def SBPort5Counter : PfmIssueCounter;
22 def SBUopsCounter : PfmUopsCounter<"uops_issued:any">;
13 def UnhaltedCoreCyclesPfmCounter : PfmCounter<"unhalted_core_cycles">;
14 def UopsIssuedPfmCounter : PfmCounter<"uops_issued:any">;
15
16 def SandyBridgePfmCounters : ProcPfmCounters {
17 let CycleCounter = UnhaltedCoreCyclesPfmCounter;
18 let UopsCounter = UopsIssuedPfmCounter;
19 let IssueCounters = [
20 PfmIssueCounter<"SBPort0", "uops_dispatched_port:port_0">,
21 PfmIssueCounter<"SBPort1", "uops_dispatched_port:port_1">,
22 PfmIssueCounter<"SBPort23", "uops_dispatched_port:port_2 + uops_dispatched_port:port_3">,
23 PfmIssueCounter<"SBPort4", "uops_dispatched_port:port_4">,
24 PfmIssueCounter<"SBPort5", "uops_dispatched_port:port_5">
25 ];
2326 }
27 def : PfmCountersBinding<"sandybridge", SandyBridgePfmCounters>;
2428
25 let SchedModel = HaswellModel in {
26 def HWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
27 def HWPort0Counter : PfmIssueCounter;
28 def HWPort1Counter : PfmIssueCounter;
29 def HWPort2Counter : PfmIssueCounter;
30 def HWPort3Counter : PfmIssueCounter;
31 def HWPort4Counter : PfmIssueCounter;
32 def HWPort5Counter : PfmIssueCounter;
33 def HWPort6Counter : PfmIssueCounter;
34 def HWPort7Counter : PfmIssueCounter;
35 def HWUopsCounter : PfmUopsCounter<"uops_issued:any">;
29 def HaswellPfmCounters : ProcPfmCounters {
30 let CycleCounter = UnhaltedCoreCyclesPfmCounter;
31 let UopsCounter = UopsIssuedPfmCounter;
32 let IssueCounters = [
33 PfmIssueCounter<"HWPort0", "uops_dispatched_port:port_0">,
34 PfmIssueCounter<"HWPort1", "uops_dispatched_port:port_1">,
35 PfmIssueCounter<"HWPort2", "uops_dispatched_port:port_2">,
36 PfmIssueCounter<"HWPort3", "uops_dispatched_port:port_3">,
37 PfmIssueCounter<"HWPort4", "uops_dispatched_port:port_4">,
38 PfmIssueCounter<"HWPort5", "uops_dispatched_port:port_5">,
39 PfmIssueCounter<"HWPort6", "uops_dispatched_port:port_6">,
40 PfmIssueCounter<"HWPort7", "uops_dispatched_port:port_7">
41 ];
3642 }
43 def : PfmCountersBinding<"haswell", HaswellPfmCounters>;
3744
38 let SchedModel = BroadwellModel in {
39 def BWCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
40 def BWPort0Counter : PfmIssueCounter;
41 def BWPort1Counter : PfmIssueCounter;
42 def BWPort2Counter : PfmIssueCounter;
43 def BWPort3Counter : PfmIssueCounter;
44 def BWPort4Counter : PfmIssueCounter;
45 def BWPort5Counter : PfmIssueCounter;
46 def BWPort6Counter : PfmIssueCounter;
47 def BWPort7Counter : PfmIssueCounter;
48 def BWUopsCounter : PfmUopsCounter<"uops_issued:any">;
45 def BroadwellPfmCounters : ProcPfmCounters {
46 let CycleCounter = UnhaltedCoreCyclesPfmCounter;
47 let UopsCounter = UopsIssuedPfmCounter;
48 let IssueCounters = [
49 PfmIssueCounter<"BWPort0", "uops_executed_port:port_0">,
50 PfmIssueCounter<"BWPort1", "uops_executed_port:port_1">,
51 PfmIssueCounter<"BWPort2", "uops_executed_port:port_2">,
52 PfmIssueCounter<"BWPort3", "uops_executed_port:port_3">,
53 PfmIssueCounter<"BWPort4", "uops_executed_port:port_4">,
54 PfmIssueCounter<"BWPort5", "uops_executed_port:port_5">,
55 PfmIssueCounter<"BWPort6", "uops_executed_port:port_6">,
56 PfmIssueCounter<"BWPort7", "uops_executed_port:port_7">
57 ];
4958 }
59 def : PfmCountersBinding<"broadwell", BroadwellPfmCounters>;
5060
51 let SchedModel = SkylakeClientModel in {
52 def SKLCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
53 def SKLPort0Counter : PfmIssueCounter;
54 def SKLPort1Counter : PfmIssueCounter;
55 def SKLPort2Counter : PfmIssueCounter;
56 def SKLPort3Counter : PfmIssueCounter;
57 def SKLPort4Counter : PfmIssueCounter;
58 def SKLPort5Counter : PfmIssueCounter;
59 def SKLPort6Counter : PfmIssueCounter;
60 def SKLPort7Counter : PfmIssueCounter;
61 def SKLUopsCounter : PfmUopsCounter<"uops_issued:any">;
61 def SkylakeClientPfmCounters : ProcPfmCounters {
62 let CycleCounter = UnhaltedCoreCyclesPfmCounter;
63 let UopsCounter = UopsIssuedPfmCounter;
64 let IssueCounters = [
65 PfmIssueCounter<"SKLPort0", "uops_dispatched_port:port_0">,
66 PfmIssueCounter<"SKLPort1", "uops_dispatched_port:port_1">,
67 PfmIssueCounter<"SKLPort2", "uops_dispatched_port:port_2">,
68 PfmIssueCounter<"SKLPort3", "uops_dispatched_port:port_3">,
69 PfmIssueCounter<"SKLPort4", "uops_dispatched_port:port_4">,
70 PfmIssueCounter<"SKLPort5", "uops_dispatched_port:port_5">,
71 PfmIssueCounter<"SKLPort6", "uops_dispatched_port:port_6">,
72 PfmIssueCounter<"SKLPort7", "uops_dispatched_port:port_7">
73 ];
6274 }
75 def : PfmCountersBinding<"skylake", SkylakeClientPfmCounters>;
6376
64 let SchedModel = SkylakeServerModel in {
65 def SKXCycleCounter : PfmCycleCounter<"unhalted_core_cycles">;
66 def SKXPort0Counter : PfmIssueCounter;
67 def SKXPort1Counter : PfmIssueCounter;
68 def SKXPort2Counter : PfmIssueCounter;
69 def SKXPort3Counter : PfmIssueCounter;
70 def SKXPort4Counter : PfmIssueCounter;
71 def SKXPort5Counter : PfmIssueCounter;
72 def SKXPort6Counter : PfmIssueCounter;
73 def SKXPort7Counter : PfmIssueCounter;
74 def SKXUopsCounter : PfmUopsCounter<"uops_issued:any">;
77 def SkylakeServerPfmCounters : ProcPfmCounters {
78 let CycleCounter = UnhaltedCoreCyclesPfmCounter;
79 let UopsCounter = UopsIssuedPfmCounter;
80 let IssueCounters = [
81 PfmIssueCounter<"SKXPort0", "uops_dispatched_port:port_0">,
82 PfmIssueCounter<"SKXPort1", "uops_dispatched_port:port_1">,
83 PfmIssueCounter<"SKXPort2", "uops_dispatched_port:port_2">,
84 PfmIssueCounter<"SKXPort3", "uops_dispatched_port:port_3">,
85 PfmIssueCounter<"SKXPort4", "uops_dispatched_port:port_4">,
86 PfmIssueCounter<"SKXPort5", "uops_dispatched_port:port_5">,
87 PfmIssueCounter<"SKXPort6", "uops_dispatched_port:port_6">,
88 PfmIssueCounter<"SKXPort7", "uops_dispatched_port:port_7">
89 ];
7590 }
91 def : PfmCountersBinding<"skylake-avx512", SkylakeServerPfmCounters>;
7692
77 let SchedModel = BtVer2Model in {
78 def JCycleCounter : PfmCycleCounter<"cpu_clk_unhalted">;
79 def JUopsCounter : PfmUopsCounter<"retired_uops">;
80 def JFPU0Counter : PfmIssueCounter;
81 def JFPU1Counter : PfmIssueCounter;
93 def BtVer2PfmCounters : ProcPfmCounters {
94 let CycleCounter = PfmCounter<"cpu_clk_unhalted">;
95 let UopsCounter = PfmCounter<"retired_uops">;
96 let IssueCounters = [
97 PfmIssueCounter<"JFPU0", "dispatched_fpu:pipe0">,
98 PfmIssueCounter<"JFPU1", "dispatched_fpu:pipe1">
99 ];
82100 }
101 def : PfmCountersBinding<"btver2", BtVer2PfmCounters>;
5252 } // namespace
5353
5454 class ExegesisAArch64Target : public ExegesisTarget {
55 public:
56 ExegesisAArch64Target() : ExegesisTarget({}) {}
57
58 private:
5559 std::vector setRegTo(const llvm::MCSubtargetInfo &STI,
5660 unsigned Reg,
5761 const llvm::APInt &Value) const override {
1111 #include "Assembler.h"
1212 #include "BenchmarkRunner.h"
1313 #include "MCInstrDescView.h"
14 #include "PerfHelper.h"
15 #include "Target.h"
1416 #include "llvm/ADT/STLExtras.h"
1517 #include "llvm/MC/MCInst.h"
1618 #include "llvm/MC/MCInstBuilder.h"
164166 }
165167
166168 const char *LatencyBenchmarkRunner::getCounterName() const {
167 if (!State.getSubtargetInfo().getSchedModel().hasExtraProcessorInfo())
168 llvm::report_fatal_error("sched model is missing extra processor info!");
169 const char *CounterName = State.getSubtargetInfo()
170 .getSchedModel()
171 .getExtraProcessorInfo()
172 .PfmCounters.CycleCounter;
169 const char *CounterName = State.getPfmCounters().CycleCounter;
173170 if (!CounterName)
174171 llvm::report_fatal_error("sched model does not define a cycle counter");
175172 return CounterName;
3535 llvm::errs() << "no exegesis target for " << Triple << ", using default\n";
3636 TheExegesisTarget = &ExegesisTarget::getDefault();
3737 }
38 PfmCounters = &TheExegesisTarget->getPfmCounters(CpuName);
39
3840 RATC.reset(new RegisterAliasingTrackerCache(
3941 getRegInfo(), getFunctionReservedRegs(getTargetMachine())));
4042 IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
4143 }
4244
43 LLVMState::LLVMState()
45 LLVMState::LLVMState(const std::string &CpuName)
4446 : LLVMState(llvm::sys::getProcessTriple(),
45 llvm::sys::getHostCPUName().str()) {}
47 CpuName.empty() ? llvm::sys::getHostCPUName().str() : CpuName) {
48 }
4649
4750 std::unique_ptr
4851 LLVMState::createTargetMachine() const {
2929 namespace exegesis {
3030
3131 class ExegesisTarget;
32 class PfmCountersInfo;
3233
3334 // An object to initialize LLVM and prepare objects needed to run the
3435 // measurements.
3536 class LLVMState {
3637 public:
37 LLVMState();
38 // Uses the host triple. If CpuName is empty, uses the host CPU.
39 LLVMState(const std::string &CpuName);
3840
3941 LLVMState(const std::string &Triple,
4042 const std::string &CpuName); // For tests.
5658 const llvm::MCSubtargetInfo &getSubtargetInfo() const {
5759 return *TargetMachine->getMCSubtargetInfo();
5860 }
61
5962 const RegisterAliasingTrackerCache &getRATC() const { return *RATC; }
6063 const InstructionsCache &getIC() const { return *IC; }
64
65 const PfmCountersInfo &getPfmCounters() const { return *PfmCounters; }
6166
6267 private:
6368 const ExegesisTarget *TheExegesisTarget;
6469 std::unique_ptr TargetMachine;
6570 std::unique_ptr RATC;
6671 std::unique_ptr IC;
72 const PfmCountersInfo *PfmCounters;
6773 };
6874
6975 } // namespace exegesis
8484 return llvm::make_unique(State);
8585 }
8686
87 static_assert(std::is_pod::value,
88 "We shouldn't have dynamic initialization here");
89 const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr};
90
91 const PfmCountersInfo &
92 ExegesisTarget::getPfmCounters(llvm::StringRef CpuName) const {
93 assert(std::is_sorted(
94 CpuPfmCounters.begin(), CpuPfmCounters.end(),
95 [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
96 return strcmp(LHS.CpuName, RHS.CpuName) < 0;
97 }) &&
98 "CpuPfmCounters table is not sorted");
99
100 // Find entry
101 auto Found =
102 std::lower_bound(CpuPfmCounters.begin(), CpuPfmCounters.end(), CpuName);
103 if (Found == CpuPfmCounters.end() ||
104 llvm::StringRef(Found->CpuName) != CpuName) {
105 return PfmCountersInfo::Default;
106 }
107 assert(Found->PCI && "Missing counters");
108 return *Found->PCI;
109 }
110
87111 namespace {
88112
89113 // Default implementation.
90114 class ExegesisDefaultTarget : public ExegesisTarget {
115 public:
116 ExegesisDefaultTarget() : ExegesisTarget({}) {}
117
91118 private:
92119 std::vector setRegTo(const llvm::MCSubtargetInfo &STI,
93120 unsigned Reg,
3030 namespace llvm {
3131 namespace exegesis {
3232
33 struct PfmCountersInfo {
34 // An optional name of a performance counter that can be used to measure
35 // cycles.
36 const char *const CycleCounter;
37
38 // An optional name of a performance counter that can be used to measure
39 // uops.
40 const char *const UopsCounter;
41
42 // An IssueCounter specifies how to measure uops issued to specific proc
43 // resources.
44 struct IssueCounter {
45 const char *const Counter;
46 // The name of the ProcResource that this counter measures.
47 const char *const ProcResName;
48 };
49 // An optional list of IssueCounters.
50 const IssueCounter *const IssueCounters;
51 const unsigned NumIssueCounters;
52
53 static const PfmCountersInfo Default;
54 };
55
56 struct CpuAndPfmCounters {
57 const char *const CpuName;
58 const PfmCountersInfo *const PCI;
59 bool operator<(llvm::StringRef S) const {
60 return llvm::StringRef(CpuName) < S;
61 }
62 };
63
3364 class ExegesisTarget {
3465 public:
66 explicit ExegesisTarget(llvm::ArrayRef CpuPfmCounters)
67 : CpuPfmCounters(CpuPfmCounters) {}
68
3569 // Targets can use this to add target-specific passes in assembleToStream();
3670 virtual void addTargetSpecificPasses(llvm::PassManagerBase &PM) const {}
3771
82116
83117 virtual ~ExegesisTarget();
84118
119 // Returns the Pfm counters for the given CPU (or the default if no pfm
120 // counters are defined for this CPU).
121 const PfmCountersInfo &getPfmCounters(llvm::StringRef CpuName) const;
122
85123 private:
86124 virtual bool matchesArch(llvm::Triple::ArchType Arch) const = 0;
87125
97135 const LLVMState &State) const;
98136
99137 const ExegesisTarget *Next = nullptr;
138 const llvm::ArrayRef CpuPfmCounters;
100139 };
101140
102141 } // namespace exegesis
222222
223223 llvm::Expected>
224224 UopsBenchmarkRunner::runMeasurements(const FunctionExecutor &Executor) const {
225 const auto &SchedModel = State.getSubtargetInfo().getSchedModel();
226
227225 std::vector Result;
228 const auto &PfmCounters = SchedModel.getExtraProcessorInfo().PfmCounters;
226 const PfmCountersInfo &PCI = State.getPfmCounters();
229227 // Uops per port.
230 for (unsigned ProcResIdx = 1;
231 ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
232 const char *const Counters = PfmCounters.IssueCounters[ProcResIdx];
233 if (!Counters)
228 for (const auto *IssueCounter = PCI.IssueCounters,
229 *IssueCounterEnd = PCI.IssueCounters + PCI.NumIssueCounters;
230 IssueCounter != IssueCounterEnd; ++IssueCounter) {
231 if (!IssueCounter->Counter)
234232 continue;
235 auto ExpectedCounterValue = Executor.runAndMeasure(Counters);
233 auto ExpectedCounterValue = Executor.runAndMeasure(IssueCounter->Counter);
236234 if (!ExpectedCounterValue)
237235 return ExpectedCounterValue.takeError();
238 Result.push_back(BenchmarkMeasure::Create(
239 SchedModel.getProcResource(ProcResIdx)->Name, *ExpectedCounterValue));
236 Result.push_back(BenchmarkMeasure::Create(IssueCounter->ProcResName,
237 *ExpectedCounterValue));
240238 }
241239 // NumMicroOps.
242 if (const char *const UopsCounter = PfmCounters.UopsCounter) {
240 if (const char *const UopsCounter = PCI.UopsCounter) {
243241 auto ExpectedCounterValue = Executor.runAndMeasure(UopsCounter);
244242 if (!ExpectedCounterValue)
245243 return ExpectedCounterValue.takeError();
328328 std::vector Instructions;
329329 };
330330
331 #include "X86GenExegesis.inc"
332
331333 class ExegesisX86Target : public ExegesisTarget {
334 public:
335 ExegesisX86Target() : ExegesisTarget(X86CpuPfmCounters) {}
336
337 private:
332338 void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override {
333339 // Lowers FP pseudo-instructions, e.g. ABS_Fp32 -> ABS_F.
334340 PM.add(llvm::createX86FloatingPointStackifierPass());
9292 static cl::opt
9393 AnalysisInconsistenciesOutputFile("analysis-inconsistencies-output-file",
9494 cl::desc(""), cl::init("-"));
95
96 static cl::opt
97 CpuName("mcpu",
98 cl::desc(
99 "cpu name to use for pfm counters, leave empty to autodetect"),
100 cl::init(""));
101
95102
96103 static ExitOnError ExitOnErr;
97104
320327 LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET();
321328 #endif
322329
323 const LLVMState State;
330 const LLVMState State(CpuName);
324331 const auto Opcodes = getOpcodesOrDie(State.getInstrInfo());
325332
326333 std::vector Configurations;
398405 llvm::InitializeNativeTargetAsmPrinter();
399406 llvm::InitializeNativeTargetDisassembler();
400407 // Read benchmarks.
401 const LLVMState State;
408 const LLVMState State("");
402409 const std::vector Points =
403410 ExitOnErr(InstructionBenchmark::readYamls(State, BenchmarkFile));
404411 llvm::outs() << "Parsed " << Points.size() << " benchmark points\n";
2020 DAGISelMatcher.cpp
2121 DFAPacketizerEmitter.cpp
2222 DisassemblerEmitter.cpp
23 ExegesisEmitter.cpp
2324 FastISelEmitter.cpp
2425 FixedLenDecoderEmitter.cpp
2526 GlobalISelEmitter.cpp
349349 unsigned OpcodeIdx = Opcode2Index[Opcode];
350350 if (OpcodeMasks[OpcodeIdx].first[ProcIndex]) {
351351 std::string Message =
352 "Opcode " + Opcode->getName().str() +
352 "Opcode " + Opcode->getName().str() +
353353 " used by multiple InstructionEquivalenceClass definitions.";
354354 PrintFatalError(EC->getLoc(), Message);
355355 }
485485
486486 // Collect processor RetireControlUnit descriptors if available.
487487 collectRetireControlUnits();
488
489 // Find pfm counter definitions for each processor.
490 collectPfmCounters();
491488
492489 checkCompleteness();
493490 }
17881785 }
17891786 }
17901787
1791 // Collect all the RegisterFile definitions available in this target.
1792 void CodeGenSchedModels::collectPfmCounters() {
1793 for (Record *Def : Records.getAllDerivedDefinitions("PfmIssueCounter")) {
1794 CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
1795 PM.PfmIssueCounterDefs.emplace_back(Def);
1796 }
1797 for (Record *Def : Records.getAllDerivedDefinitions("PfmCycleCounter")) {
1798 CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
1799 if (PM.PfmCycleCounterDef) {
1800 PrintFatalError(Def->getLoc(),
1801 "multiple cycle counters for " +
1802 Def->getValueAsDef("SchedModel")->getName());
1803 }
1804 PM.PfmCycleCounterDef = Def;
1805 }
1806 for (Record *Def : Records.getAllDerivedDefinitions("PfmUopsCounter")) {
1807 CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel"));
1808 if (PM.PfmUopsCounterDef) {
1809 PrintFatalError(Def->getLoc(),
1810 "multiple uops counters for " +
1811 Def->getValueAsDef("SchedModel")->getName());
1812 }
1813 PM.PfmUopsCounterDef = Def;
1814 }
1815 }
1816
18171788 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
18181789 void CodeGenSchedModels::collectProcResources() {
18191790 ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits");
245245 // Optional Retire Control Unit definition.
246246 Record *RetireControlUnit;
247247
248 // List of PfmCounters.
249 RecVec PfmIssueCounterDefs;
250 Record *PfmCycleCounterDef = nullptr;
251 Record *PfmUopsCounterDef = nullptr;
252
253248 CodeGenProcModel(unsigned Idx, std::string Name, Record *MDef,
254249 Record *IDef) :
255250 Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
264259 }
265260
266261 bool hasExtraProcessorInfo() const {
267 return RetireControlUnit || !RegisterFiles.empty() ||
268 !PfmIssueCounterDefs.empty() ||
269 PfmCycleCounterDef != nullptr ||
270 PfmUopsCounterDef != nullptr;
262 return RetireControlUnit || !RegisterFiles.empty();
271263 }
272264
273265 unsigned getProcResourceIdx(Record *PRDef) const;
592584
593585 void collectRegisterFiles();
594586
595 void collectPfmCounters();
596
597587 void collectOptionalProcessorInfo();
598588
599589 std::string createSchedClassName(Record *ItinClassDef,
710710 // Sort the argument attributes for later benefit.
711711 llvm::sort(ArgumentAttributes);
712712 }
713
0 //===- ExegesisEmitter.cpp - Generate exegesis target data ----------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend emits llvm-exegesis information.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/ADT/SmallSet.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/Debug.h"
16 #include "llvm/Support/Format.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/TableGen/Error.h"
19 #include "llvm/TableGen/Record.h"
20 #include "llvm/TableGen/TableGenBackend.h"
21 #include
22 #include
23 #include
24 #include
25 #include
26 #include
27
28 using namespace llvm;
29
30 #define DEBUG_TYPE "exegesis-emitter"
31
32 namespace {
33
34 class ExegesisEmitter {
35 public:
36 ExegesisEmitter(RecordKeeper &RK);
37
38 void run(raw_ostream &OS) const;
39
40 private:
41 unsigned getPfmCounterId(llvm::StringRef Name) const {
42 const auto It = PfmCounterNameTable.find(Name);
43 if (It == PfmCounterNameTable.end())
44 PrintFatalError("no pfm counter id for " + Name);
45 return It->second;
46 }
47
48 // Collects all the ProcPfmCounters definitions available in this target.
49 void emitPfmCounters(raw_ostream &OS) const;
50
51 void emitPfmCountersInfo(const Record &Def,
52 unsigned &IssueCountersTableOffset,
53 raw_ostream &OS) const;
54
55 void emitPfmCountersLookupTable(raw_ostream &OS) const;
56
57 RecordKeeper &Records;
58 std::string Target;
59
60 // Table of counter name -> counter index.
61 const std::map PfmCounterNameTable;
62 };
63
64 static std::map
65 collectPfmCounters(const RecordKeeper &Records) {
66 std::map PfmCounterNameTable;
67 const auto AddPfmCounterName = [&PfmCounterNameTable](
68 const Record *PfmCounterDef) {
69 const llvm::StringRef Counter = PfmCounterDef->getValueAsString("Counter");
70 if (!Counter.empty())
71 PfmCounterNameTable.emplace(Counter, 0);
72 };
73 for (Record *Def : Records.getAllDerivedDefinitions("ProcPfmCounters")) {
74 // Check that ResourceNames are unique.
75 llvm::SmallSet Seen;
76 for (const Record *IssueCounter :
77 Def->getValueAsListOfDefs("IssueCounters")) {
78 const llvm::StringRef ResourceName =
79 IssueCounter->getValueAsString("ResourceName");
80 if (ResourceName.empty())
81 PrintFatalError(IssueCounter->getLoc(), "invalid empty ResourceName");
82 if (!Seen.insert(ResourceName).second)
83 PrintFatalError(IssueCounter->getLoc(),
84 "duplicate ResourceName " + ResourceName);
85 AddPfmCounterName(IssueCounter);
86 }
87 AddPfmCounterName(Def->getValueAsDef("CycleCounter"));
88 AddPfmCounterName(Def->getValueAsDef("UopsCounter"));
89 }
90 unsigned Index = 0;
91 for (auto &NameAndIndex : PfmCounterNameTable)
92 NameAndIndex.second = Index++;
93 return PfmCounterNameTable;
94 }
95
96 ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
97 : Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {
98 std::vector Targets = Records.getAllDerivedDefinitions("Target");
99 if (Targets.size() == 0)
100 PrintFatalError("ERROR: No 'Target' subclasses defined!");
101 if (Targets.size() != 1)
102 PrintFatalError("ERROR: Multiple subclasses of Target defined!");
103 Target = Targets[0]->getName();
104 }
105
106 void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
107 unsigned &IssueCountersTableOffset,
108 raw_ostream &OS) const {
109 const auto CycleCounter =
110 Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");
111 const auto UopsCounter =
112 Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
113 const size_t NumIssueCounters =
114 Def.getValueAsListOfDefs("IssueCounters").size();
115
116 // This is the default, do not emit.
117 if (CycleCounter.empty() && UopsCounter.empty() && NumIssueCounters == 0)
118 return;
119
120 OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
121 << " = {\n";
122
123 // Cycle Counter.
124 if (CycleCounter.empty())
125 OS << " nullptr, // No cycle counter.\n";
126 else
127 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
128 << "], // Cycle counter\n";
129
130 // Uops Counter.
131 if (UopsCounter.empty())
132 OS << " nullptr, // No uops counter.\n";
133 else
134 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)
135 << "], // Uops counter\n";
136
137 // Issue Counters
138 if (NumIssueCounters == 0)
139 OS << " nullptr, // No issue counters.\n 0\n";
140 else
141 OS << " " << Target << "PfmIssueCounters + " << IssueCountersTableOffset
142 << ", " << NumIssueCounters << " // Issue counters.\n";
143
144 OS << "};\n";
145 IssueCountersTableOffset += NumIssueCounters;
146 }
147
148 void ExegesisEmitter::emitPfmCounters(raw_ostream &OS) const {
149 // Emit the counter name table.
150 OS << "\nstatic const char* " << Target << "PfmCounterNames[] = {\n";
151 for (const auto &NameAndIndex : PfmCounterNameTable)
152 OS << " \"" << NameAndIndex.first << "\", // " << NameAndIndex.second
153 << "\n";
154 OS << "};\n\n";
155
156 // Emit the IssueCounters table.
157 const auto PfmCounterDefs =
158 Records.getAllDerivedDefinitions("ProcPfmCounters");
159 OS << "static const PfmCountersInfo::IssueCounter " << Target
160 << "PfmIssueCounters[] = {\n";
161 for (const Record *Def : PfmCounterDefs) {
162 for (const Record *ICDef : Def->getValueAsListOfDefs("IssueCounters"))
163 OS << " { " << Target << "PfmCounterNames["
164 << getPfmCounterId(ICDef->getValueAsString("Counter")) << "], \""
165 << ICDef->getValueAsString("ResourceName") << "\"},\n";
166 }
167
168 OS << "};\n";
169
170 // Now generate the PfmCountersInfo.
171 unsigned IssueCountersTableOffset = 0;
172 for (const Record *Def : PfmCounterDefs)
173 emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);
174
175 OS << "\n";
176 }
177
178 void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {
179 std::vector Bindings =
180 Records.getAllDerivedDefinitions("PfmCountersBinding");
181 llvm::sort(Bindings, [](const Record *L, const Record *R) {
182 return L->getValueAsString("CpuName") < R->getValueAsString("CpuName");
183 });
184
185 OS << "// Sorted (by CpuName) array of pfm counters.\n"
186 << "static const CpuAndPfmCounters " << Target << "CpuPfmCounters[] = {\n";
187 for (Record *Binding : Bindings) {
188 // Emit as { "cpu", procinit },
189 OS << " { \"" //
190 << Binding->getValueAsString("CpuName") << "\"," //
191 << " &" << Target << Binding->getValueAsDef("Counters")->getName() //
192 << " },\n";
193 }
194 OS << "};\n\n";
195 }
196
197 void ExegesisEmitter::run(raw_ostream &OS) const {
198 emitSourceFileHeader("Exegesis Tables", OS);
199 emitPfmCounters(OS);
200 emitPfmCountersLookupTable(OS);
201 }
202
203 } // end anonymous namespace
204
205 namespace llvm {
206
207 void EmitExegesis(RecordKeeper &RK, raw_ostream &OS) {
208 ExegesisEmitter(RK).run(OS);
209 }
210
211 } // end namespace llvm
696696 return CostTblIndex;
697697 }
698698
699 static bool EmitPfmIssueCountersTable(const CodeGenProcModel &ProcModel,
700 raw_ostream &OS) {
701 unsigned NumCounterDefs = 1 + ProcModel.ProcResourceDefs.size();
702 std::vector CounterDefs(NumCounterDefs);
703 bool HasCounters = false;
704 for (const Record *CounterDef : ProcModel.PfmIssueCounterDefs) {
705 const Record *&CD = CounterDefs[ProcModel.getProcResourceIdx(
706 CounterDef->getValueAsDef("Resource"))];
707 if (CD) {
708 PrintFatalError(CounterDef->getLoc(),
709 "multiple issue counters for " +
710 CounterDef->getValueAsDef("Resource")->getName());
711 }
712 CD = CounterDef;
713 HasCounters = true;
714 }
715 if (!HasCounters) {
716 return false;
717 }
718 OS << "\nstatic const char* " << ProcModel.ModelName
719 << "PfmIssueCounters[] = {\n";
720 for (unsigned i = 0; i != NumCounterDefs; ++i) {
721 const Record *CounterDef = CounterDefs[i];
722 if (CounterDef) {
723 const auto PfmCounters = CounterDef->getValueAsListOfStrings("Counters");
724 if (PfmCounters.empty())
725 PrintFatalError(CounterDef->getLoc(), "empty counter list");
726 OS << " \"" << PfmCounters[0];
727 for (unsigned p = 1, e = PfmCounters.size(); p != e; ++p)
728 OS << ",\" \"" << PfmCounters[p];
729 OS << "\", // #" << i << " = ";
730 OS << CounterDef->getValueAsDef("Resource")->getName() << "\n";
731 } else {
732 OS << " nullptr, // #" << i << "\n";
733 }
734 }
735 OS << "};\n";
736 return true;
737 }
738
739 static void EmitPfmCounters(const CodeGenProcModel &ProcModel,
740 const bool HasPfmIssueCounters, raw_ostream &OS) {
741 OS << " {\n";
742 // Emit the cycle counter.
743 if (ProcModel.PfmCycleCounterDef)
744 OS << " \"" << ProcModel.PfmCycleCounterDef->getValueAsString("Counter")
745 << "\", // Cycle counter.\n";
746 else
747 OS << " nullptr, // No cycle counter.\n";
748
749 // Emit the uops counter.
750 if (ProcModel.PfmUopsCounterDef)
751 OS << " \"" << ProcModel.PfmUopsCounterDef->getValueAsString("Counter")
752 << "\", // Uops counter.\n";
753 else
754 OS << " nullptr, // No uops counter.\n";
755
756 // Emit a reference to issue counters table.
757 if (HasPfmIssueCounters)
758 OS << " " << ProcModel.ModelName << "PfmIssueCounters\n";
759 else
760 OS << " nullptr // No issue counters.\n";
761 OS << " }\n";
762 }
763
764699 void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel,
765700 raw_ostream &OS) {
766701 // Generate a table of register file descriptors (one entry per each user
767702 // defined register file), and a table of register costs.
768703 unsigned NumCostEntries = EmitRegisterFileTables(ProcModel, OS);
769704
770 // Generate a table of ProcRes counter names.
771 const bool HasPfmIssueCounters = EmitPfmIssueCountersTable(ProcModel, OS);
772
773705 // Now generate a table for the extra processor info.
774706 OS << "\nstatic const llvm::MCExtraProcessorInfo " << ProcModel.ModelName
775707 << "ExtraInfo = {\n ";
781713 // file descriptors and register costs).
782714 EmitRegisterFileInfo(ProcModel, ProcModel.RegisterFiles.size(),
783715 NumCostEntries, OS);
784
785 EmitPfmCounters(ProcModel, HasPfmIssueCounters, OS);
786716
787717 OS << "};\n";
788718 }
14091339 }
14101340
14111341 //
1412 // EmitProcessorLookup - generate cpu name to itinerary lookup table.
1342 // EmitProcessorLookup - generate cpu name to sched model lookup tables.
14131343 //
14141344 void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
14151345 // Gather and sort processor information
14171347 Records.getAllDerivedDefinitions("Processor");
14181348 llvm::sort(ProcessorList, LessRecordFieldName());
14191349
1420 // Begin processor table
1350 // Begin processor->sched model table
14211351 OS << "\n";
1422 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
1423 << "extern const llvm::SubtargetInfoKV "
1424 << Target << "ProcSchedKV[] = {\n";
1425
1352 OS << "// Sorted (by key) array of sched model for CPU subtype.\n"
1353 << "extern const llvm::SubtargetInfoKV " << Target
1354 << "ProcSchedKV[] = {\n";
14261355 // For each processor
14271356 for (Record *Processor : ProcessorList) {
14281357 StringRef Name = Processor->getValueAsString("Name");
14321361 // Emit as { "cpu", procinit },
14331362 OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " },\n";
14341363 }
1435
1436 // End processor table
1364 // End processor->sched model table
14371365 OS << "};\n";
14381366 }
14391367
16741602
16751603 // Emit target predicates.
16761604 emitSchedModelHelpersImpl(OS);
1677
1605
16781606 OS << "} // " << ClassName << "::resolveSchedClass\n\n";
16791607
16801608 OS << "unsigned " << ClassName
5252 GenX86EVEX2VEXTables,
5353 GenX86FoldTables,
5454 GenRegisterBank,
55 GenExegesis,
5556 };
5657
5758 namespace {
116117 clEnumValN(GenX86FoldTables, "gen-x86-fold-tables",
117118 "Generate X86 fold tables"),
118119 clEnumValN(GenRegisterBank, "gen-register-bank",
119 "Generate registers bank descriptions")));
120 "Generate registers bank descriptions"),
121 clEnumValN(GenExegesis, "gen-exegesis",
122 "Generate llvm-exegesis tables")));
120123
121124 cl::OptionCategory PrintEnumsCat("Options for -print-enums");
122125 cl::opt
230233 case GenX86FoldTables:
231234 EmitX86FoldTables(Records, OS);
232235 break;
236 case GenExegesis:
237 EmitExegesis(Records, OS);
238 break;
233239 }
234240
235241 return false;
8888 void EmitX86EVEX2VEXTables(RecordKeeper &RK, raw_ostream &OS);
8989 void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &OS);
9090 void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS);
91 void EmitExegesis(RecordKeeper &RK, raw_ostream &OS);
9192
9293 } // End llvm namespace
9394