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 "SnippetGenerator.h" 24 #include "llvm/ADT/Triple.h" 25 #include "llvm/CodeGen/TargetPassConfig.h" 26 #include "llvm/IR/CallingConv.h" 27 #include "llvm/IR/LegacyPassManager.h" 28 #include "llvm/MC/MCInst.h" 29 #include "llvm/MC/MCRegisterInfo.h" 30 31 namespace llvm { 32 namespace exegesis { 33 34 struct PfmCountersInfo { 35 // An optional name of a performance counter that can be used to measure 36 // cycles. 37 const char *CycleCounter; 38 39 // An optional name of a performance counter that can be used to measure 40 // uops. 41 const char *UopsCounter; 42 43 // An IssueCounter specifies how to measure uops issued to specific proc 44 // resources. 45 struct IssueCounter { 46 const char *Counter; 47 // The name of the ProcResource that this counter measures. 48 const char *ProcResName; 49 }; 50 // An optional list of IssueCounters. 51 const IssueCounter *IssueCounters; 52 unsigned NumIssueCounters; 53 54 static const PfmCountersInfo Default; 55 }; 56 57 struct CpuAndPfmCounters { 58 const char *CpuName; 59 const PfmCountersInfo *PCI; 60 bool operator<(StringRef S) const { return StringRef(CpuName) < S; } 61 }; 62 63 class ExegesisTarget { 64 public: 65 explicit ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters) 66 : CpuPfmCounters(CpuPfmCounters) {} 67 68 // Targets can use this to add target-specific passes in assembleToStream(); 69 virtual void addTargetSpecificPasses(PassManagerBase &PM) const {} 70 71 // Generates code to move a constant into a the given register. 72 // Precondition: Value must fit into Reg. 73 virtual std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg, 74 const APInt &Value) const = 0; 75 76 // Returns the register pointing to scratch memory, or 0 if this target 77 // does not support memory operands. The benchmark function uses the 78 // default calling convention. 79 virtual unsigned getScratchMemoryRegister(const Triple &) const { return 0; } 80 81 // Fills memory operands with references to the address at [Reg] + Offset. 82 virtual void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, 83 unsigned Offset) const { 84 llvm_unreachable( 85 "fillMemoryOperands() requires getScratchMemoryRegister() > 0"); 86 } 87 88 // Returns a counter usable as a loop counter. 89 virtual unsigned getLoopCounterRegister(const Triple &) const { return 0; } 90 91 // Adds the code to decrement the loop counter and 92 virtual void decrementLoopCounterAndJump(MachineBasicBlock &MBB, 93 MachineBasicBlock &TargetMBB, 94 const MCInstrInfo &MII) const { 95 llvm_unreachable("decrementLoopCounterAndBranch() requires " 96 "getLoopCounterRegister() > 0"); 97 } 98 99 // Returns a list of unavailable registers. 100 // Targets can use this to prevent some registers to be automatically selected 101 // for use in snippets. 102 virtual ArrayRef<unsigned> getUnavailableRegisters() const { return {}; } 103 104 // Returns the maximum number of bytes a load/store instruction can access at 105 // once. This is typically the size of the largest register available on the 106 // processor. Note that this only used as a hint to generate independant 107 // load/stores to/from memory, so the exact returned value does not really 108 // matter as long as it's large enough. 109 virtual unsigned getMaxMemoryAccessSize() const { return 0; } 110 111 // Assigns a random operand of the right type to variable Var. 112 // The target is responsible for handling any operand starting from 113 // OPERAND_FIRST_TARGET. 114 virtual Error randomizeTargetMCOperand(const Instruction &Instr, 115 const Variable &Var, 116 MCOperand &AssignedValue, 117 const BitVector &ForbiddenRegs) const { 118 return make_error<Failure>( 119 "targets with target-specific operands should implement this"); 120 } 121 122 // Returns true if this instruction is supported as a back-to-back 123 // instructions. 124 // FIXME: Eventually we should discover this dynamically. 125 virtual bool allowAsBackToBack(const Instruction &Instr) const { 126 return true; 127 } 128 129 // Creates a snippet generator for the given mode. 130 std::unique_ptr<SnippetGenerator> 131 createSnippetGenerator(InstructionBenchmark::ModeE Mode, 132 const LLVMState &State, 133 const SnippetGenerator::Options &Opts) const; 134 // Creates a benchmark runner for the given mode. 135 std::unique_ptr<BenchmarkRunner> 136 createBenchmarkRunner(InstructionBenchmark::ModeE Mode, 137 const LLVMState &State) const; 138 139 // Returns the ExegesisTarget for the given triple or nullptr if the target 140 // does not exist. 141 static const ExegesisTarget *lookup(Triple TT); 142 // Returns the default (unspecialized) ExegesisTarget. 143 static const ExegesisTarget &getDefault(); 144 // Registers a target. Not thread safe. 145 static void registerTarget(ExegesisTarget *T); 146 147 virtual ~ExegesisTarget(); 148 149 // Returns the Pfm counters for the given CPU (or the default if no pfm 150 // counters are defined for this CPU). 151 const PfmCountersInfo &getPfmCounters(StringRef CpuName) const; 152 153 private: 154 virtual bool matchesArch(Triple::ArchType Arch) const = 0; 155 156 // Targets can implement their own snippet generators/benchmarks runners by 157 // implementing these. 158 std::unique_ptr<SnippetGenerator> virtual createSerialSnippetGenerator( 159 const LLVMState &State, const SnippetGenerator::Options &Opts) const; 160 std::unique_ptr<SnippetGenerator> virtual createParallelSnippetGenerator( 161 const LLVMState &State, const SnippetGenerator::Options &Opts) const; 162 std::unique_ptr<BenchmarkRunner> virtual createLatencyBenchmarkRunner( 163 const LLVMState &State, InstructionBenchmark::ModeE Mode) const; 164 std::unique_ptr<BenchmarkRunner> virtual createUopsBenchmarkRunner( 165 const LLVMState &State) const; 166 167 const ExegesisTarget *Next = nullptr; 168 const ArrayRef<CpuAndPfmCounters> CpuPfmCounters; 169 }; 170 171 } // namespace exegesis 172 } // namespace llvm 173 174 #endif // LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H 175