1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
//===------------------- 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);
}
|