xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1*bdd1243dSDimitry Andric //===------------------- RISCVCustomBehaviour.cpp ---------------*-C++ -* -===//
2*bdd1243dSDimitry Andric //
3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bdd1243dSDimitry Andric //
7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8*bdd1243dSDimitry Andric /// \file
9*bdd1243dSDimitry Andric ///
10*bdd1243dSDimitry Andric /// This file implements methods from the RISCVCustomBehaviour class.
11*bdd1243dSDimitry Andric ///
12*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
13*bdd1243dSDimitry Andric 
14*bdd1243dSDimitry Andric #include "RISCVCustomBehaviour.h"
15*bdd1243dSDimitry Andric #include "MCTargetDesc/RISCVMCTargetDesc.h"
16*bdd1243dSDimitry Andric #include "RISCVInstrInfo.h"
17*bdd1243dSDimitry Andric #include "TargetInfo/RISCVTargetInfo.h"
18*bdd1243dSDimitry Andric #include "llvm/MC/TargetRegistry.h"
19*bdd1243dSDimitry Andric #include "llvm/Support/Debug.h"
20*bdd1243dSDimitry Andric 
21*bdd1243dSDimitry Andric #define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"
22*bdd1243dSDimitry Andric 
23*bdd1243dSDimitry Andric // This brings in a table with primary key of
24*bdd1243dSDimitry Andric // base instruction opcode and lmul and maps
25*bdd1243dSDimitry Andric // to the opcode of the pseudo instruction.
26*bdd1243dSDimitry Andric namespace RISCVVInversePseudosTable {
27*bdd1243dSDimitry Andric using namespace llvm;
28*bdd1243dSDimitry Andric using namespace llvm::RISCV;
29*bdd1243dSDimitry Andric 
30*bdd1243dSDimitry Andric struct PseudoInfo {
31*bdd1243dSDimitry Andric   uint16_t Pseudo;
32*bdd1243dSDimitry Andric   uint16_t BaseInstr;
33*bdd1243dSDimitry Andric   uint8_t VLMul;
34*bdd1243dSDimitry Andric };
35*bdd1243dSDimitry Andric 
36*bdd1243dSDimitry Andric #define GET_RISCVVInversePseudosTable_IMPL
37*bdd1243dSDimitry Andric #define GET_RISCVVInversePseudosTable_DECL
38*bdd1243dSDimitry Andric #include "RISCVGenSearchableTables.inc"
39*bdd1243dSDimitry Andric 
40*bdd1243dSDimitry Andric } // end namespace RISCVVInversePseudosTable
41*bdd1243dSDimitry Andric 
42*bdd1243dSDimitry Andric namespace llvm {
43*bdd1243dSDimitry Andric namespace mca {
44*bdd1243dSDimitry Andric 
45*bdd1243dSDimitry Andric const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL";
46*bdd1243dSDimitry Andric 
47*bdd1243dSDimitry Andric bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data) {
48*bdd1243dSDimitry Andric   // Return true if not one of the valid LMUL strings
49*bdd1243dSDimitry Andric   return StringSwitch<bool>(Data)
50*bdd1243dSDimitry Andric       .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)
51*bdd1243dSDimitry Andric       .Default(false);
52*bdd1243dSDimitry Andric }
53*bdd1243dSDimitry Andric 
54*bdd1243dSDimitry Andric uint8_t RISCVLMULInstrument::getLMUL() const {
55*bdd1243dSDimitry Andric   // assertion prevents us from needing llvm_unreachable in the StringSwitch
56*bdd1243dSDimitry Andric   // below
57*bdd1243dSDimitry Andric   assert(isDataValid(getData()) &&
58*bdd1243dSDimitry Andric          "Cannot get LMUL because invalid Data value");
59*bdd1243dSDimitry Andric   // These are the LMUL values that are used in RISCV tablegen
60*bdd1243dSDimitry Andric   return StringSwitch<uint8_t>(getData())
61*bdd1243dSDimitry Andric       .Case("M1", 0b000)
62*bdd1243dSDimitry Andric       .Case("M2", 0b001)
63*bdd1243dSDimitry Andric       .Case("M4", 0b010)
64*bdd1243dSDimitry Andric       .Case("M8", 0b011)
65*bdd1243dSDimitry Andric       .Case("MF2", 0b101)
66*bdd1243dSDimitry Andric       .Case("MF4", 0b110)
67*bdd1243dSDimitry Andric       .Case("MF8", 0b111);
68*bdd1243dSDimitry Andric }
69*bdd1243dSDimitry Andric 
70*bdd1243dSDimitry Andric bool RISCVInstrumentManager::supportsInstrumentType(
71*bdd1243dSDimitry Andric     llvm::StringRef Type) const {
72*bdd1243dSDimitry Andric   // Currently, only support for RISCVLMULInstrument type
73*bdd1243dSDimitry Andric   return Type == RISCVLMULInstrument::DESC_NAME;
74*bdd1243dSDimitry Andric }
75*bdd1243dSDimitry Andric 
76*bdd1243dSDimitry Andric SharedInstrument
77*bdd1243dSDimitry Andric RISCVInstrumentManager::createInstrument(llvm::StringRef Desc,
78*bdd1243dSDimitry Andric                                          llvm::StringRef Data) {
79*bdd1243dSDimitry Andric   if (Desc != RISCVLMULInstrument::DESC_NAME) {
80*bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc
81*bdd1243dSDimitry Andric                       << '\n');
82*bdd1243dSDimitry Andric     return nullptr;
83*bdd1243dSDimitry Andric   }
84*bdd1243dSDimitry Andric   if (RISCVLMULInstrument::isDataValid(Data)) {
85*bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
86*bdd1243dSDimitry Andric                       << Data << '\n');
87*bdd1243dSDimitry Andric     return nullptr;
88*bdd1243dSDimitry Andric   }
89*bdd1243dSDimitry Andric   return std::make_shared<RISCVLMULInstrument>(Data);
90*bdd1243dSDimitry Andric }
91*bdd1243dSDimitry Andric 
92*bdd1243dSDimitry Andric unsigned RISCVInstrumentManager::getSchedClassID(
93*bdd1243dSDimitry Andric     const MCInstrInfo &MCII, const MCInst &MCI,
94*bdd1243dSDimitry Andric     const llvm::SmallVector<SharedInstrument> &IVec) const {
95*bdd1243dSDimitry Andric   unsigned short Opcode = MCI.getOpcode();
96*bdd1243dSDimitry Andric   unsigned SchedClassID = MCII.get(Opcode).getSchedClass();
97*bdd1243dSDimitry Andric 
98*bdd1243dSDimitry Andric   for (const auto &I : IVec) {
99*bdd1243dSDimitry Andric     // Unknown Instrument kind
100*bdd1243dSDimitry Andric     if (I->getDesc() == RISCVLMULInstrument::DESC_NAME) {
101*bdd1243dSDimitry Andric       uint8_t LMUL = static_cast<RISCVLMULInstrument *>(I.get())->getLMUL();
102*bdd1243dSDimitry Andric       const RISCVVInversePseudosTable::PseudoInfo *RVV =
103*bdd1243dSDimitry Andric           RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL);
104*bdd1243dSDimitry Andric       // Not a RVV instr
105*bdd1243dSDimitry Andric       if (!RVV) {
106*bdd1243dSDimitry Andric         LLVM_DEBUG(
107*bdd1243dSDimitry Andric             dbgs()
108*bdd1243dSDimitry Andric             << "RVCB: Could not find PseudoInstruction for Opcode "
109*bdd1243dSDimitry Andric             << MCII.getName(Opcode) << ", LMUL=" << I->getData()
110*bdd1243dSDimitry Andric             << ". Ignoring instrumentation and using original SchedClassID="
111*bdd1243dSDimitry Andric             << SchedClassID << '\n');
112*bdd1243dSDimitry Andric         return SchedClassID;
113*bdd1243dSDimitry Andric       }
114*bdd1243dSDimitry Andric 
115*bdd1243dSDimitry Andric       // Override using pseudo
116*bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode "
117*bdd1243dSDimitry Andric                         << MCII.getName(Opcode) << ", LMUL=" << I->getData()
118*bdd1243dSDimitry Andric                         << ". Overriding original SchedClassID=" << SchedClassID
119*bdd1243dSDimitry Andric                         << " with " << MCII.getName(RVV->Pseudo) << '\n');
120*bdd1243dSDimitry Andric       return MCII.get(RVV->Pseudo).getSchedClass();
121*bdd1243dSDimitry Andric     }
122*bdd1243dSDimitry Andric   }
123*bdd1243dSDimitry Andric 
124*bdd1243dSDimitry Andric   // Unknown Instrument kind
125*bdd1243dSDimitry Andric   LLVM_DEBUG(
126*bdd1243dSDimitry Andric       dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");
127*bdd1243dSDimitry Andric   return SchedClassID;
128*bdd1243dSDimitry Andric }
129*bdd1243dSDimitry Andric 
130*bdd1243dSDimitry Andric } // namespace mca
131*bdd1243dSDimitry Andric } // namespace llvm
132*bdd1243dSDimitry Andric 
133*bdd1243dSDimitry Andric using namespace llvm;
134*bdd1243dSDimitry Andric using namespace mca;
135*bdd1243dSDimitry Andric 
136*bdd1243dSDimitry Andric static InstrumentManager *
137*bdd1243dSDimitry Andric createRISCVInstrumentManager(const MCSubtargetInfo &STI,
138*bdd1243dSDimitry Andric                              const MCInstrInfo &MCII) {
139*bdd1243dSDimitry Andric   return new RISCVInstrumentManager(STI, MCII);
140*bdd1243dSDimitry Andric }
141*bdd1243dSDimitry Andric 
142*bdd1243dSDimitry Andric /// Extern function to initialize the targets for the RISCV backend
143*bdd1243dSDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA() {
144*bdd1243dSDimitry Andric   TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(),
145*bdd1243dSDimitry Andric                                             createRISCVInstrumentManager);
146*bdd1243dSDimitry Andric   TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(),
147*bdd1243dSDimitry Andric                                             createRISCVInstrumentManager);
148*bdd1243dSDimitry Andric }
149