Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Target / RISCV / MCA / RISCVCustomBehaviour.cpp
blobaba2511959af03b9c82c362b20cc79eebdfb2745
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 //===----------------------------------------------------------------------===//
14 #include "RISCVCustomBehaviour.h"
15 #include "MCTargetDesc/RISCVMCTargetDesc.h"
16 #include "RISCV.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"
23 // This brings in a table with primary key of
24 // base instruction opcode and lmul and maps
25 // to the opcode of the pseudo instruction.
26 namespace RISCVVInversePseudosTable {
27 using namespace llvm;
28 using namespace llvm::RISCV;
30 struct PseudoInfo {
31 uint16_t Pseudo;
32 uint16_t BaseInstr;
33 uint8_t VLMul;
34 uint8_t SEW;
37 #define GET_RISCVVInversePseudosTable_IMPL
38 #define GET_RISCVVInversePseudosTable_DECL
39 #include "RISCVGenSearchableTables.inc"
41 } // end namespace RISCVVInversePseudosTable
43 namespace llvm {
44 namespace mca {
46 const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL";
48 bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data) {
49 // Return true if not one of the valid LMUL strings
50 return StringSwitch<bool>(Data)
51 .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)
52 .Default(false);
55 uint8_t RISCVLMULInstrument::getLMUL() const {
56 // assertion prevents us from needing llvm_unreachable in the StringSwitch
57 // below
58 assert(isDataValid(getData()) &&
59 "Cannot get LMUL because invalid Data value");
60 // These are the LMUL values that are used in RISC-V tablegen
61 return StringSwitch<uint8_t>(getData())
62 .Case("M1", 0b000)
63 .Case("M2", 0b001)
64 .Case("M4", 0b010)
65 .Case("M8", 0b011)
66 .Case("MF2", 0b111)
67 .Case("MF4", 0b110)
68 .Case("MF8", 0b101);
71 const llvm::StringRef RISCVSEWInstrument::DESC_NAME = "RISCV-SEW";
73 bool RISCVSEWInstrument::isDataValid(llvm::StringRef Data) {
74 // Return true if not one of the valid SEW strings
75 return StringSwitch<bool>(Data)
76 .Cases("E8", "E16", "E32", "E64", true)
77 .Default(false);
80 uint8_t RISCVSEWInstrument::getSEW() const {
81 // assertion prevents us from needing llvm_unreachable in the StringSwitch
82 // below
83 assert(isDataValid(getData()) && "Cannot get SEW because invalid Data value");
84 // These are the LMUL values that are used in RISC-V tablegen
85 return StringSwitch<uint8_t>(getData())
86 .Case("E8", 8)
87 .Case("E16", 16)
88 .Case("E32", 32)
89 .Case("E64", 64);
92 bool RISCVInstrumentManager::supportsInstrumentType(
93 llvm::StringRef Type) const {
94 return Type == RISCVLMULInstrument::DESC_NAME ||
95 Type == RISCVSEWInstrument::DESC_NAME;
98 UniqueInstrument
99 RISCVInstrumentManager::createInstrument(llvm::StringRef Desc,
100 llvm::StringRef Data) {
101 if (Desc == RISCVLMULInstrument::DESC_NAME) {
102 if (!RISCVLMULInstrument::isDataValid(Data)) {
103 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
104 << Data << '\n');
105 return nullptr;
107 return std::make_unique<RISCVLMULInstrument>(Data);
110 if (Desc == RISCVSEWInstrument::DESC_NAME) {
111 if (!RISCVSEWInstrument::isDataValid(Data)) {
112 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
113 << Data << '\n');
114 return nullptr;
116 return std::make_unique<RISCVSEWInstrument>(Data);
119 LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc << '\n');
120 return nullptr;
123 SmallVector<UniqueInstrument>
124 RISCVInstrumentManager::createInstruments(const MCInst &Inst) {
125 if (Inst.getOpcode() == RISCV::VSETVLI ||
126 Inst.getOpcode() == RISCV::VSETIVLI) {
127 LLVM_DEBUG(dbgs() << "RVCB: Found VSETVLI and creating instrument for it: "
128 << Inst << "\n");
129 unsigned VTypeI = Inst.getOperand(2).getImm();
130 RISCVII::VLMUL VLMUL = RISCVVType::getVLMUL(VTypeI);
132 StringRef LMUL;
133 switch (VLMUL) {
134 case RISCVII::LMUL_1:
135 LMUL = "M1";
136 break;
137 case RISCVII::LMUL_2:
138 LMUL = "M2";
139 break;
140 case RISCVII::LMUL_4:
141 LMUL = "M4";
142 break;
143 case RISCVII::LMUL_8:
144 LMUL = "M8";
145 break;
146 case RISCVII::LMUL_F2:
147 LMUL = "MF2";
148 break;
149 case RISCVII::LMUL_F4:
150 LMUL = "MF4";
151 break;
152 case RISCVII::LMUL_F8:
153 LMUL = "MF8";
154 break;
155 case RISCVII::LMUL_RESERVED:
156 llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
158 SmallVector<UniqueInstrument> Instruments;
159 Instruments.emplace_back(
160 createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL));
162 unsigned SEW = RISCVVType::getSEW(VTypeI);
163 StringRef SEWStr;
164 switch (SEW) {
165 case 8:
166 SEWStr = "E8";
167 break;
168 case 16:
169 SEWStr = "E16";
170 break;
171 case 32:
172 SEWStr = "E32";
173 break;
174 case 64:
175 SEWStr = "E64";
176 break;
177 default:
178 llvm_unreachable("Cannot create instrument for SEW");
180 Instruments.emplace_back(
181 createInstrument(RISCVSEWInstrument::DESC_NAME, SEWStr));
183 return Instruments;
185 return SmallVector<UniqueInstrument>();
188 static std::pair<uint8_t, uint8_t>
189 getEEWAndEMULForUnitStrideLoadStore(unsigned Opcode, RISCVII::VLMUL LMUL,
190 uint8_t SEW) {
191 uint8_t EEW;
192 switch (Opcode) {
193 case RISCV::VLM_V:
194 case RISCV::VSM_V:
195 case RISCV::VLE8_V:
196 case RISCV::VSE8_V:
197 EEW = 8;
198 break;
199 case RISCV::VLE16_V:
200 case RISCV::VSE16_V:
201 EEW = 16;
202 break;
203 case RISCV::VLE32_V:
204 case RISCV::VSE32_V:
205 EEW = 32;
206 break;
207 case RISCV::VLE64_V:
208 case RISCV::VSE64_V:
209 EEW = 64;
210 break;
211 default:
212 llvm_unreachable("Opcode is not a vector unit stride load nor store");
215 auto EMUL = RISCVVType::getSameRatioLMUL(SEW, LMUL, EEW);
216 if (!EEW)
217 llvm_unreachable("Invalid SEW or LMUL for new ratio");
218 return std::make_pair(EEW, *EMUL);
221 unsigned RISCVInstrumentManager::getSchedClassID(
222 const MCInstrInfo &MCII, const MCInst &MCI,
223 const llvm::SmallVector<Instrument *> &IVec) const {
224 unsigned short Opcode = MCI.getOpcode();
225 unsigned SchedClassID = MCII.get(Opcode).getSchedClass();
227 // Unpack all possible RISC-V instruments from IVec.
228 RISCVLMULInstrument *LI = nullptr;
229 RISCVSEWInstrument *SI = nullptr;
230 for (auto &I : IVec) {
231 if (I->getDesc() == RISCVLMULInstrument::DESC_NAME)
232 LI = static_cast<RISCVLMULInstrument *>(I);
233 else if (I->getDesc() == RISCVSEWInstrument::DESC_NAME)
234 SI = static_cast<RISCVSEWInstrument *>(I);
237 // Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,
238 // then no option to override.
239 if (!LI) {
240 LLVM_DEBUG(
241 dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");
242 return SchedClassID;
244 uint8_t LMUL = LI->getLMUL();
246 // getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument,
247 // or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL
248 // and SEW, or (Opcode, LMUL, 0) if does not depend on SEW.
249 uint8_t SEW = SI ? SI->getSEW() : 0;
251 const RISCVVInversePseudosTable::PseudoInfo *RVV = nullptr;
252 if (Opcode == RISCV::VLM_V || Opcode == RISCV::VSM_V ||
253 Opcode == RISCV::VLE8_V || Opcode == RISCV::VSE8_V ||
254 Opcode == RISCV::VLE16_V || Opcode == RISCV::VSE16_V ||
255 Opcode == RISCV::VLE32_V || Opcode == RISCV::VSE32_V ||
256 Opcode == RISCV::VLE64_V || Opcode == RISCV::VSE64_V) {
257 RISCVII::VLMUL VLMUL = static_cast<RISCVII::VLMUL>(LMUL);
258 auto [EEW, EMUL] = getEEWAndEMULForUnitStrideLoadStore(Opcode, VLMUL, SEW);
259 RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, EMUL, EEW);
260 } else {
261 // Check if it depends on LMUL and SEW
262 RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW);
263 // Check if it depends only on LMUL
264 if (!RVV)
265 RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0);
268 // Not a RVV instr
269 if (!RVV) {
270 LLVM_DEBUG(
271 dbgs() << "RVCB: Could not find PseudoInstruction for Opcode "
272 << MCII.getName(Opcode)
273 << ", LMUL=" << (LI ? LI->getData() : "Unspecified")
274 << ", SEW=" << (SI ? SI->getData() : "Unspecified")
275 << ". Ignoring instrumentation and using original SchedClassID="
276 << SchedClassID << '\n');
277 return SchedClassID;
280 // Override using pseudo
281 LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode "
282 << MCII.getName(Opcode) << ", LMUL=" << LI->getData()
283 << ", SEW=" << (SI ? SI->getData() : "Unspecified")
284 << ". Overriding original SchedClassID=" << SchedClassID
285 << " with " << MCII.getName(RVV->Pseudo) << '\n');
286 return MCII.get(RVV->Pseudo).getSchedClass();
289 } // namespace mca
290 } // namespace llvm
292 using namespace llvm;
293 using namespace mca;
295 static InstrumentManager *
296 createRISCVInstrumentManager(const MCSubtargetInfo &STI,
297 const MCInstrInfo &MCII) {
298 return new RISCVInstrumentManager(STI, MCII);
301 /// Extern function to initialize the targets for the RISC-V backend
302 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA() {
303 TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(),
304 createRISCVInstrumentManager);
305 TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(),
306 createRISCVInstrumentManager);