//===------------------- RISCVCustomBehaviour.cpp ---------------*-C++ -* -===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file /// /// This file implements methods from the RISCVCustomBehaviour class. /// //===----------------------------------------------------------------------===// #include "RISCVCustomBehaviour.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "RISCVInstrInfo.h" #include "TargetInfo/RISCVTargetInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "llvm-mca-riscv-custombehaviour" // This brings in a table with primary key of // base instruction opcode and lmul and maps // to the opcode of the pseudo instruction. namespace RISCVVInversePseudosTable { using namespace llvm; using namespace llvm::RISCV; struct PseudoInfo { uint16_t Pseudo; uint16_t BaseInstr; uint8_t VLMul; }; #define GET_RISCVVInversePseudosTable_IMPL #define GET_RISCVVInversePseudosTable_DECL #include "RISCVGenSearchableTables.inc" } // end namespace RISCVVInversePseudosTable namespace llvm { namespace mca { const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL"; bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data) { // Return true if not one of the valid LMUL strings return StringSwitch(Data) .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true) .Default(false); } uint8_t RISCVLMULInstrument::getLMUL() const { // assertion prevents us from needing llvm_unreachable in the StringSwitch // below assert(isDataValid(getData()) && "Cannot get LMUL because invalid Data value"); // These are the LMUL values that are used in RISCV tablegen return StringSwitch(getData()) .Case("M1", 0b000) .Case("M2", 0b001) .Case("M4", 0b010) .Case("M8", 0b011) .Case("MF2", 0b101) .Case("MF4", 0b110) .Case("MF8", 0b111); } bool RISCVInstrumentManager::supportsInstrumentType( llvm::StringRef Type) const { // Currently, only support for RISCVLMULInstrument type return Type == RISCVLMULInstrument::DESC_NAME; } SharedInstrument RISCVInstrumentManager::createInstrument(llvm::StringRef Desc, llvm::StringRef Data) { if (Desc != RISCVLMULInstrument::DESC_NAME) { LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc << '\n'); return nullptr; } if (RISCVLMULInstrument::isDataValid(Data)) { LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": " << Data << '\n'); return nullptr; } return std::make_shared(Data); } unsigned RISCVInstrumentManager::getSchedClassID( const MCInstrInfo &MCII, const MCInst &MCI, const llvm::SmallVector &IVec) const { unsigned short Opcode = MCI.getOpcode(); unsigned SchedClassID = MCII.get(Opcode).getSchedClass(); for (const auto &I : IVec) { // Unknown Instrument kind if (I->getDesc() == RISCVLMULInstrument::DESC_NAME) { uint8_t LMUL = static_cast(I.get())->getLMUL(); const RISCVVInversePseudosTable::PseudoInfo *RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL); // Not a RVV instr if (!RVV) { LLVM_DEBUG( dbgs() << "RVCB: Could not find PseudoInstruction for Opcode " << MCII.getName(Opcode) << ", LMUL=" << I->getData() << ". Ignoring instrumentation and using original SchedClassID=" << SchedClassID << '\n'); return SchedClassID; } // Override using pseudo LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode " << MCII.getName(Opcode) << ", LMUL=" << I->getData() << ". Overriding original SchedClassID=" << SchedClassID << " with " << MCII.getName(RVV->Pseudo) << '\n'); return MCII.get(RVV->Pseudo).getSchedClass(); } } // Unknown Instrument kind LLVM_DEBUG( dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n"); return SchedClassID; } } // namespace mca } // namespace llvm using namespace llvm; using namespace mca; static InstrumentManager * createRISCVInstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII) { return new RISCVInstrumentManager(STI, MCII); } /// Extern function to initialize the targets for the RISCV backend extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA() { TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(), createRISCVInstrumentManager); TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(), createRISCVInstrumentManager); }