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"
21
22#define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"
23
24namespace llvm::RISCV {
26 unsigned Log2IdxEEW : 3;
27 unsigned IsOrdered : 1;
28 unsigned IsStore : 1;
29 unsigned NF : 4;
30 unsigned BaseInstr;
31};
32
33#define GET_RISCVBaseVXMemOpTable_IMPL
34#include "RISCVGenSearchableTables.inc"
35} // namespace llvm::RISCV
36
37namespace llvm {
38namespace mca {
39
41
43 // Return true if not one of the valid LMUL strings
44 return StringSwitch<bool>(Data)
45 .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)
46 .Default(false);
47}
48
50 // assertion prevents us from needing llvm_unreachable in the StringSwitch
51 // below
53 "Cannot get LMUL because invalid Data value");
54 // These are the LMUL values that are used in RISC-V tablegen
56 .Case("M1", 0b000)
57 .Case("M2", 0b001)
58 .Case("M4", 0b010)
59 .Case("M8", 0b011)
60 .Case("MF2", 0b111)
61 .Case("MF4", 0b110)
62 .Case("MF8", 0b101);
63}
64
66
68 // Return true if not one of the valid SEW strings
69 return StringSwitch<bool>(Data)
70 .Cases("E8", "E16", "E32", "E64", true)
71 .Default(false);
72}
73
75 // assertion prevents us from needing llvm_unreachable in the StringSwitch
76 // below
77 assert(isDataValid(getData()) && "Cannot get SEW because invalid Data value");
78 // These are the LMUL values that are used in RISC-V tablegen
80 .Case("E8", 8)
81 .Case("E16", 16)
82 .Case("E32", 32)
83 .Case("E64", 64);
84}
85
87 llvm::StringRef Type) const {
90}
91
97 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
98 << Data << '\n');
99 return nullptr;
100 }
101 return std::make_unique<RISCVLMULInstrument>(Data);
102 }
103
106 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
107 << Data << '\n');
108 return nullptr;
109 }
110 return std::make_unique<RISCVSEWInstrument>(Data);
111 }
112
113 LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc << '\n');
114 return nullptr;
115}
116
119 if (Inst.getOpcode() == RISCV::VSETVLI ||
120 Inst.getOpcode() == RISCV::VSETIVLI) {
121 LLVM_DEBUG(dbgs() << "RVCB: Found VSETVLI and creating instrument for it: "
122 << Inst << "\n");
123 unsigned VTypeI = Inst.getOperand(2).getImm();
125
126 StringRef LMUL;
127 switch (VLMUL) {
129 LMUL = "M1";
130 break;
132 LMUL = "M2";
133 break;
135 LMUL = "M4";
136 break;
138 LMUL = "M8";
139 break;
141 LMUL = "MF2";
142 break;
144 LMUL = "MF4";
145 break;
147 LMUL = "MF8";
148 break;
150 llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
151 }
153 Instruments.emplace_back(
155
156 unsigned SEW = RISCVVType::getSEW(VTypeI);
157 StringRef SEWStr;
158 switch (SEW) {
159 case 8:
160 SEWStr = "E8";
161 break;
162 case 16:
163 SEWStr = "E16";
164 break;
165 case 32:
166 SEWStr = "E32";
167 break;
168 case 64:
169 SEWStr = "E64";
170 break;
171 default:
172 llvm_unreachable("Cannot create instrument for SEW");
173 }
174 Instruments.emplace_back(
176
177 return Instruments;
178 }
180}
181
182static std::pair<uint8_t, uint8_t>
183getEEWAndEMUL(unsigned Opcode, RISCVVType::VLMUL LMUL, uint8_t SEW) {
184 uint8_t EEW;
185 switch (Opcode) {
186 case RISCV::VLM_V:
187 case RISCV::VSM_V:
188 case RISCV::VLE8_V:
189 case RISCV::VSE8_V:
190 case RISCV::VLSE8_V:
191 case RISCV::VSSE8_V:
192 EEW = 8;
193 break;
194 case RISCV::VLE16_V:
195 case RISCV::VSE16_V:
196 case RISCV::VLSE16_V:
197 case RISCV::VSSE16_V:
198 EEW = 16;
199 break;
200 case RISCV::VLE32_V:
201 case RISCV::VSE32_V:
202 case RISCV::VLSE32_V:
203 case RISCV::VSSE32_V:
204 EEW = 32;
205 break;
206 case RISCV::VLE64_V:
207 case RISCV::VSE64_V:
208 case RISCV::VLSE64_V:
209 case RISCV::VSSE64_V:
210 EEW = 64;
211 break;
212 default:
213 llvm_unreachable("Could not determine EEW from Opcode");
214 }
215
216 auto EMUL = RISCVVType::getSameRatioLMUL(SEW, LMUL, EEW);
217 if (!EEW)
218 llvm_unreachable("Invalid SEW or LMUL for new ratio");
219 return std::make_pair(EEW, *EMUL);
220}
221
222static bool opcodeHasEEWAndEMULInfo(unsigned short Opcode) {
223 return Opcode == RISCV::VLM_V || Opcode == RISCV::VSM_V ||
224 Opcode == RISCV::VLE8_V || Opcode == RISCV::VSE8_V ||
225 Opcode == RISCV::VLE16_V || Opcode == RISCV::VSE16_V ||
226 Opcode == RISCV::VLE32_V || Opcode == RISCV::VSE32_V ||
227 Opcode == RISCV::VLE64_V || Opcode == RISCV::VSE64_V ||
228 Opcode == RISCV::VLSE8_V || Opcode == RISCV::VSSE8_V ||
229 Opcode == RISCV::VLSE16_V || Opcode == RISCV::VSSE16_V ||
230 Opcode == RISCV::VLSE32_V || Opcode == RISCV::VSSE32_V ||
231 Opcode == RISCV::VLSE64_V || Opcode == RISCV::VSSE64_V;
232}
233
235 const MCInstrInfo &MCII, const MCInst &MCI,
236 const llvm::SmallVector<Instrument *> &IVec) const {
237 unsigned short Opcode = MCI.getOpcode();
238 unsigned SchedClassID = MCII.get(Opcode).getSchedClass();
239
240 // Unpack all possible RISC-V instruments from IVec.
241 RISCVLMULInstrument *LI = nullptr;
242 RISCVSEWInstrument *SI = nullptr;
243 for (auto &I : IVec) {
244 if (I->getDesc() == RISCVLMULInstrument::DESC_NAME)
245 LI = static_cast<RISCVLMULInstrument *>(I);
246 else if (I->getDesc() == RISCVSEWInstrument::DESC_NAME)
247 SI = static_cast<RISCVSEWInstrument *>(I);
248 }
249
250 // Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,
251 // then no option to override.
252 if (!LI) {
254 dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");
255 return SchedClassID;
256 }
257 uint8_t LMUL = LI->getLMUL();
258
259 // getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument,
260 // or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL
261 // and SEW, or (Opcode, LMUL, 0) if does not depend on SEW.
262 uint8_t SEW = SI ? SI->getSEW() : 0;
263
264 std::optional<unsigned> VPOpcode;
265 if (const auto *VXMO = RISCV::getVXMemOpInfo(Opcode)) {
266 // Calculate the expected index EMUL. For indexed operations,
267 // the DataEEW and DataEMUL are equal to SEW and LMUL, respectively.
268 unsigned IndexEMUL = ((1 << VXMO->Log2IdxEEW) * LMUL) / SEW;
269
270 if (!VXMO->NF) {
271 // Indexed Load / Store.
272 if (VXMO->IsStore) {
273 if (const auto *VXP = RISCV::getVSXPseudo(
274 /*Masked=*/0, VXMO->IsOrdered, VXMO->Log2IdxEEW, LMUL,
275 IndexEMUL))
276 VPOpcode = VXP->Pseudo;
277 } else {
278 if (const auto *VXP = RISCV::getVLXPseudo(
279 /*Masked=*/0, VXMO->IsOrdered, VXMO->Log2IdxEEW, LMUL,
280 IndexEMUL))
281 VPOpcode = VXP->Pseudo;
282 }
283 } else {
284 // Segmented Indexed Load / Store.
285 if (VXMO->IsStore) {
286 if (const auto *VXP =
287 RISCV::getVSXSEGPseudo(VXMO->NF, /*Masked=*/0, VXMO->IsOrdered,
288 VXMO->Log2IdxEEW, LMUL, IndexEMUL))
289 VPOpcode = VXP->Pseudo;
290 } else {
291 if (const auto *VXP =
292 RISCV::getVLXSEGPseudo(VXMO->NF, /*Masked=*/0, VXMO->IsOrdered,
293 VXMO->Log2IdxEEW, LMUL, IndexEMUL))
294 VPOpcode = VXP->Pseudo;
295 }
296 }
297 } else if (opcodeHasEEWAndEMULInfo(Opcode)) {
298 RISCVVType::VLMUL VLMUL = static_cast<RISCVVType::VLMUL>(LMUL);
299 auto [EEW, EMUL] = getEEWAndEMUL(Opcode, VLMUL, SEW);
300 if (const auto *RVV =
301 RISCVVInversePseudosTable::getBaseInfo(Opcode, EMUL, EEW))
302 VPOpcode = RVV->Pseudo;
303 } else {
304 // Check if it depends on LMUL and SEW
305 const auto *RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW);
306 // Check if it depends only on LMUL
307 if (!RVV)
308 RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0);
309
310 if (RVV)
311 VPOpcode = RVV->Pseudo;
312 }
313
314 // Not a RVV instr
315 if (!VPOpcode) {
317 dbgs() << "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 LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode "
328 << MCII.getName(Opcode) << ", LMUL=" << LI->getData()
329 << ", SEW=" << (SI ? SI->getData() : "Unspecified")
330 << ". Overriding original SchedClassID=" << SchedClassID
331 << " with " << 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
354}
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 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.
#define LLVM_DEBUG(...)
Definition: Debug.h:119
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
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Definition: MCInstrDesc.h:603
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:64
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition: MCInstrInfo.h:71
int64_t getImm() const
Definition: MCInst.h:84
Generic base class for all target subtargets.
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:68
R Default(T Value)
Definition: StringSwitch.h:177
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Definition: StringSwitch.h:87
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.
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 const StringRef DESC_NAME
static bool isDataValid(StringRef Data)
static const StringRef DESC_NAME
#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)
static bool opcodeHasEEWAndEMULInfo(unsigned short Opcode)
static std::pair< uint8_t, uint8_t > getEEWAndEMUL(unsigned Opcode, RISCVVType::VLMUL LMUL, uint8_t SEW)
std::unique_ptr< Instrument > UniqueInstrument
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheRISCV32Target()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
Target & getTheRISCV64Target()
Description of the encoding of one expression Op.
static void RegisterInstrumentManager(Target &T, Target::InstrumentManagerCtorTy Fn)
RegisterInstrumentManager - Register an InstrumentManager implementation for the given target.