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