Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 1 | //===-- Target.h ------------------------------------------------*- C++ -*-===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// \file |
| 10 | /// |
| 11 | /// Classes that handle the creation of target-specific objects. This is |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 12 | /// similar to Target/TargetRegistry. |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 13 | /// |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
| 16 | #ifndef LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H |
| 17 | #define LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H |
| 18 | |
Clement Courbet | 4860b98 | 2018-06-26 08:49:30 +0000 | [diff] [blame] | 19 | #include "BenchmarkResult.h" |
| 20 | #include "BenchmarkRunner.h" |
| 21 | #include "LlvmState.h" |
Clement Courbet | d939f6d | 2018-09-13 07:40:53 +0000 | [diff] [blame] | 22 | #include "SnippetGenerator.h" |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/Triple.h" |
Clement Courbet | 6fd00e3 | 2018-06-20 11:54:35 +0000 | [diff] [blame] | 24 | #include "llvm/CodeGen/TargetPassConfig.h" |
Guillaume Chatelet | fb94354 | 2018-08-01 14:41:45 +0000 | [diff] [blame] | 25 | #include "llvm/IR/CallingConv.h" |
Clement Courbet | 6fd00e3 | 2018-06-20 11:54:35 +0000 | [diff] [blame] | 26 | #include "llvm/IR/LegacyPassManager.h" |
Clement Courbet | a51efc2 | 2018-06-25 13:12:02 +0000 | [diff] [blame] | 27 | #include "llvm/MC/MCInst.h" |
| 28 | #include "llvm/MC/MCRegisterInfo.h" |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 29 | |
Fangrui Song | 32401af | 2018-10-22 17:10:47 +0000 | [diff] [blame] | 30 | namespace llvm { |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 31 | namespace exegesis { |
| 32 | |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 33 | struct PfmCountersInfo { |
| 34 | // An optional name of a performance counter that can be used to measure |
| 35 | // cycles. |
Simon Pilgrim | 2a9c728 | 2018-10-25 10:45:38 +0000 | [diff] [blame] | 36 | const char *CycleCounter; |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 37 | |
| 38 | // An optional name of a performance counter that can be used to measure |
| 39 | // uops. |
Simon Pilgrim | 2a9c728 | 2018-10-25 10:45:38 +0000 | [diff] [blame] | 40 | const char *UopsCounter; |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 41 | |
| 42 | // An IssueCounter specifies how to measure uops issued to specific proc |
| 43 | // resources. |
| 44 | struct IssueCounter { |
Simon Pilgrim | 2a9c728 | 2018-10-25 10:45:38 +0000 | [diff] [blame] | 45 | const char *Counter; |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 46 | // The name of the ProcResource that this counter measures. |
Simon Pilgrim | 2a9c728 | 2018-10-25 10:45:38 +0000 | [diff] [blame] | 47 | const char *ProcResName; |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 48 | }; |
| 49 | // An optional list of IssueCounters. |
Simon Pilgrim | 2a9c728 | 2018-10-25 10:45:38 +0000 | [diff] [blame] | 50 | const IssueCounter *IssueCounters; |
| 51 | unsigned NumIssueCounters; |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 52 | |
| 53 | static const PfmCountersInfo Default; |
| 54 | }; |
| 55 | |
| 56 | struct CpuAndPfmCounters { |
Simon Pilgrim | 2a9c728 | 2018-10-25 10:45:38 +0000 | [diff] [blame] | 57 | const char *CpuName; |
| 58 | const PfmCountersInfo *PCI; |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 59 | bool operator<(StringRef S) const { return StringRef(CpuName) < S; } |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 60 | }; |
| 61 | |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 62 | class ExegesisTarget { |
| 63 | public: |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 64 | explicit ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters) |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 65 | : CpuPfmCounters(CpuPfmCounters) {} |
| 66 | |
Clement Courbet | 6fd00e3 | 2018-06-20 11:54:35 +0000 | [diff] [blame] | 67 | // Targets can use this to add target-specific passes in assembleToStream(); |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 68 | virtual void addTargetSpecificPasses(PassManagerBase &PM) const {} |
Clement Courbet | 6fd00e3 | 2018-06-20 11:54:35 +0000 | [diff] [blame] | 69 | |
Clement Courbet | a51efc2 | 2018-06-25 13:12:02 +0000 | [diff] [blame] | 70 | // Generates code to move a constant into a the given register. |
Guillaume Chatelet | c96a97b | 2018-09-20 12:22:18 +0000 | [diff] [blame] | 71 | // Precondition: Value must fit into Reg. |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 72 | virtual std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg, |
| 73 | const APInt &Value) const = 0; |
Guillaume Chatelet | 5ad2909 | 2018-09-18 11:26:27 +0000 | [diff] [blame] | 74 | |
| 75 | // Returns the register pointing to scratch memory, or 0 if this target |
| 76 | // does not support memory operands. The benchmark function uses the |
| 77 | // default calling convention. |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 78 | virtual unsigned getScratchMemoryRegister(const Triple &) const { return 0; } |
Guillaume Chatelet | fb94354 | 2018-08-01 14:41:45 +0000 | [diff] [blame] | 79 | |
| 80 | // Fills memory operands with references to the address at [Reg] + Offset. |
Guillaume Chatelet | 70ac019 | 2018-09-27 09:23:04 +0000 | [diff] [blame] | 81 | virtual void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, |
Guillaume Chatelet | c96a97b | 2018-09-20 12:22:18 +0000 | [diff] [blame] | 82 | unsigned Offset) const { |
Guillaume Chatelet | c96a97b | 2018-09-20 12:22:18 +0000 | [diff] [blame] | 83 | llvm_unreachable( |
| 84 | "fillMemoryOperands() requires getScratchMemoryRegister() > 0"); |
| 85 | } |
Guillaume Chatelet | fb94354 | 2018-08-01 14:41:45 +0000 | [diff] [blame] | 86 | |
Clement Courbet | 9431b72 | 2019-09-27 12:56:24 +0000 | [diff] [blame] | 87 | // Returns a counter usable as a loop counter. |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 88 | virtual unsigned getLoopCounterRegister(const Triple &) const { return 0; } |
Clement Courbet | 9431b72 | 2019-09-27 12:56:24 +0000 | [diff] [blame] | 89 | |
| 90 | // Adds the code to decrement the loop counter and |
Clement Courbet | c029274 | 2019-10-03 07:56:56 +0000 | [diff] [blame] | 91 | virtual void decrementLoopCounterAndJump(MachineBasicBlock &MBB, |
| 92 | MachineBasicBlock &TargetMBB, |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 93 | const MCInstrInfo &MII) const { |
Clement Courbet | 9431b72 | 2019-09-27 12:56:24 +0000 | [diff] [blame] | 94 | llvm_unreachable("decrementLoopCounterAndBranch() requires " |
| 95 | "getLoopCounterRegister() > 0"); |
| 96 | } |
| 97 | |
Clement Courbet | 52da938 | 2019-03-26 15:44:57 +0000 | [diff] [blame] | 98 | // Returns a list of unavailable registers. |
| 99 | // Targets can use this to prevent some registers to be automatically selected |
| 100 | // for use in snippets. |
| 101 | virtual ArrayRef<unsigned> getUnavailableRegisters() const { return {}; } |
| 102 | |
Guillaume Chatelet | fb94354 | 2018-08-01 14:41:45 +0000 | [diff] [blame] | 103 | // Returns the maximum number of bytes a load/store instruction can access at |
| 104 | // once. This is typically the size of the largest register available on the |
| 105 | // processor. Note that this only used as a hint to generate independant |
| 106 | // load/stores to/from memory, so the exact returned value does not really |
| 107 | // matter as long as it's large enough. |
Guillaume Chatelet | c96a97b | 2018-09-20 12:22:18 +0000 | [diff] [blame] | 108 | virtual unsigned getMaxMemoryAccessSize() const { return 0; } |
Guillaume Chatelet | fb94354 | 2018-08-01 14:41:45 +0000 | [diff] [blame] | 109 | |
Roman Lebedev | 404bdb1 | 2019-04-06 14:16:26 +0000 | [diff] [blame] | 110 | // Assigns a random operand of the right type to variable Var. |
| 111 | // The default implementation only handles generic operand types. |
| 112 | // The target is responsible for handling any operand |
| 113 | // starting from OPERAND_FIRST_TARGET. |
| 114 | virtual void randomizeMCOperand(const Instruction &Instr, const Variable &Var, |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 115 | MCOperand &AssignedValue, |
| 116 | const BitVector &ForbiddenRegs) const; |
Roman Lebedev | 404bdb1 | 2019-04-06 14:16:26 +0000 | [diff] [blame] | 117 | |
Clement Courbet | d939f6d | 2018-09-13 07:40:53 +0000 | [diff] [blame] | 118 | // Creates a snippet generator for the given mode. |
| 119 | std::unique_ptr<SnippetGenerator> |
| 120 | createSnippetGenerator(InstructionBenchmark::ModeE Mode, |
Clement Courbet | 2cd0f28 | 2019-10-08 14:30:24 +0000 | [diff] [blame] | 121 | const LLVMState &State, |
| 122 | const SnippetGenerator::Options &Opts) const; |
Clement Courbet | 4860b98 | 2018-06-26 08:49:30 +0000 | [diff] [blame] | 123 | // Creates a benchmark runner for the given mode. |
| 124 | std::unique_ptr<BenchmarkRunner> |
| 125 | createBenchmarkRunner(InstructionBenchmark::ModeE Mode, |
| 126 | const LLVMState &State) const; |
| 127 | |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 128 | // Returns the ExegesisTarget for the given triple or nullptr if the target |
| 129 | // does not exist. |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 130 | static const ExegesisTarget *lookup(Triple TT); |
Clement Courbet | 4860b98 | 2018-06-26 08:49:30 +0000 | [diff] [blame] | 131 | // Returns the default (unspecialized) ExegesisTarget. |
| 132 | static const ExegesisTarget &getDefault(); |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 133 | // Registers a target. Not thread safe. |
| 134 | static void registerTarget(ExegesisTarget *T); |
| 135 | |
Roman Lebedev | 3de9664 | 2018-06-19 11:58:10 +0000 | [diff] [blame] | 136 | virtual ~ExegesisTarget(); |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 137 | |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 138 | // Returns the Pfm counters for the given CPU (or the default if no pfm |
| 139 | // counters are defined for this CPU). |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 140 | const PfmCountersInfo &getPfmCounters(StringRef CpuName) const; |
Clement Courbet | 41c8af3 | 2018-10-25 07:44:01 +0000 | [diff] [blame] | 141 | |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 142 | private: |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 143 | virtual bool matchesArch(Triple::ArchType Arch) const = 0; |
Clement Courbet | 4860b98 | 2018-06-26 08:49:30 +0000 | [diff] [blame] | 144 | |
Clement Courbet | d939f6d | 2018-09-13 07:40:53 +0000 | [diff] [blame] | 145 | // Targets can implement their own snippet generators/benchmarks runners by |
Clement Courbet | 4860b98 | 2018-06-26 08:49:30 +0000 | [diff] [blame] | 146 | // implementing these. |
Clement Courbet | d939f6d | 2018-09-13 07:40:53 +0000 | [diff] [blame] | 147 | std::unique_ptr<SnippetGenerator> virtual createLatencySnippetGenerator( |
Clement Courbet | 2cd0f28 | 2019-10-08 14:30:24 +0000 | [diff] [blame] | 148 | const LLVMState &State, const SnippetGenerator::Options &Opts) const; |
Clement Courbet | d939f6d | 2018-09-13 07:40:53 +0000 | [diff] [blame] | 149 | std::unique_ptr<SnippetGenerator> virtual createUopsSnippetGenerator( |
Clement Courbet | 2cd0f28 | 2019-10-08 14:30:24 +0000 | [diff] [blame] | 150 | const LLVMState &State, const SnippetGenerator::Options &Opts) const; |
Clement Courbet | 4860b98 | 2018-06-26 08:49:30 +0000 | [diff] [blame] | 151 | std::unique_ptr<BenchmarkRunner> virtual createLatencyBenchmarkRunner( |
Clement Courbet | 362653f | 2019-01-30 16:02:20 +0000 | [diff] [blame] | 152 | const LLVMState &State, InstructionBenchmark::ModeE Mode) const; |
Clement Courbet | 4860b98 | 2018-06-26 08:49:30 +0000 | [diff] [blame] | 153 | std::unique_ptr<BenchmarkRunner> virtual createUopsBenchmarkRunner( |
| 154 | const LLVMState &State) const; |
| 155 | |
Clement Courbet | cff2caa | 2018-06-25 11:22:23 +0000 | [diff] [blame] | 156 | const ExegesisTarget *Next = nullptr; |
Clement Courbet | 50cdd56 | 2019-10-09 11:58:42 +0000 | [diff] [blame^] | 157 | const ArrayRef<CpuAndPfmCounters> CpuPfmCounters; |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 158 | }; |
| 159 | |
Clement Courbet | cff2caa | 2018-06-25 11:22:23 +0000 | [diff] [blame] | 160 | } // namespace exegesis |
Fangrui Song | 32401af | 2018-10-22 17:10:47 +0000 | [diff] [blame] | 161 | } // namespace llvm |
Clement Courbet | 44b4c54 | 2018-06-19 11:28:59 +0000 | [diff] [blame] | 162 | |
| 163 | #endif // LLVM_TOOLS_LLVM_EXEGESIS_TARGET_H |