| //===------------------- 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<bool>(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<uint8_t>(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<RISCVLMULInstrument>(Data); | |
| } | |
| unsigned RISCVInstrumentManager::getSchedClassID( | |
| const MCInstrInfo &MCII, const MCInst &MCI, | |
| const llvm::SmallVector<SharedInstrument> &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<RISCVLMULInstrument *>(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); | |
| } |