Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
35294 views
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
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"
20
21
#define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"
22
23
namespace llvm {
24
namespace mca {
25
26
const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL";
27
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)
32
.Default(false);
33
}
34
35
uint8_t RISCVLMULInstrument::getLMUL() const {
36
// assertion prevents us from needing llvm_unreachable in the StringSwitch
37
// below
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())
42
.Case("M1", 0b000)
43
.Case("M2", 0b001)
44
.Case("M4", 0b010)
45
.Case("M8", 0b011)
46
.Case("MF2", 0b111)
47
.Case("MF4", 0b110)
48
.Case("MF8", 0b101);
49
}
50
51
const llvm::StringRef RISCVSEWInstrument::DESC_NAME = "RISCV-SEW";
52
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)
57
.Default(false);
58
}
59
60
uint8_t RISCVSEWInstrument::getSEW() const {
61
// assertion prevents us from needing llvm_unreachable in the StringSwitch
62
// below
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())
66
.Case("E8", 8)
67
.Case("E16", 16)
68
.Case("E32", 32)
69
.Case("E64", 64);
70
}
71
72
bool RISCVInstrumentManager::supportsInstrumentType(
73
llvm::StringRef Type) const {
74
return Type == RISCVLMULInstrument::DESC_NAME ||
75
Type == RISCVSEWInstrument::DESC_NAME;
76
}
77
78
UniqueInstrument
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 << ": "
84
<< Data << '\n');
85
return nullptr;
86
}
87
return std::make_unique<RISCVLMULInstrument>(Data);
88
}
89
90
if (Desc == RISCVSEWInstrument::DESC_NAME) {
91
if (!RISCVSEWInstrument::isDataValid(Data)) {
92
LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
93
<< Data << '\n');
94
return nullptr;
95
}
96
return std::make_unique<RISCVSEWInstrument>(Data);
97
}
98
99
LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc << '\n');
100
return nullptr;
101
}
102
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: "
108
<< Inst << "\n");
109
unsigned VTypeI = Inst.getOperand(2).getImm();
110
RISCVII::VLMUL VLMUL = RISCVVType::getVLMUL(VTypeI);
111
112
StringRef LMUL;
113
switch (VLMUL) {
114
case RISCVII::LMUL_1:
115
LMUL = "M1";
116
break;
117
case RISCVII::LMUL_2:
118
LMUL = "M2";
119
break;
120
case RISCVII::LMUL_4:
121
LMUL = "M4";
122
break;
123
case RISCVII::LMUL_8:
124
LMUL = "M8";
125
break;
126
case RISCVII::LMUL_F2:
127
LMUL = "MF2";
128
break;
129
case RISCVII::LMUL_F4:
130
LMUL = "MF4";
131
break;
132
case RISCVII::LMUL_F8:
133
LMUL = "MF8";
134
break;
135
case RISCVII::LMUL_RESERVED:
136
llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
137
}
138
SmallVector<UniqueInstrument> Instruments;
139
Instruments.emplace_back(
140
createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL));
141
142
unsigned SEW = RISCVVType::getSEW(VTypeI);
143
StringRef SEWStr;
144
switch (SEW) {
145
case 8:
146
SEWStr = "E8";
147
break;
148
case 16:
149
SEWStr = "E16";
150
break;
151
case 32:
152
SEWStr = "E32";
153
break;
154
case 64:
155
SEWStr = "E64";
156
break;
157
default:
158
llvm_unreachable("Cannot create instrument for SEW");
159
}
160
Instruments.emplace_back(
161
createInstrument(RISCVSEWInstrument::DESC_NAME, SEWStr));
162
163
return Instruments;
164
}
165
return SmallVector<UniqueInstrument>();
166
}
167
168
static std::pair<uint8_t, uint8_t>
169
getEEWAndEMUL(unsigned Opcode, RISCVII::VLMUL LMUL, uint8_t SEW) {
170
uint8_t EEW;
171
switch (Opcode) {
172
case RISCV::VLM_V:
173
case RISCV::VSM_V:
174
case RISCV::VLE8_V:
175
case RISCV::VSE8_V:
176
case RISCV::VLSE8_V:
177
case RISCV::VSSE8_V:
178
EEW = 8;
179
break;
180
case RISCV::VLE16_V:
181
case RISCV::VSE16_V:
182
case RISCV::VLSE16_V:
183
case RISCV::VSSE16_V:
184
EEW = 16;
185
break;
186
case RISCV::VLE32_V:
187
case RISCV::VSE32_V:
188
case RISCV::VLSE32_V:
189
case RISCV::VSSE32_V:
190
EEW = 32;
191
break;
192
case RISCV::VLE64_V:
193
case RISCV::VSE64_V:
194
case RISCV::VLSE64_V:
195
case RISCV::VSSE64_V:
196
EEW = 64;
197
break;
198
default:
199
llvm_unreachable("Could not determine EEW from Opcode");
200
}
201
202
auto EMUL = RISCVVType::getSameRatioLMUL(SEW, LMUL, EEW);
203
if (!EEW)
204
llvm_unreachable("Invalid SEW or LMUL for new ratio");
205
return std::make_pair(EEW, *EMUL);
206
}
207
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;
218
}
219
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();
225
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);
234
}
235
236
// Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,
237
// then no option to override.
238
if (!LI) {
239
LLVM_DEBUG(
240
dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");
241
return SchedClassID;
242
}
243
uint8_t LMUL = LI->getLMUL();
244
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;
249
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);
255
} else {
256
// Check if it depends on LMUL and SEW
257
RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW);
258
// Check if it depends only on LMUL
259
if (!RVV)
260
RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0);
261
}
262
263
// Not a RVV instr
264
if (!RVV) {
265
LLVM_DEBUG(
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');
272
return SchedClassID;
273
}
274
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();
282
}
283
284
} // namespace mca
285
} // namespace llvm
286
287
using namespace llvm;
288
using namespace mca;
289
290
static InstrumentManager *
291
createRISCVInstrumentManager(const MCSubtargetInfo &STI,
292
const MCInstrInfo &MCII) {
293
return new RISCVInstrumentManager(STI, MCII);
294
}
295
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);
302
}
303
304