diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp | 202 |
1 files changed, 159 insertions, 43 deletions
diff --git a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp index 277b976b313a..8f8684e30b3a 100644 --- a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp +++ b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp @@ -13,6 +13,7 @@ #include "RISCVCustomBehaviour.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "RISCV.h" #include "RISCVInstrInfo.h" #include "TargetInfo/RISCVTargetInfo.h" #include "llvm/MC/TargetRegistry.h" @@ -31,6 +32,7 @@ struct PseudoInfo { uint16_t Pseudo; uint16_t BaseInstr; uint8_t VLMul; + uint8_t SEW; }; #define GET_RISCVVInversePseudosTable_IMPL @@ -56,7 +58,7 @@ uint8_t RISCVLMULInstrument::getLMUL() const { // below assert(isDataValid(getData()) && "Cannot get LMUL because invalid Data value"); - // These are the LMUL values that are used in RISCV tablegen + // These are the LMUL values that are used in RISC-V tablegen return StringSwitch<uint8_t>(getData()) .Case("M1", 0b000) .Case("M2", 0b001) @@ -67,64 +69,178 @@ uint8_t RISCVLMULInstrument::getLMUL() const { .Case("MF8", 0b111); } +const llvm::StringRef RISCVSEWInstrument::DESC_NAME = "RISCV-SEW"; + +bool RISCVSEWInstrument::isDataValid(llvm::StringRef Data) { + // Return true if not one of the valid SEW strings + return StringSwitch<bool>(Data) + .Cases("E8", "E16", "E32", "E64", true) + .Default(false); +} + +uint8_t RISCVSEWInstrument::getSEW() const { + // assertion prevents us from needing llvm_unreachable in the StringSwitch + // below + assert(isDataValid(getData()) && "Cannot get SEW because invalid Data value"); + // These are the LMUL values that are used in RISC-V tablegen + return StringSwitch<uint8_t>(getData()) + .Case("E8", 8) + .Case("E16", 16) + .Case("E32", 32) + .Case("E64", 64); +} + bool RISCVInstrumentManager::supportsInstrumentType( llvm::StringRef Type) const { - // Currently, only support for RISCVLMULInstrument type - return Type == RISCVLMULInstrument::DESC_NAME; + return Type == RISCVLMULInstrument::DESC_NAME || + Type == RISCVSEWInstrument::DESC_NAME; } -SharedInstrument +UniqueInstrument 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 (Desc == RISCVLMULInstrument::DESC_NAME) { + if (!RISCVLMULInstrument::isDataValid(Data)) { + LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": " + << Data << '\n'); + return nullptr; + } + return std::make_unique<RISCVLMULInstrument>(Data); + } + + if (Desc == RISCVSEWInstrument::DESC_NAME) { + if (!RISCVSEWInstrument::isDataValid(Data)) { + LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": " + << Data << '\n'); + return nullptr; + } + return std::make_unique<RISCVSEWInstrument>(Data); } - if (RISCVLMULInstrument::isDataValid(Data)) { - LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": " - << Data << '\n'); - return nullptr; + + LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc << '\n'); + return nullptr; +} + +SmallVector<UniqueInstrument> +RISCVInstrumentManager::createInstruments(const MCInst &Inst) { + if (Inst.getOpcode() == RISCV::VSETVLI || + Inst.getOpcode() == RISCV::VSETIVLI) { + LLVM_DEBUG(dbgs() << "RVCB: Found VSETVLI and creating instrument for it: " + << Inst << "\n"); + unsigned VTypeI = Inst.getOperand(2).getImm(); + RISCVII::VLMUL VLMUL = RISCVVType::getVLMUL(VTypeI); + + StringRef LMUL; + switch (VLMUL) { + case RISCVII::LMUL_1: + LMUL = "M1"; + break; + case RISCVII::LMUL_2: + LMUL = "M2"; + break; + case RISCVII::LMUL_4: + LMUL = "M4"; + break; + case RISCVII::LMUL_8: + LMUL = "M8"; + break; + case RISCVII::LMUL_F2: + LMUL = "MF2"; + break; + case RISCVII::LMUL_F4: + LMUL = "MF4"; + break; + case RISCVII::LMUL_F8: + LMUL = "MF8"; + break; + case RISCVII::LMUL_RESERVED: + llvm_unreachable("Cannot create instrument for LMUL_RESERVED"); + } + SmallVector<UniqueInstrument> Instruments; + Instruments.emplace_back( + createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL)); + + unsigned SEW = RISCVVType::getSEW(VTypeI); + StringRef SEWStr; + switch (SEW) { + case 8: + SEWStr = "E8"; + break; + case 16: + SEWStr = "E16"; + break; + case 32: + SEWStr = "E32"; + break; + case 64: + SEWStr = "E64"; + break; + default: + llvm_unreachable("Cannot create instrument for SEW"); + } + Instruments.emplace_back( + createInstrument(RISCVSEWInstrument::DESC_NAME, SEWStr)); + + return Instruments; } - return std::make_shared<RISCVLMULInstrument>(Data); + return SmallVector<UniqueInstrument>(); } unsigned RISCVInstrumentManager::getSchedClassID( const MCInstrInfo &MCII, const MCInst &MCI, - const llvm::SmallVector<SharedInstrument> &IVec) const { + const llvm::SmallVector<Instrument *> &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(); - } + // Unpack all possible RISCV instruments from IVec. + RISCVLMULInstrument *LI = nullptr; + RISCVSEWInstrument *SI = nullptr; + for (auto &I : IVec) { + if (I->getDesc() == RISCVLMULInstrument::DESC_NAME) + LI = static_cast<RISCVLMULInstrument *>(I); + else if (I->getDesc() == RISCVSEWInstrument::DESC_NAME) + SI = static_cast<RISCVSEWInstrument *>(I); + } + + // Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided, + // then no option to override. + if (!LI) { + LLVM_DEBUG( + dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n"); + return SchedClassID; + } + uint8_t LMUL = LI->getLMUL(); + + // getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument, + // or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL + // and SEW, or (Opcode, LMUL, 0) if does not depend on SEW. + uint8_t SEW = SI ? SI->getSEW() : 0; + // Check if it depends on LMUL and SEW + const RISCVVInversePseudosTable::PseudoInfo *RVV = + RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW); + // Check if it depends only on LMUL + if (!RVV) + RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0); + + // Not a RVV instr + if (!RVV) { + LLVM_DEBUG( + dbgs() << "RVCB: Could not find PseudoInstruction for Opcode " + << MCII.getName(Opcode) + << ", LMUL=" << (LI ? LI->getData() : "Unspecified") + << ", SEW=" << (SI ? SI->getData() : "Unspecified") + << ". Ignoring instrumentation and using original SchedClassID=" + << SchedClassID << '\n'); + return SchedClassID; } - // Unknown Instrument kind - LLVM_DEBUG( - dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n"); - return SchedClassID; + // Override using pseudo + LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode " + << MCII.getName(Opcode) << ", LMUL=" << LI->getData() + << ", SEW=" << (SI ? SI->getData() : "Unspecified") + << ". Overriding original SchedClassID=" << SchedClassID + << " with " << MCII.getName(RVV->Pseudo) << '\n'); + return MCII.get(RVV->Pseudo).getSchedClass(); } } // namespace mca @@ -139,7 +255,7 @@ createRISCVInstrumentManager(const MCSubtargetInfo &STI, return new RISCVInstrumentManager(STI, MCII); } -/// Extern function to initialize the targets for the RISCV backend +/// Extern function to initialize the targets for the RISC-V backend extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA() { TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(), createRISCVInstrumentManager); |