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 "llvm/ADT/Triple.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 34 namespace llvm { 35 namespace exegesis { 36 37 extern cl::OptionCategory Options; 38 extern cl::OptionCategory BenchmarkOptions; 39 extern cl::OptionCategory AnalysisOptions; 40 41 struct PfmCountersInfo { 42 // An optional name of a performance counter that can be used to measure 43 // cycles. 44 const char *CycleCounter; 45 46 // An optional name of a performance counter that can be used to measure 47 // uops. 48 const char *UopsCounter; 49 50 // An IssueCounter specifies how to measure uops issued to specific proc 51 // resources. 52 struct IssueCounter { 53 const char *Counter; 54 // The name of the ProcResource that this counter measures. 55 const char *ProcResName; 56 }; 57 // An optional list of IssueCounters. 58 const IssueCounter *IssueCounters; 59 unsigned NumIssueCounters; 60 61 static const PfmCountersInfo Default; 62 }; 63 64 struct CpuAndPfmCounters { 65 const char *CpuName; 66 const PfmCountersInfo *PCI; 67 bool operator<(StringRef S) const { return StringRef(CpuName) < S; } 68 }; 69 70 class ExegesisTarget { 71 public: ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters)72 explicit ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters) 73 : CpuPfmCounters(CpuPfmCounters) {} 74 75 // Targets can use this to create target-specific perf counters. 76 virtual Expected<std::unique_ptr<pfm::Counter>> 77 createCounter(StringRef CounterName, const LLVMState &State) const; 78 79 // Targets can use this to add target-specific passes in assembleToStream(); addTargetSpecificPasses(PassManagerBase & PM)80 virtual void addTargetSpecificPasses(PassManagerBase &PM) const {} 81 82 // Generates code to move a constant into a the given register. 83 // Precondition: Value must fit into Reg. 84 virtual std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg, 85 const APInt &Value) const = 0; 86 87 // Returns the register pointing to scratch memory, or 0 if this target 88 // does not support memory operands. The benchmark function uses the 89 // default calling convention. getScratchMemoryRegister(const Triple &)90 virtual unsigned getScratchMemoryRegister(const Triple &) const { return 0; } 91 92 // Fills memory operands with references to the address at [Reg] + Offset. fillMemoryOperands(InstructionTemplate & IT,unsigned Reg,unsigned Offset)93 virtual void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, 94 unsigned Offset) const { 95 llvm_unreachable( 96 "fillMemoryOperands() requires getScratchMemoryRegister() > 0"); 97 } 98 99 // Returns a counter usable as a loop counter. getLoopCounterRegister(const Triple &)100 virtual unsigned getLoopCounterRegister(const Triple &) const { return 0; } 101 102 // Adds the code to decrement the loop counter and decrementLoopCounterAndJump(MachineBasicBlock & MBB,MachineBasicBlock & TargetMBB,const MCInstrInfo & MII)103 virtual void decrementLoopCounterAndJump(MachineBasicBlock &MBB, 104 MachineBasicBlock &TargetMBB, 105 const MCInstrInfo &MII) const { 106 llvm_unreachable("decrementLoopCounterAndBranch() requires " 107 "getLoopCounterRegister() > 0"); 108 } 109 110 // Returns a list of unavailable registers. 111 // Targets can use this to prevent some registers to be automatically selected 112 // for use in snippets. getUnavailableRegisters()113 virtual ArrayRef<unsigned> getUnavailableRegisters() const { return {}; } 114 115 // Returns the maximum number of bytes a load/store instruction can access at 116 // once. This is typically the size of the largest register available on the 117 // processor. Note that this only used as a hint to generate independant 118 // load/stores to/from memory, so the exact returned value does not really 119 // matter as long as it's large enough. getMaxMemoryAccessSize()120 virtual unsigned getMaxMemoryAccessSize() const { return 0; } 121 122 // Assigns a random operand of the right type to variable Var. 123 // The target is responsible for handling any operand starting from 124 // OPERAND_FIRST_TARGET. randomizeTargetMCOperand(const Instruction & Instr,const Variable & Var,MCOperand & AssignedValue,const BitVector & ForbiddenRegs)125 virtual Error randomizeTargetMCOperand(const Instruction &Instr, 126 const Variable &Var, 127 MCOperand &AssignedValue, 128 const BitVector &ForbiddenRegs) const { 129 return make_error<Failure>( 130 "targets with target-specific operands should implement this"); 131 } 132 133 // Returns true if this instruction is supported as a back-to-back 134 // instructions. 135 // FIXME: Eventually we should discover this dynamically. allowAsBackToBack(const Instruction & Instr)136 virtual bool allowAsBackToBack(const Instruction &Instr) const { 137 return true; 138 } 139 140 // For some instructions, it is interesting to measure how it's performance 141 // characteristics differ depending on it's operands. 142 // This allows us to produce all the interesting variants. 143 virtual std::vector<InstructionTemplate> generateInstructionVariants(const Instruction & Instr,unsigned MaxConfigsPerOpcode)144 generateInstructionVariants(const Instruction &Instr, 145 unsigned MaxConfigsPerOpcode) const { 146 // By default, we're happy with whatever randomizer will give us. 147 return {&Instr}; 148 } 149 150 // Checks hardware and software support for current benchmark mode. 151 // Returns an error if the target host does not have support to run the 152 // benchmark. checkFeatureSupport()153 virtual Error checkFeatureSupport() const { return Error::success(); } 154 155 // Creates a snippet generator for the given mode. 156 std::unique_ptr<SnippetGenerator> 157 createSnippetGenerator(InstructionBenchmark::ModeE Mode, 158 const LLVMState &State, 159 const SnippetGenerator::Options &Opts) const; 160 // Creates a benchmark runner for the given mode. 161 Expected<std::unique_ptr<BenchmarkRunner>> createBenchmarkRunner( 162 InstructionBenchmark::ModeE Mode, const LLVMState &State, 163 BenchmarkPhaseSelectorE BenchmarkPhaseSelector, 164 InstructionBenchmark::ResultAggregationModeE ResultAggMode = 165 InstructionBenchmark::Min) const; 166 167 // Returns the ExegesisTarget for the given triple or nullptr if the target 168 // does not exist. 169 static const ExegesisTarget *lookup(Triple TT); 170 // Returns the default (unspecialized) ExegesisTarget. 171 static const ExegesisTarget &getDefault(); 172 // Registers a target. Not thread safe. 173 static void registerTarget(ExegesisTarget *T); 174 175 virtual ~ExegesisTarget(); 176 177 // Returns the Pfm counters for the given CPU (or the default if no pfm 178 // counters are defined for this CPU). 179 const PfmCountersInfo &getPfmCounters(StringRef CpuName) const; 180 181 // Saves the CPU state that needs to be preserved when running a benchmark, 182 // and returns and RAII object that restores the state on destruction. 183 // By default no state is preserved. 184 struct SavedState { 185 virtual ~SavedState(); 186 }; withSavedState()187 virtual std::unique_ptr<SavedState> withSavedState() const { 188 return std::make_unique<SavedState>(); 189 } 190 191 private: 192 virtual bool matchesArch(Triple::ArchType Arch) const = 0; 193 194 // Targets can implement their own snippet generators/benchmarks runners by 195 // implementing these. 196 std::unique_ptr<SnippetGenerator> virtual createSerialSnippetGenerator( 197 const LLVMState &State, const SnippetGenerator::Options &Opts) const; 198 std::unique_ptr<SnippetGenerator> virtual createParallelSnippetGenerator( 199 const LLVMState &State, const SnippetGenerator::Options &Opts) const; 200 std::unique_ptr<BenchmarkRunner> virtual createLatencyBenchmarkRunner( 201 const LLVMState &State, InstructionBenchmark::ModeE Mode, 202 BenchmarkPhaseSelectorE BenchmarkPhaseSelector, 203 InstructionBenchmark::ResultAggregationModeE ResultAggMode) const; 204 std::unique_ptr<BenchmarkRunner> virtual createUopsBenchmarkRunner( 205 const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, 206 InstructionBenchmark::ResultAggregationModeE ResultAggMode) const; 207 208 const ExegesisTarget *Next = nullptr; 209 const ArrayRef<CpuAndPfmCounters> CpuPfmCounters; 210 }; 211 212 } // namespace exegesis 213 } // namespace llvm 214 215 #endif // LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H 216