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