LLVM 18.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"
19#include "llvm/Support/Debug.h"
20
21#define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"
22
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.
27using namespace llvm;
28using namespace llvm::RISCV;
29
30struct PseudoInfo {
33 uint8_t VLMul;
34 uint8_t SEW;
35};
36
37#define GET_RISCVVInversePseudosTable_IMPL
38#define GET_RISCVVInversePseudosTable_DECL
39#include "RISCVGenSearchableTables.inc"
40
41} // end namespace RISCVVInversePseudosTable
42
43namespace llvm {
44namespace mca {
45
47
49 // Return true if not one of the valid LMUL strings
51 .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)
52 .Default(false);
53}
54
56 // assertion prevents us from needing llvm_unreachable in the StringSwitch
57 // below
59 "Cannot get LMUL because invalid Data value");
60 // These are the LMUL values that are used in RISC-V tablegen
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);
69}
70
72
74 // Return true if not one of the valid SEW strings
76 .Cases("E8", "E16", "E32", "E64", true)
77 .Default(false);
78}
79
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
86 .Case("E8", 8)
87 .Case("E16", 16)
88 .Case("E32", 32)
89 .Case("E64", 64);
90}
91
93 llvm::StringRef Type) const {
96}
97
103 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
104 << Data << '\n');
105 return nullptr;
106 }
107 return std::make_unique<RISCVLMULInstrument>(Data);
108 }
109
112 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
113 << Data << '\n');
114 return nullptr;
115 }
116 return std::make_unique<RISCVSEWInstrument>(Data);
117 }
118
119 LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc << '\n');
120 return nullptr;
121}
122
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);
131
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;
156 llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
157 }
159 Instruments.emplace_back(
161
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");
179 }
180 Instruments.emplace_back(
182
183 return Instruments;
184 }
186}
187
189 const MCInstrInfo &MCII, const MCInst &MCI,
190 const llvm::SmallVector<Instrument *> &IVec) const {
191 unsigned short Opcode = MCI.getOpcode();
192 unsigned SchedClassID = MCII.get(Opcode).getSchedClass();
193
194 // Unpack all possible RISCV instruments from IVec.
195 RISCVLMULInstrument *LI = nullptr;
196 RISCVSEWInstrument *SI = nullptr;
197 for (auto &I : IVec) {
198 if (I->getDesc() == RISCVLMULInstrument::DESC_NAME)
199 LI = static_cast<RISCVLMULInstrument *>(I);
200 else if (I->getDesc() == RISCVSEWInstrument::DESC_NAME)
201 SI = static_cast<RISCVSEWInstrument *>(I);
202 }
203
204 // Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,
205 // then no option to override.
206 if (!LI) {
208 dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");
209 return SchedClassID;
210 }
211 uint8_t LMUL = LI->getLMUL();
212
213 // getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument,
214 // or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL
215 // and SEW, or (Opcode, LMUL, 0) if does not depend on SEW.
216 uint8_t SEW = SI ? SI->getSEW() : 0;
217 // Check if it depends on LMUL and SEW
219 RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW);
220 // Check if it depends only on LMUL
221 if (!RVV)
222 RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0);
223
224 // Not a RVV instr
225 if (!RVV) {
227 dbgs() << "RVCB: Could not find PseudoInstruction for Opcode "
228 << MCII.getName(Opcode)
229 << ", LMUL=" << (LI ? LI->getData() : "Unspecified")
230 << ", SEW=" << (SI ? SI->getData() : "Unspecified")
231 << ". Ignoring instrumentation and using original SchedClassID="
232 << SchedClassID << '\n');
233 return SchedClassID;
234 }
235
236 // Override using pseudo
237 LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode "
238 << MCII.getName(Opcode) << ", LMUL=" << LI->getData()
239 << ", SEW=" << (SI ? SI->getData() : "Unspecified")
240 << ". Overriding original SchedClassID=" << SchedClassID
241 << " with " << MCII.getName(RVV->Pseudo) << '\n');
242 return MCII.get(RVV->Pseudo).getSchedClass();
243}
244
245} // namespace mca
246} // namespace llvm
247
248using namespace llvm;
249using namespace mca;
250
251static InstrumentManager *
253 const MCInstrInfo &MCII) {
254 return new RISCVInstrumentManager(STI, MCII);
255}
256
257/// Extern function to initialize the targets for the RISC-V backend
263}
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
#define LLVM_DEBUG(X)
Definition: Debug.h:101
#define I(x, y, z)
Definition: MD5.cpp:58
static InstrumentManager * createRISCVInstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA()
Extern function to initialize the targets for the RISC-V backend.
This file defines the RISCVCustomBehaviour class which inherits from CustomBehaviour.
unsigned SEW
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
unsigned getOpcode() const
Definition: MCInst.h:198
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Definition: MCInstrDesc.h:600
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:63
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition: MCInstrInfo.h:70
int64_t getImm() const
Definition: MCInst.h:80
Generic base class for all target subtargets.
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:941
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Definition: StringSwitch.h:90
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.
static RISCVII::VLMUL getVLMUL(unsigned VType)
static unsigned getSEW(unsigned VType)
std::unique_ptr< Instrument > UniqueInstrument
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheRISCV32Target()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
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.