1//===-- Target.h ------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10///
11/// Classes that handle the creation of target-specific objects. This is
12/// similar to Target/TargetRegistry.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H
17#define LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H
18
19#include "BenchmarkResult.h"
20#include "BenchmarkRunner.h"
21#include "Error.h"
22#include "LlvmState.h"
23#include "PerfHelper.h"
24#include "SnippetGenerator.h"
25#include "ValidationEvent.h"
26#include "llvm/CodeGen/TargetPassConfig.h"
27#include "llvm/IR/CallingConv.h"
28#include "llvm/IR/LegacyPassManager.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCRegisterInfo.h"
31#include "llvm/Support/CommandLine.h"
32#include "llvm/Support/Error.h"
33#include "llvm/TargetParser/SubtargetFeature.h"
34#include "llvm/TargetParser/Triple.h"
35
36namespace llvm {
37namespace exegesis {
38
39extern cl::OptionCategory Options;
40extern cl::OptionCategory BenchmarkOptions;
41extern cl::OptionCategory AnalysisOptions;
42
43struct PfmCountersInfo {
44 // An optional name of a performance counter that can be used to measure
45 // cycles.
46 const char *CycleCounter;
47
48 // Optional raw PMU encoding for Cycle counter.
49 int CycleCounterEventSelect;
50 int CycleCounterUMask;
51
52 // An optional name of a performance counter that can be used to measure
53 // uops.
54 const char *UopsCounter;
55
56 // Optional raw PMU encoding for Uops counter.
57 int UopsCounterEventSelect;
58 int UopsCounterUMask;
59
60 // An IssueCounter specifies how to measure uops issued to specific proc
61 // resources.
62 struct IssueCounter {
63 const char *Counter;
64 // The name of the ProcResource that this counter measures.
65 const char *ProcResName;
66 };
67 // An optional list of IssueCounters.
68 const IssueCounter *IssueCounters;
69 unsigned NumIssueCounters;
70
71 const std::pair<ValidationEvent, const char *> *ValidationEvents;
72 unsigned NumValidationEvents;
73
74 static const PfmCountersInfo Default;
75 static const PfmCountersInfo Dummy;
76};
77
78struct CpuAndPfmCounters {
79 const char *CpuName;
80 const PfmCountersInfo *PCI;
81 bool operator<(StringRef S) const { return StringRef(CpuName) < S; }
82};
83
84class ExegesisTarget {
85public:
86 typedef bool (*OpcodeAvailabilityChecker)(unsigned, const FeatureBitset &);
87 ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters,
88 OpcodeAvailabilityChecker IsOpcodeAvailable)
89 : CpuPfmCounters(CpuPfmCounters), IsOpcodeAvailable(IsOpcodeAvailable) {}
90
91 // Targets can use this to create target-specific perf counters.
92 virtual Expected<std::unique_ptr<pfm::CounterGroup>>
93 createCounter(StringRef CounterName, const LLVMState &State,
94 ArrayRef<const char *> ValidationCounters,
95 const pid_t ProcessID = 0) const;
96
97 // Targets can use this to add target-specific passes in assembleToStream();
98 virtual void addTargetSpecificPasses(PassManagerBase &PM) const {}
99
100 // Generates code to move a constant into a the given register.
101 // Precondition: Value must fit into Reg.
102 virtual std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI,
103 MCRegister Reg,
104 const APInt &Value) const = 0;
105
106 // Generates the code for the lower munmap call. The code generated by this
107 // function may clobber registers.
108 virtual void generateLowerMunmap(std::vector<MCInst> &GeneratedCode) const {
109 report_fatal_error(
110 reason: "generateLowerMunmap is not implemented on the current architecture");
111 }
112
113 // Generates the upper munmap call. The code generated by this function may
114 // clobber registers.
115 virtual void generateUpperMunmap(std::vector<MCInst> &GeneratedCode) const {
116 report_fatal_error(
117 reason: "generateUpperMunmap is not implemented on the current architecture");
118 }
119
120 // Generates the code for an exit syscall. The code generated by this function
121 // may clobber registers.
122 virtual std::vector<MCInst> generateExitSyscall(unsigned ExitCode) const {
123 report_fatal_error(
124 reason: "generateExitSyscall is not implemented on the current architecture");
125 }
126
127 // Generates the code to mmap a region of code. The code generated by this
128 // function may clobber registers.
129 virtual std::vector<MCInst>
130 generateMmap(uintptr_t Address, size_t Length,
131 uintptr_t FileDescriptorAddress) const {
132 report_fatal_error(
133 reason: "generateMmap is not implemented on the current architecture");
134 }
135
136 // Generates the mmap code for the aux memory. The code generated by this
137 // function may clobber registers.
138 virtual void generateMmapAuxMem(std::vector<MCInst> &GeneratedCode) const {
139 report_fatal_error(
140 reason: "generateMmapAuxMem is not implemented on the current architecture\n");
141 }
142
143 // Moves argument registers into other registers that won't get clobbered
144 // while making syscalls. The code generated by this function may clobber
145 // registers.
146 virtual void moveArgumentRegisters(std::vector<MCInst> &GeneratedCode) const {
147 report_fatal_error(reason: "moveArgumentRegisters is not implemented on the "
148 "current architecture\n");
149 }
150
151 // Generates code to move argument registers, unmap memory above and below the
152 // snippet, and map the auxiliary memory into the subprocess. The code
153 // generated by this function may clobber registers.
154 virtual std::vector<MCInst> generateMemoryInitialSetup() const {
155 report_fatal_error(reason: "generateMemoryInitialSetup is not supported on the "
156 "current architecture\n");
157 }
158
159 // Returns true if all features are available that are required by Opcode.
160 virtual bool isOpcodeAvailable(unsigned Opcode,
161 const FeatureBitset &Features) const {
162 return IsOpcodeAvailable(Opcode, Features);
163 }
164
165 virtual const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,
166 unsigned Opcode) const;
167
168 // Sets the stack register to the auxiliary memory so that operations
169 // requiring the stack can be formed (e.g., setting large registers). The code
170 // generated by this function may clobber registers.
171 virtual std::vector<MCInst> setStackRegisterToAuxMem() const {
172 report_fatal_error(reason: "setStackRegisterToAuxMem is not implemented on the "
173 "current architectures");
174 }
175
176 virtual uintptr_t getAuxiliaryMemoryStartAddress() const {
177 report_fatal_error(reason: "getAuxiliaryMemoryStartAddress is not implemented on "
178 "the current architecture");
179 }
180
181 // Generates the necessary ioctl system calls to configure the perf counters.
182 // The code generated by this function preserves all registers if the
183 // parameter SaveRegisters is set to true.
184 virtual std::vector<MCInst> configurePerfCounter(long Request,
185 bool SaveRegisters) const {
186 report_fatal_error(
187 reason: "configurePerfCounter is not implemented on the current architecture");
188 }
189
190 // Gets the ABI dependent registers that are used to pass arguments in a
191 // function call.
192 virtual std::vector<MCRegister> getArgumentRegisters() const {
193 report_fatal_error(
194 reason: "getArgumentRegisters is not implemented on the current architecture");
195 };
196
197 // Gets the registers that might potentially need to be saved by while
198 // the setup in the test harness executes.
199 virtual std::vector<MCRegister> getRegistersNeedSaving() const {
200 report_fatal_error(reason: "getRegistersNeedSaving is not implemented on the "
201 "current architecture");
202 };
203
204 // Returns the register pointing to scratch memory, or 0 if this target
205 // does not support memory operands. The benchmark function uses the
206 // default calling convention.
207 virtual MCRegister getScratchMemoryRegister(const Triple &) const {
208 return MCRegister();
209 }
210
211 // Fills memory operands with references to the address at [Reg] + Offset.
212 virtual void fillMemoryOperands(InstructionTemplate &IT, MCRegister Reg,
213 unsigned Offset) const {
214 llvm_unreachable(
215 "fillMemoryOperands() requires getScratchMemoryRegister() > 0");
216 }
217
218 // Returns a counter usable as a loop counter.
219 virtual MCRegister getDefaultLoopCounterRegister(const Triple &) const {
220 return MCRegister();
221 }
222
223 // Adds the code to decrement the loop counter and
224 virtual void decrementLoopCounterAndJump(MachineBasicBlock &MBB,
225 MachineBasicBlock &TargetMBB,
226 const MCInstrInfo &MII,
227 MCRegister LoopRegister) const {
228 llvm_unreachable("decrementLoopCounterAndBranch() requires "
229 "getLoopCounterRegister() > 0");
230 }
231
232 // Returns a list of unavailable registers.
233 // Targets can use this to prevent some registers to be automatically selected
234 // for use in snippets.
235 virtual ArrayRef<MCPhysReg> getUnavailableRegisters() const { return {}; }
236
237 // Returns the maximum number of bytes a load/store instruction can access at
238 // once. This is typically the size of the largest register available on the
239 // processor. Note that this only used as a hint to generate independant
240 // load/stores to/from memory, so the exact returned value does not really
241 // matter as long as it's large enough.
242 virtual unsigned getMaxMemoryAccessSize() const { return 0; }
243
244 // Assigns a random operand of the right type to variable Var.
245 // The target is responsible for handling any operand starting from
246 // OPERAND_FIRST_TARGET.
247 virtual Error randomizeTargetMCOperand(const Instruction &Instr,
248 const Variable &Var,
249 MCOperand &AssignedValue,
250 const BitVector &ForbiddenRegs) const {
251 return make_error<Failure>(
252 Args: "targets with target-specific operands should implement this");
253 }
254
255 // Returns true if this instruction is supported as a back-to-back
256 // instructions.
257 // FIXME: Eventually we should discover this dynamically.
258 virtual bool allowAsBackToBack(const Instruction &Instr) const {
259 return true;
260 }
261
262 // For some instructions, it is interesting to measure how it's performance
263 // characteristics differ depending on it's operands.
264 // This allows us to produce all the interesting variants.
265 virtual std::vector<InstructionTemplate>
266 generateInstructionVariants(const Instruction &Instr,
267 unsigned MaxConfigsPerOpcode) const {
268 // By default, we're happy with whatever randomizer will give us.
269 return {&Instr};
270 }
271
272 // Checks hardware and software support for current benchmark mode.
273 // Returns an error if the target host does not have support to run the
274 // benchmark.
275 virtual Error checkFeatureSupport() const { return Error::success(); }
276
277 // Creates a snippet generator for the given mode.
278 std::unique_ptr<SnippetGenerator>
279 createSnippetGenerator(Benchmark::ModeE Mode,
280 const LLVMState &State,
281 const SnippetGenerator::Options &Opts) const;
282 // Creates a benchmark runner for the given mode.
283 Expected<std::unique_ptr<BenchmarkRunner>> createBenchmarkRunner(
284 Benchmark::ModeE Mode, const LLVMState &State,
285 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
286 BenchmarkRunner::ExecutionModeE ExecutionMode,
287 unsigned BenchmarkRepeatCount,
288 ArrayRef<ValidationEvent> ValidationCounters,
289 Benchmark::ResultAggregationModeE ResultAggMode = Benchmark::Min) const;
290
291 // Returns the ExegesisTarget for the given triple or nullptr if the target
292 // does not exist.
293 static const ExegesisTarget *lookup(Triple TT);
294 // Returns the default (unspecialized) ExegesisTarget.
295 static const ExegesisTarget &getDefault();
296 // Registers a target. Not thread safe.
297 static void registerTarget(ExegesisTarget *T);
298
299 virtual ~ExegesisTarget();
300
301 // Returns the Pfm counters for the given CPU (or the default if no pfm
302 // counters are defined for this CPU).
303 const PfmCountersInfo &getPfmCounters(StringRef CpuName) const;
304
305 // Returns dummy Pfm counters which can be used to execute generated snippet
306 // without access to performance counters.
307 const PfmCountersInfo &getDummyPfmCounters() const;
308
309 // Saves the CPU state that needs to be preserved when running a benchmark,
310 // and returns and RAII object that restores the state on destruction.
311 // By default no state is preserved.
312 struct SavedState {
313 virtual ~SavedState();
314 };
315 virtual std::unique_ptr<SavedState> withSavedState() const {
316 return std::make_unique<SavedState>();
317 }
318
319private:
320 virtual bool matchesArch(Triple::ArchType Arch) const = 0;
321
322 // Targets can implement their own snippet generators/benchmarks runners by
323 // implementing these.
324 std::unique_ptr<SnippetGenerator> virtual createSerialSnippetGenerator(
325 const LLVMState &State, const SnippetGenerator::Options &Opts) const;
326 std::unique_ptr<SnippetGenerator> virtual createParallelSnippetGenerator(
327 const LLVMState &State, const SnippetGenerator::Options &Opts) const;
328 std::unique_ptr<BenchmarkRunner> virtual createLatencyBenchmarkRunner(
329 const LLVMState &State, Benchmark::ModeE Mode,
330 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
331 Benchmark::ResultAggregationModeE ResultAggMode,
332 BenchmarkRunner::ExecutionModeE ExecutionMode,
333 ArrayRef<ValidationEvent> ValidationCounters,
334 unsigned BenchmarkRepeatCount) const;
335 std::unique_ptr<BenchmarkRunner> virtual createUopsBenchmarkRunner(
336 const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
337 Benchmark::ResultAggregationModeE ResultAggMode,
338 BenchmarkRunner::ExecutionModeE ExecutionMode,
339 ArrayRef<ValidationEvent> ValidationCounters) const;
340
341 const ExegesisTarget *Next = nullptr;
342 const ArrayRef<CpuAndPfmCounters> CpuPfmCounters;
343 const OpcodeAvailabilityChecker IsOpcodeAvailable;
344};
345
346} // namespace exegesis
347} // namespace llvm
348
349#endif // LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H
350