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 "RISCVInstrInfo.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 // 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; 29 30 struct PseudoInfo { 31 uint16_t Pseudo; 32 uint16_t BaseInstr; 33 uint8_t VLMul; 34 }; 35 36 #define GET_RISCVVInversePseudosTable_IMPL 37 #define GET_RISCVVInversePseudosTable_DECL 38 #include "RISCVGenSearchableTables.inc" 39 40 } // end namespace RISCVVInversePseudosTable 41 42 namespace llvm { 43 namespace mca { 44 45 const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL"; 46 47 bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data) { 48 // Return true if not one of the valid LMUL strings 49 return StringSwitch<bool>(Data) 50 .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true) 51 .Default(false); 52 } 53 54 uint8_t RISCVLMULInstrument::getLMUL() const { 55 // assertion prevents us from needing llvm_unreachable in the StringSwitch 56 // below 57 assert(isDataValid(getData()) && 58 "Cannot get LMUL because invalid Data value"); 59 // These are the LMUL values that are used in RISCV tablegen 60 return StringSwitch<uint8_t>(getData()) 61 .Case("M1", 0b000) 62 .Case("M2", 0b001) 63 .Case("M4", 0b010) 64 .Case("M8", 0b011) 65 .Case("MF2", 0b101) 66 .Case("MF4", 0b110) 67 .Case("MF8", 0b111); 68 } 69 70 bool RISCVInstrumentManager::supportsInstrumentType( 71 llvm::StringRef Type) const { 72 // Currently, only support for RISCVLMULInstrument type 73 return Type == RISCVLMULInstrument::DESC_NAME; 74 } 75 76 SharedInstrument 77 RISCVInstrumentManager::createInstrument(llvm::StringRef Desc, 78 llvm::StringRef Data) { 79 if (Desc != RISCVLMULInstrument::DESC_NAME) { 80 LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc 81 << '\n'); 82 return nullptr; 83 } 84 if (RISCVLMULInstrument::isDataValid(Data)) { 85 LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": " 86 << Data << '\n'); 87 return nullptr; 88 } 89 return std::make_shared<RISCVLMULInstrument>(Data); 90 } 91 92 unsigned RISCVInstrumentManager::getSchedClassID( 93 const MCInstrInfo &MCII, const MCInst &MCI, 94 const llvm::SmallVector<SharedInstrument> &IVec) const { 95 unsigned short Opcode = MCI.getOpcode(); 96 unsigned SchedClassID = MCII.get(Opcode).getSchedClass(); 97 98 for (const auto &I : IVec) { 99 // Unknown Instrument kind 100 if (I->getDesc() == RISCVLMULInstrument::DESC_NAME) { 101 uint8_t LMUL = static_cast<RISCVLMULInstrument *>(I.get())->getLMUL(); 102 const RISCVVInversePseudosTable::PseudoInfo *RVV = 103 RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL); 104 // Not a RVV instr 105 if (!RVV) { 106 LLVM_DEBUG( 107 dbgs() 108 << "RVCB: Could not find PseudoInstruction for Opcode " 109 << MCII.getName(Opcode) << ", LMUL=" << I->getData() 110 << ". Ignoring instrumentation and using original SchedClassID=" 111 << SchedClassID << '\n'); 112 return SchedClassID; 113 } 114 115 // Override using pseudo 116 LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode " 117 << MCII.getName(Opcode) << ", LMUL=" << I->getData() 118 << ". Overriding original SchedClassID=" << SchedClassID 119 << " with " << MCII.getName(RVV->Pseudo) << '\n'); 120 return MCII.get(RVV->Pseudo).getSchedClass(); 121 } 122 } 123 124 // Unknown Instrument kind 125 LLVM_DEBUG( 126 dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n"); 127 return SchedClassID; 128 } 129 130 } // namespace mca 131 } // namespace llvm 132 133 using namespace llvm; 134 using namespace mca; 135 136 static InstrumentManager * 137 createRISCVInstrumentManager(const MCSubtargetInfo &STI, 138 const MCInstrInfo &MCII) { 139 return new RISCVInstrumentManager(STI, MCII); 140 } 141 142 /// Extern function to initialize the targets for the RISCV backend 143 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA() { 144 TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(), 145 createRISCVInstrumentManager); 146 TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(), 147 createRISCVInstrumentManager); 148 } 149