1 //===------------------- RISCVCustomBehaviour.cpp ---------------*-C++ -* -===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements methods from the RISCVCustomBehaviour class.
12 //===----------------------------------------------------------------------===//
14 #include "RISCVCustomBehaviour.h"
15 #include "MCTargetDesc/RISCVMCTargetDesc.h"
17 #include "TargetInfo/RISCVTargetInfo.h"
18 #include "llvm/MC/TargetRegistry.h"
19 #include "llvm/Support/Debug.h"
21 #define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"
26 const llvm::StringRef
RISCVLMULInstrument::DESC_NAME
= "RISCV-LMUL";
28 bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data
) {
29 // Return true if not one of the valid LMUL strings
30 return StringSwitch
<bool>(Data
)
31 .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)
35 uint8_t RISCVLMULInstrument::getLMUL() const {
36 // assertion prevents us from needing llvm_unreachable in the StringSwitch
38 assert(isDataValid(getData()) &&
39 "Cannot get LMUL because invalid Data value");
40 // These are the LMUL values that are used in RISC-V tablegen
41 return StringSwitch
<uint8_t>(getData())
51 const llvm::StringRef
RISCVSEWInstrument::DESC_NAME
= "RISCV-SEW";
53 bool RISCVSEWInstrument::isDataValid(llvm::StringRef Data
) {
54 // Return true if not one of the valid SEW strings
55 return StringSwitch
<bool>(Data
)
56 .Cases("E8", "E16", "E32", "E64", true)
60 uint8_t RISCVSEWInstrument::getSEW() const {
61 // assertion prevents us from needing llvm_unreachable in the StringSwitch
63 assert(isDataValid(getData()) && "Cannot get SEW because invalid Data value");
64 // These are the LMUL values that are used in RISC-V tablegen
65 return StringSwitch
<uint8_t>(getData())
72 bool RISCVInstrumentManager::supportsInstrumentType(
73 llvm::StringRef Type
) const {
74 return Type
== RISCVLMULInstrument::DESC_NAME
||
75 Type
== RISCVSEWInstrument::DESC_NAME
;
79 RISCVInstrumentManager::createInstrument(llvm::StringRef Desc
,
80 llvm::StringRef Data
) {
81 if (Desc
== RISCVLMULInstrument::DESC_NAME
) {
82 if (!RISCVLMULInstrument::isDataValid(Data
)) {
83 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc
<< ": "
87 return std::make_unique
<RISCVLMULInstrument
>(Data
);
90 if (Desc
== RISCVSEWInstrument::DESC_NAME
) {
91 if (!RISCVSEWInstrument::isDataValid(Data
)) {
92 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc
<< ": "
96 return std::make_unique
<RISCVSEWInstrument
>(Data
);
99 LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc
<< '\n');
103 SmallVector
<UniqueInstrument
>
104 RISCVInstrumentManager::createInstruments(const MCInst
&Inst
) {
105 if (Inst
.getOpcode() == RISCV::VSETVLI
||
106 Inst
.getOpcode() == RISCV::VSETIVLI
) {
107 LLVM_DEBUG(dbgs() << "RVCB: Found VSETVLI and creating instrument for it: "
109 unsigned VTypeI
= Inst
.getOperand(2).getImm();
110 RISCVII::VLMUL VLMUL
= RISCVVType::getVLMUL(VTypeI
);
114 case RISCVII::LMUL_1
:
117 case RISCVII::LMUL_2
:
120 case RISCVII::LMUL_4
:
123 case RISCVII::LMUL_8
:
126 case RISCVII::LMUL_F2
:
129 case RISCVII::LMUL_F4
:
132 case RISCVII::LMUL_F8
:
135 case RISCVII::LMUL_RESERVED
:
136 llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
138 SmallVector
<UniqueInstrument
> Instruments
;
139 Instruments
.emplace_back(
140 createInstrument(RISCVLMULInstrument::DESC_NAME
, LMUL
));
142 unsigned SEW
= RISCVVType::getSEW(VTypeI
);
158 llvm_unreachable("Cannot create instrument for SEW");
160 Instruments
.emplace_back(
161 createInstrument(RISCVSEWInstrument::DESC_NAME
, SEWStr
));
165 return SmallVector
<UniqueInstrument
>();
168 static std::pair
<uint8_t, uint8_t>
169 getEEWAndEMUL(unsigned Opcode
, RISCVII::VLMUL LMUL
, uint8_t SEW
) {
182 case RISCV::VLSE16_V
:
183 case RISCV::VSSE16_V
:
188 case RISCV::VLSE32_V
:
189 case RISCV::VSSE32_V
:
194 case RISCV::VLSE64_V
:
195 case RISCV::VSSE64_V
:
199 llvm_unreachable("Could not determine EEW from Opcode");
202 auto EMUL
= RISCVVType::getSameRatioLMUL(SEW
, LMUL
, EEW
);
204 llvm_unreachable("Invalid SEW or LMUL for new ratio");
205 return std::make_pair(EEW
, *EMUL
);
208 bool opcodeHasEEWAndEMULInfo(unsigned short Opcode
) {
209 return Opcode
== RISCV::VLM_V
|| Opcode
== RISCV::VSM_V
||
210 Opcode
== RISCV::VLE8_V
|| Opcode
== RISCV::VSE8_V
||
211 Opcode
== RISCV::VLE16_V
|| Opcode
== RISCV::VSE16_V
||
212 Opcode
== RISCV::VLE32_V
|| Opcode
== RISCV::VSE32_V
||
213 Opcode
== RISCV::VLE64_V
|| Opcode
== RISCV::VSE64_V
||
214 Opcode
== RISCV::VLSE8_V
|| Opcode
== RISCV::VSSE8_V
||
215 Opcode
== RISCV::VLSE16_V
|| Opcode
== RISCV::VSSE16_V
||
216 Opcode
== RISCV::VLSE32_V
|| Opcode
== RISCV::VSSE32_V
||
217 Opcode
== RISCV::VLSE64_V
|| Opcode
== RISCV::VSSE64_V
;
220 unsigned RISCVInstrumentManager::getSchedClassID(
221 const MCInstrInfo
&MCII
, const MCInst
&MCI
,
222 const llvm::SmallVector
<Instrument
*> &IVec
) const {
223 unsigned short Opcode
= MCI
.getOpcode();
224 unsigned SchedClassID
= MCII
.get(Opcode
).getSchedClass();
226 // Unpack all possible RISC-V instruments from IVec.
227 RISCVLMULInstrument
*LI
= nullptr;
228 RISCVSEWInstrument
*SI
= nullptr;
229 for (auto &I
: IVec
) {
230 if (I
->getDesc() == RISCVLMULInstrument::DESC_NAME
)
231 LI
= static_cast<RISCVLMULInstrument
*>(I
);
232 else if (I
->getDesc() == RISCVSEWInstrument::DESC_NAME
)
233 SI
= static_cast<RISCVSEWInstrument
*>(I
);
236 // Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,
237 // then no option to override.
240 dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");
243 uint8_t LMUL
= LI
->getLMUL();
245 // getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument,
246 // or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL
247 // and SEW, or (Opcode, LMUL, 0) if does not depend on SEW.
248 uint8_t SEW
= SI
? SI
->getSEW() : 0;
250 const RISCVVInversePseudosTable::PseudoInfo
*RVV
= nullptr;
251 if (opcodeHasEEWAndEMULInfo(Opcode
)) {
252 RISCVII::VLMUL VLMUL
= static_cast<RISCVII::VLMUL
>(LMUL
);
253 auto [EEW
, EMUL
] = getEEWAndEMUL(Opcode
, VLMUL
, SEW
);
254 RVV
= RISCVVInversePseudosTable::getBaseInfo(Opcode
, EMUL
, EEW
);
256 // Check if it depends on LMUL and SEW
257 RVV
= RISCVVInversePseudosTable::getBaseInfo(Opcode
, LMUL
, SEW
);
258 // Check if it depends only on LMUL
260 RVV
= RISCVVInversePseudosTable::getBaseInfo(Opcode
, LMUL
, 0);
266 dbgs() << "RVCB: Could not find PseudoInstruction for Opcode "
267 << MCII
.getName(Opcode
)
268 << ", LMUL=" << (LI
? LI
->getData() : "Unspecified")
269 << ", SEW=" << (SI
? SI
->getData() : "Unspecified")
270 << ". Ignoring instrumentation and using original SchedClassID="
271 << SchedClassID
<< '\n');
275 // Override using pseudo
276 LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode "
277 << MCII
.getName(Opcode
) << ", LMUL=" << LI
->getData()
278 << ", SEW=" << (SI
? SI
->getData() : "Unspecified")
279 << ". Overriding original SchedClassID=" << SchedClassID
280 << " with " << MCII
.getName(RVV
->Pseudo
) << '\n');
281 return MCII
.get(RVV
->Pseudo
).getSchedClass();
287 using namespace llvm
;
290 static InstrumentManager
*
291 createRISCVInstrumentManager(const MCSubtargetInfo
&STI
,
292 const MCInstrInfo
&MCII
) {
293 return new RISCVInstrumentManager(STI
, MCII
);
296 /// Extern function to initialize the targets for the RISC-V backend
297 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeRISCVTargetMCA() {
298 TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(),
299 createRISCVInstrumentManager
);
300 TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(),
301 createRISCVInstrumentManager
);