Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
35294 views
//===------------------- RISCVCustomBehaviour.cpp ---------------*-C++ -* -===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file implements methods from the RISCVCustomBehaviour class.10///11//===----------------------------------------------------------------------===//1213#include "RISCVCustomBehaviour.h"14#include "MCTargetDesc/RISCVMCTargetDesc.h"15#include "RISCV.h"16#include "TargetInfo/RISCVTargetInfo.h"17#include "llvm/MC/TargetRegistry.h"18#include "llvm/Support/Debug.h"1920#define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"2122namespace llvm {23namespace mca {2425const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL";2627bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data) {28// Return true if not one of the valid LMUL strings29return StringSwitch<bool>(Data)30.Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)31.Default(false);32}3334uint8_t RISCVLMULInstrument::getLMUL() const {35// assertion prevents us from needing llvm_unreachable in the StringSwitch36// below37assert(isDataValid(getData()) &&38"Cannot get LMUL because invalid Data value");39// These are the LMUL values that are used in RISC-V tablegen40return StringSwitch<uint8_t>(getData())41.Case("M1", 0b000)42.Case("M2", 0b001)43.Case("M4", 0b010)44.Case("M8", 0b011)45.Case("MF2", 0b111)46.Case("MF4", 0b110)47.Case("MF8", 0b101);48}4950const llvm::StringRef RISCVSEWInstrument::DESC_NAME = "RISCV-SEW";5152bool RISCVSEWInstrument::isDataValid(llvm::StringRef Data) {53// Return true if not one of the valid SEW strings54return StringSwitch<bool>(Data)55.Cases("E8", "E16", "E32", "E64", true)56.Default(false);57}5859uint8_t RISCVSEWInstrument::getSEW() const {60// assertion prevents us from needing llvm_unreachable in the StringSwitch61// below62assert(isDataValid(getData()) && "Cannot get SEW because invalid Data value");63// These are the LMUL values that are used in RISC-V tablegen64return StringSwitch<uint8_t>(getData())65.Case("E8", 8)66.Case("E16", 16)67.Case("E32", 32)68.Case("E64", 64);69}7071bool RISCVInstrumentManager::supportsInstrumentType(72llvm::StringRef Type) const {73return Type == RISCVLMULInstrument::DESC_NAME ||74Type == RISCVSEWInstrument::DESC_NAME;75}7677UniqueInstrument78RISCVInstrumentManager::createInstrument(llvm::StringRef Desc,79llvm::StringRef Data) {80if (Desc == RISCVLMULInstrument::DESC_NAME) {81if (!RISCVLMULInstrument::isDataValid(Data)) {82LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "83<< Data << '\n');84return nullptr;85}86return std::make_unique<RISCVLMULInstrument>(Data);87}8889if (Desc == RISCVSEWInstrument::DESC_NAME) {90if (!RISCVSEWInstrument::isDataValid(Data)) {91LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "92<< Data << '\n');93return nullptr;94}95return std::make_unique<RISCVSEWInstrument>(Data);96}9798LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc << '\n');99return nullptr;100}101102SmallVector<UniqueInstrument>103RISCVInstrumentManager::createInstruments(const MCInst &Inst) {104if (Inst.getOpcode() == RISCV::VSETVLI ||105Inst.getOpcode() == RISCV::VSETIVLI) {106LLVM_DEBUG(dbgs() << "RVCB: Found VSETVLI and creating instrument for it: "107<< Inst << "\n");108unsigned VTypeI = Inst.getOperand(2).getImm();109RISCVII::VLMUL VLMUL = RISCVVType::getVLMUL(VTypeI);110111StringRef LMUL;112switch (VLMUL) {113case RISCVII::LMUL_1:114LMUL = "M1";115break;116case RISCVII::LMUL_2:117LMUL = "M2";118break;119case RISCVII::LMUL_4:120LMUL = "M4";121break;122case RISCVII::LMUL_8:123LMUL = "M8";124break;125case RISCVII::LMUL_F2:126LMUL = "MF2";127break;128case RISCVII::LMUL_F4:129LMUL = "MF4";130break;131case RISCVII::LMUL_F8:132LMUL = "MF8";133break;134case RISCVII::LMUL_RESERVED:135llvm_unreachable("Cannot create instrument for LMUL_RESERVED");136}137SmallVector<UniqueInstrument> Instruments;138Instruments.emplace_back(139createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL));140141unsigned SEW = RISCVVType::getSEW(VTypeI);142StringRef SEWStr;143switch (SEW) {144case 8:145SEWStr = "E8";146break;147case 16:148SEWStr = "E16";149break;150case 32:151SEWStr = "E32";152break;153case 64:154SEWStr = "E64";155break;156default:157llvm_unreachable("Cannot create instrument for SEW");158}159Instruments.emplace_back(160createInstrument(RISCVSEWInstrument::DESC_NAME, SEWStr));161162return Instruments;163}164return SmallVector<UniqueInstrument>();165}166167static std::pair<uint8_t, uint8_t>168getEEWAndEMUL(unsigned Opcode, RISCVII::VLMUL LMUL, uint8_t SEW) {169uint8_t EEW;170switch (Opcode) {171case RISCV::VLM_V:172case RISCV::VSM_V:173case RISCV::VLE8_V:174case RISCV::VSE8_V:175case RISCV::VLSE8_V:176case RISCV::VSSE8_V:177EEW = 8;178break;179case RISCV::VLE16_V:180case RISCV::VSE16_V:181case RISCV::VLSE16_V:182case RISCV::VSSE16_V:183EEW = 16;184break;185case RISCV::VLE32_V:186case RISCV::VSE32_V:187case RISCV::VLSE32_V:188case RISCV::VSSE32_V:189EEW = 32;190break;191case RISCV::VLE64_V:192case RISCV::VSE64_V:193case RISCV::VLSE64_V:194case RISCV::VSSE64_V:195EEW = 64;196break;197default:198llvm_unreachable("Could not determine EEW from Opcode");199}200201auto EMUL = RISCVVType::getSameRatioLMUL(SEW, LMUL, EEW);202if (!EEW)203llvm_unreachable("Invalid SEW or LMUL for new ratio");204return std::make_pair(EEW, *EMUL);205}206207bool opcodeHasEEWAndEMULInfo(unsigned short Opcode) {208return Opcode == RISCV::VLM_V || Opcode == RISCV::VSM_V ||209Opcode == RISCV::VLE8_V || Opcode == RISCV::VSE8_V ||210Opcode == RISCV::VLE16_V || Opcode == RISCV::VSE16_V ||211Opcode == RISCV::VLE32_V || Opcode == RISCV::VSE32_V ||212Opcode == RISCV::VLE64_V || Opcode == RISCV::VSE64_V ||213Opcode == RISCV::VLSE8_V || Opcode == RISCV::VSSE8_V ||214Opcode == RISCV::VLSE16_V || Opcode == RISCV::VSSE16_V ||215Opcode == RISCV::VLSE32_V || Opcode == RISCV::VSSE32_V ||216Opcode == RISCV::VLSE64_V || Opcode == RISCV::VSSE64_V;217}218219unsigned RISCVInstrumentManager::getSchedClassID(220const MCInstrInfo &MCII, const MCInst &MCI,221const llvm::SmallVector<Instrument *> &IVec) const {222unsigned short Opcode = MCI.getOpcode();223unsigned SchedClassID = MCII.get(Opcode).getSchedClass();224225// Unpack all possible RISC-V instruments from IVec.226RISCVLMULInstrument *LI = nullptr;227RISCVSEWInstrument *SI = nullptr;228for (auto &I : IVec) {229if (I->getDesc() == RISCVLMULInstrument::DESC_NAME)230LI = static_cast<RISCVLMULInstrument *>(I);231else if (I->getDesc() == RISCVSEWInstrument::DESC_NAME)232SI = static_cast<RISCVSEWInstrument *>(I);233}234235// Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,236// then no option to override.237if (!LI) {238LLVM_DEBUG(239dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");240return SchedClassID;241}242uint8_t LMUL = LI->getLMUL();243244// getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument,245// or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL246// and SEW, or (Opcode, LMUL, 0) if does not depend on SEW.247uint8_t SEW = SI ? SI->getSEW() : 0;248249const RISCVVInversePseudosTable::PseudoInfo *RVV = nullptr;250if (opcodeHasEEWAndEMULInfo(Opcode)) {251RISCVII::VLMUL VLMUL = static_cast<RISCVII::VLMUL>(LMUL);252auto [EEW, EMUL] = getEEWAndEMUL(Opcode, VLMUL, SEW);253RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, EMUL, EEW);254} else {255// Check if it depends on LMUL and SEW256RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW);257// Check if it depends only on LMUL258if (!RVV)259RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0);260}261262// Not a RVV instr263if (!RVV) {264LLVM_DEBUG(265dbgs() << "RVCB: Could not find PseudoInstruction for Opcode "266<< MCII.getName(Opcode)267<< ", LMUL=" << (LI ? LI->getData() : "Unspecified")268<< ", SEW=" << (SI ? SI->getData() : "Unspecified")269<< ". Ignoring instrumentation and using original SchedClassID="270<< SchedClassID << '\n');271return SchedClassID;272}273274// Override using pseudo275LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode "276<< MCII.getName(Opcode) << ", LMUL=" << LI->getData()277<< ", SEW=" << (SI ? SI->getData() : "Unspecified")278<< ". Overriding original SchedClassID=" << SchedClassID279<< " with " << MCII.getName(RVV->Pseudo) << '\n');280return MCII.get(RVV->Pseudo).getSchedClass();281}282283} // namespace mca284} // namespace llvm285286using namespace llvm;287using namespace mca;288289static InstrumentManager *290createRISCVInstrumentManager(const MCSubtargetInfo &STI,291const MCInstrInfo &MCII) {292return new RISCVInstrumentManager(STI, MCII);293}294295/// Extern function to initialize the targets for the RISC-V backend296extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA() {297TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(),298createRISCVInstrumentManager);299TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(),300createRISCVInstrumentManager);301}302303304