Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
RISCVCustomBehaviour.cpp
Go to the documentation of this file.
1//===------------------- RISCVCustomBehaviour.cpp ---------------*-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/// \file
9///
10/// This file implements methods from the RISCVCustomBehaviour class.
11///
12//===----------------------------------------------------------------------===//
13
16#include "RISCV.h"
20#include "llvm/Support/Debug.h"
22
23#define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"
24
25namespace llvm::RISCV {
27 unsigned Log2IdxEEW : 3;
28 unsigned IsOrdered : 1;
29 unsigned IsStore : 1;
30 unsigned NF : 4;
31 unsigned BaseInstr;
32};
33
34#define GET_RISCVBaseVXMemOpTable_IMPL
35#include "RISCVGenSearchableTables.inc"
36} // namespace llvm::RISCV
37
38namespace llvm {
39namespace mca {
40
41const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL";
42
44 // Return true if not one of the valid LMUL strings
45 return StringSwitch<bool>(Data)
46 .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)
47 .Default(false);
48}
49
51 // assertion prevents us from needing llvm_unreachable in the StringSwitch
52 // below
54 "Cannot get LMUL because invalid Data value");
55 // These are the LMUL values that are used in RISC-V tablegen
57 .Case("M1", 0b000)
58 .Case("M2", 0b001)
59 .Case("M4", 0b010)
60 .Case("M8", 0b011)
61 .Case("MF2", 0b111)
62 .Case("MF4", 0b110)
63 .Case("MF8", 0b101);
64}
65
67
69 // Return true if not one of the valid SEW strings
70 return StringSwitch<bool>(Data)
71 .Cases("E8", "E16", "E32", "E64", true)
72 .Default(false);
73}
74
76 // assertion prevents us from needing llvm_unreachable in the StringSwitch
77 // below
78 assert(isDataValid(getData()) && "Cannot get SEW because invalid Data value");
79 // These are the LMUL values that are used in RISC-V tablegen
81 .Case("E8", 8)
82 .Case("E16", 16)
83 .Case("E32", 32)
84 .Case("E64", 64);
85}
86
93
99 LDBG() << "RVCB: Bad data for instrument kind " << Desc << ": " << Data
100 << '\n';
101 return nullptr;
102 }
103 return std::make_unique<RISCVLMULInstrument>(Data);
104 }
105
108 LDBG() << "RVCB: Bad data for instrument kind " << Desc << ": " << Data
109 << '\n';
110 return nullptr;
111 }
112 return std::make_unique<RISCVSEWInstrument>(Data);
113 }
114
115 LDBG() << "RVCB: Creating default instrument for Desc: " << Desc << '\n';
117}
118
121 if (Inst.getOpcode() == RISCV::VSETVLI ||
122 Inst.getOpcode() == RISCV::VSETIVLI) {
123 LDBG() << "RVCB: Found VSETVLI and creating instrument for it: " << Inst
124 << "\n";
125 unsigned VTypeI = Inst.getOperand(2).getImm();
127
128 StringRef LMUL;
129 switch (VLMUL) {
131 LMUL = "M1";
132 break;
134 LMUL = "M2";
135 break;
137 LMUL = "M4";
138 break;
140 LMUL = "M8";
141 break;
143 LMUL = "MF2";
144 break;
146 LMUL = "MF4";
147 break;
149 LMUL = "MF8";
150 break;
152 llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
153 }
155 Instruments.emplace_back(
157
158 unsigned SEW = RISCVVType::getSEW(VTypeI);
159 StringRef SEWStr;
160 switch (SEW) {
161 case 8:
162 SEWStr = "E8";
163 break;
164 case 16:
165 SEWStr = "E16";
166 break;
167 case 32:
168 SEWStr = "E32";
169 break;
170 case 64:
171 SEWStr = "E64";
172 break;
173 default:
174 llvm_unreachable("Cannot create instrument for SEW");
175 }
176 Instruments.emplace_back(
178
179 return Instruments;
180 }
182}
183
184static std::pair<uint8_t, uint8_t>
185getEEWAndEMUL(unsigned Opcode, RISCVVType::VLMUL LMUL, uint8_t SEW) {
186 uint8_t EEW;
187 switch (Opcode) {
188 case RISCV::VLM_V:
189 case RISCV::VSM_V:
190 case RISCV::VLE8_V:
191 case RISCV::VSE8_V:
192 case RISCV::VLSE8_V:
193 case RISCV::VSSE8_V:
194 EEW = 8;
195 break;
196 case RISCV::VLE16_V:
197 case RISCV::VSE16_V:
198 case RISCV::VLSE16_V:
199 case RISCV::VSSE16_V:
200 EEW = 16;
201 break;
202 case RISCV::VLE32_V:
203 case RISCV::VSE32_V:
204 case RISCV::VLSE32_V:
205 case RISCV::VSSE32_V:
206 EEW = 32;
207 break;
208 case RISCV::VLE64_V:
209 case RISCV::VSE64_V:
210 case RISCV::VLSE64_V:
211 case RISCV::VSSE64_V:
212 EEW = 64;
213 break;
214 default:
215 llvm_unreachable("Could not determine EEW from Opcode");
216 }
217
218 auto EMUL = RISCVVType::getSameRatioLMUL(SEW, LMUL, EEW);
219 if (!EEW)
220 llvm_unreachable("Invalid SEW or LMUL for new ratio");
221 return std::make_pair(EEW, *EMUL);
222}
223
224static bool opcodeHasEEWAndEMULInfo(unsigned short Opcode) {
225 return Opcode == RISCV::VLM_V || Opcode == RISCV::VSM_V ||
226 Opcode == RISCV::VLE8_V || Opcode == RISCV::VSE8_V ||
227 Opcode == RISCV::VLE16_V || Opcode == RISCV::VSE16_V ||
228 Opcode == RISCV::VLE32_V || Opcode == RISCV::VSE32_V ||
229 Opcode == RISCV::VLE64_V || Opcode == RISCV::VSE64_V ||
230 Opcode == RISCV::VLSE8_V || Opcode == RISCV::VSSE8_V ||
231 Opcode == RISCV::VLSE16_V || Opcode == RISCV::VSSE16_V ||
232 Opcode == RISCV::VLSE32_V || Opcode == RISCV::VSSE32_V ||
233 Opcode == RISCV::VLSE64_V || Opcode == RISCV::VSSE64_V;
234}
235
237 const MCInstrInfo &MCII, const MCInst &MCI,
238 const llvm::SmallVector<Instrument *> &IVec) const {
239 unsigned short Opcode = MCI.getOpcode();
240 unsigned SchedClassID = MCII.get(Opcode).getSchedClass();
241
242 // Unpack all possible RISC-V instruments from IVec.
243 RISCVLMULInstrument *LI = nullptr;
244 RISCVSEWInstrument *SI = nullptr;
245 for (auto &I : IVec) {
246 if (I->getDesc() == RISCVLMULInstrument::DESC_NAME)
247 LI = static_cast<RISCVLMULInstrument *>(I);
248 else if (I->getDesc() == RISCVSEWInstrument::DESC_NAME)
249 SI = static_cast<RISCVSEWInstrument *>(I);
250 }
251
252 // Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,
253 // then no option to override.
254 if (!LI) {
255 LDBG() << "RVCB: Did not use instrumentation to override Opcode.\n";
256 return SchedClassID;
257 }
258 uint8_t LMUL = LI->getLMUL();
259
260 // getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument,
261 // or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL
262 // and SEW, or (Opcode, LMUL, 0) if does not depend on SEW.
263 uint8_t SEW = SI ? SI->getSEW() : 0;
264
265 std::optional<unsigned> VPOpcode;
266 if (const auto *VXMO = RISCV::getVXMemOpInfo(Opcode)) {
267 // Calculate the expected index EMUL. For indexed operations,
268 // the DataEEW and DataEMUL are equal to SEW and LMUL, respectively.
269 unsigned IndexEMUL = ((1 << VXMO->Log2IdxEEW) * LMUL) / SEW;
270
271 if (!VXMO->NF) {
272 // Indexed Load / Store.
273 if (VXMO->IsStore) {
274 if (const auto *VXP = RISCV::getVSXPseudo(
275 /*Masked=*/0, VXMO->IsOrdered, VXMO->Log2IdxEEW, LMUL,
276 IndexEMUL))
277 VPOpcode = VXP->Pseudo;
278 } else {
279 if (const auto *VXP = RISCV::getVLXPseudo(
280 /*Masked=*/0, VXMO->IsOrdered, VXMO->Log2IdxEEW, LMUL,
281 IndexEMUL))
282 VPOpcode = VXP->Pseudo;
283 }
284 } else {
285 // Segmented Indexed Load / Store.
286 if (VXMO->IsStore) {
287 if (const auto *VXP =
288 RISCV::getVSXSEGPseudo(VXMO->NF, /*Masked=*/0, VXMO->IsOrdered,
289 VXMO->Log2IdxEEW, LMUL, IndexEMUL))
290 VPOpcode = VXP->Pseudo;
291 } else {
292 if (const auto *VXP =
293 RISCV::getVLXSEGPseudo(VXMO->NF, /*Masked=*/0, VXMO->IsOrdered,
294 VXMO->Log2IdxEEW, LMUL, IndexEMUL))
295 VPOpcode = VXP->Pseudo;
296 }
297 }
298 } else if (opcodeHasEEWAndEMULInfo(Opcode)) {
299 RISCVVType::VLMUL VLMUL = static_cast<RISCVVType::VLMUL>(LMUL);
300 auto [EEW, EMUL] = getEEWAndEMUL(Opcode, VLMUL, SEW);
301 if (const auto *RVV =
302 RISCVVInversePseudosTable::getBaseInfo(Opcode, EMUL, EEW))
303 VPOpcode = RVV->Pseudo;
304 } else {
305 // Check if it depends on LMUL and SEW
306 const auto *RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW);
307 // Check if it depends only on LMUL
308 if (!RVV)
309 RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0);
310
311 if (RVV)
312 VPOpcode = RVV->Pseudo;
313 }
314
315 // Not a RVV instr
316 if (!VPOpcode) {
317 LDBG() << "RVCB: Could not find PseudoInstruction for Opcode "
318 << MCII.getName(Opcode)
319 << ", LMUL=" << (LI ? LI->getData() : "Unspecified")
320 << ", SEW=" << (SI ? SI->getData() : "Unspecified")
321 << ". Ignoring instrumentation and using original SchedClassID="
322 << SchedClassID << '\n';
323 return SchedClassID;
324 }
325
326 // Override using pseudo
327 LDBG() << "RVCB: Found Pseudo Instruction for Opcode " << MCII.getName(Opcode)
328 << ", LMUL=" << LI->getData()
329 << ", SEW=" << (SI ? SI->getData() : "Unspecified")
330 << ". Overriding original SchedClassID=" << SchedClassID << " with "
331 << MCII.getName(*VPOpcode) << '\n';
332 return MCII.get(*VPOpcode).getSchedClass();
333}
334
335} // namespace mca
336} // namespace llvm
337
338using namespace llvm;
339using namespace mca;
340
341static InstrumentManager *
343 const MCInstrInfo &MCII) {
344 return new RISCVInstrumentManager(STI, MCII);
345}
346
347/// Extern function to initialize the targets for the RISC-V backend
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define LDBG(...)
LDBG() is a macro that can be used as a raw_ostream for debugging.
Definition DebugLog.h:50
#define I(x, y, z)
Definition MD5.cpp:58
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA()
Extern function to initialize the targets for the RISC-V backend.
static InstrumentManager * createRISCVInstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
This file defines the RISCVCustomBehaviour class which inherits from CustomBehaviour.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getOpcode() const
Definition MCInst.h:202
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
int64_t getImm() const
Definition MCInst.h:84
Generic base class for all target subtargets.
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
This class allows targets to optionally customize the logic that resolves scheduling class IDs.
virtual UniqueInstrument createInstrument(StringRef Desc, StringRef Data)
Allocate an Instrument, and return a unique pointer to it.
virtual bool supportsInstrumentType(StringRef Type) const
StringRef getData() const
bool supportsInstrumentType(StringRef Type) const override
unsigned getSchedClassID(const MCInstrInfo &MCII, const MCInst &MCI, const SmallVector< Instrument * > &IVec) const override
Using the Instrument, returns a SchedClassID to use instead of the SchedClassID that belongs to the M...
UniqueInstrument createInstrument(StringRef Desc, StringRef Data) override
Create a Instrument for RISC-V target.
SmallVector< UniqueInstrument > createInstruments(const MCInst &Inst) override
Return a list of unique pointers to Instruments, where each Instrument is allocated by this function.
static bool isDataValid(StringRef Data)
static bool isDataValid(StringRef Data)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI std::optional< VLMUL > getSameRatioLMUL(unsigned SEW, VLMUL VLMUL, unsigned EEW)
static unsigned getSEW(unsigned VType)
static VLMUL getVLMUL(unsigned VType)
std::unique_ptr< Instrument > UniqueInstrument
static bool opcodeHasEEWAndEMULInfo(unsigned short Opcode)
static std::pair< uint8_t, uint8_t > getEEWAndEMUL(unsigned Opcode, RISCVVType::VLMUL LMUL, uint8_t SEW)
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheRISCV32Target()
Op::Description Desc
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
Target & getTheRISCV64Target()
static void RegisterInstrumentManager(Target &T, Target::InstrumentManagerCtorTy Fn)
RegisterInstrumentManager - Register an InstrumentManager implementation for the given target.