brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.3 KiB · b00589a Raw
355 lines · cpp
1//===------------------- RISCVCustomBehaviour.cpp ---------------*-C++ -* -===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file implements methods from the RISCVCustomBehaviour class.11///12//===----------------------------------------------------------------------===//13 14#include "RISCVCustomBehaviour.h"15#include "MCTargetDesc/RISCVMCTargetDesc.h"16#include "RISCV.h"17#include "TargetInfo/RISCVTargetInfo.h"18#include "llvm/MC/TargetRegistry.h"19#include "llvm/Support/Compiler.h"20#include "llvm/Support/Debug.h"21#include "llvm/Support/DebugLog.h"22 23#define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"24 25namespace llvm::RISCV {26struct VXMemOpInfo {27  unsigned Log2IdxEEW : 3;28  unsigned IsOrdered : 1;29  unsigned IsStore : 1;30  unsigned NF : 4;31  unsigned BaseInstr;32};33 34#define GET_RISCVBaseVXMemOpTable_IMPL35#include "RISCVGenSearchableTables.inc"36} // namespace llvm::RISCV37 38namespace llvm {39namespace mca {40 41const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL";42 43bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data) {44  // Return true if not one of the valid LMUL strings45  return StringSwitch<bool>(Data)46      .Cases({"M1", "M2", "M4", "M8", "MF2", "MF4", "MF8"}, true)47      .Default(false);48}49 50uint8_t RISCVLMULInstrument::getLMUL() const {51  // assertion prevents us from needing llvm_unreachable in the StringSwitch52  // below53  assert(isDataValid(getData()) &&54         "Cannot get LMUL because invalid Data value");55  // These are the LMUL values that are used in RISC-V tablegen56  return StringSwitch<uint8_t>(getData())57      .Case("M1", 0b000)58      .Case("M2", 0b001)59      .Case("M4", 0b010)60      .Case("M8", 0b011)61      .Case("MF2", 0b111)62      .Case("MF4", 0b110)63      .Case("MF8", 0b101);64}65 66const llvm::StringRef RISCVSEWInstrument::DESC_NAME = "RISCV-SEW";67 68bool RISCVSEWInstrument::isDataValid(llvm::StringRef Data) {69  // Return true if not one of the valid SEW strings70  return StringSwitch<bool>(Data)71      .Cases({"E8", "E16", "E32", "E64"}, true)72      .Default(false);73}74 75uint8_t RISCVSEWInstrument::getSEW() const {76  // assertion prevents us from needing llvm_unreachable in the StringSwitch77  // below78  assert(isDataValid(getData()) && "Cannot get SEW because invalid Data value");79  // These are the LMUL values that are used in RISC-V tablegen80  return StringSwitch<uint8_t>(getData())81      .Case("E8", 8)82      .Case("E16", 16)83      .Case("E32", 32)84      .Case("E64", 64);85}86 87bool RISCVInstrumentManager::supportsInstrumentType(88    llvm::StringRef Type) const {89  return Type == RISCVLMULInstrument::DESC_NAME ||90         Type == RISCVSEWInstrument::DESC_NAME ||91         InstrumentManager::supportsInstrumentType(Type);92}93 94UniqueInstrument95RISCVInstrumentManager::createInstrument(llvm::StringRef Desc,96                                         llvm::StringRef Data) {97  if (Desc == RISCVLMULInstrument::DESC_NAME) {98    if (!RISCVLMULInstrument::isDataValid(Data)) {99      LDBG() << "RVCB: Bad data for instrument kind " << Desc << ": " << Data100             << '\n';101      return nullptr;102    }103    return std::make_unique<RISCVLMULInstrument>(Data);104  }105 106  if (Desc == RISCVSEWInstrument::DESC_NAME) {107    if (!RISCVSEWInstrument::isDataValid(Data)) {108      LDBG() << "RVCB: Bad data for instrument kind " << Desc << ": " << Data109             << '\n';110      return nullptr;111    }112    return std::make_unique<RISCVSEWInstrument>(Data);113  }114 115  LDBG() << "RVCB: Creating default instrument for Desc: " << Desc << '\n';116  return InstrumentManager::createInstrument(Desc, Data);117}118 119SmallVector<UniqueInstrument>120RISCVInstrumentManager::createInstruments(const MCInst &Inst) {121  if (Inst.getOpcode() == RISCV::VSETVLI ||122      Inst.getOpcode() == RISCV::VSETIVLI) {123    LDBG() << "RVCB: Found VSETVLI and creating instrument for it: " << Inst124           << "\n";125    unsigned VTypeI = Inst.getOperand(2).getImm();126    RISCVVType::VLMUL VLMUL = RISCVVType::getVLMUL(VTypeI);127 128    StringRef LMUL;129    switch (VLMUL) {130    case RISCVVType::LMUL_1:131      LMUL = "M1";132      break;133    case RISCVVType::LMUL_2:134      LMUL = "M2";135      break;136    case RISCVVType::LMUL_4:137      LMUL = "M4";138      break;139    case RISCVVType::LMUL_8:140      LMUL = "M8";141      break;142    case RISCVVType::LMUL_F2:143      LMUL = "MF2";144      break;145    case RISCVVType::LMUL_F4:146      LMUL = "MF4";147      break;148    case RISCVVType::LMUL_F8:149      LMUL = "MF8";150      break;151    case RISCVVType::LMUL_RESERVED:152      llvm_unreachable("Cannot create instrument for LMUL_RESERVED");153    }154    SmallVector<UniqueInstrument> Instruments;155    Instruments.emplace_back(156        createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL));157 158    unsigned SEW = RISCVVType::getSEW(VTypeI);159    StringRef SEWStr;160    switch (SEW) {161    case 8:162      SEWStr = "E8";163      break;164    case 16:165      SEWStr = "E16";166      break;167    case 32:168      SEWStr = "E32";169      break;170    case 64:171      SEWStr = "E64";172      break;173    default:174      llvm_unreachable("Cannot create instrument for SEW");175    }176    Instruments.emplace_back(177        createInstrument(RISCVSEWInstrument::DESC_NAME, SEWStr));178 179    return Instruments;180  }181  return SmallVector<UniqueInstrument>();182}183 184static std::pair<uint8_t, uint8_t>185getEEWAndEMUL(unsigned Opcode, RISCVVType::VLMUL LMUL, uint8_t SEW) {186  uint8_t EEW;187  switch (Opcode) {188  case RISCV::VLM_V:189  case RISCV::VSM_V:190  case RISCV::VLE8_V:191  case RISCV::VSE8_V:192  case RISCV::VLSE8_V:193  case RISCV::VSSE8_V:194    EEW = 8;195    break;196  case RISCV::VLE16_V:197  case RISCV::VSE16_V:198  case RISCV::VLSE16_V:199  case RISCV::VSSE16_V:200    EEW = 16;201    break;202  case RISCV::VLE32_V:203  case RISCV::VSE32_V:204  case RISCV::VLSE32_V:205  case RISCV::VSSE32_V:206    EEW = 32;207    break;208  case RISCV::VLE64_V:209  case RISCV::VSE64_V:210  case RISCV::VLSE64_V:211  case RISCV::VSSE64_V:212    EEW = 64;213    break;214  default:215    llvm_unreachable("Could not determine EEW from Opcode");216  }217 218  auto EMUL = RISCVVType::getSameRatioLMUL(SEW, LMUL, EEW);219  if (!EEW)220    llvm_unreachable("Invalid SEW or LMUL for new ratio");221  return std::make_pair(EEW, *EMUL);222}223 224static bool opcodeHasEEWAndEMULInfo(unsigned short Opcode) {225  return Opcode == RISCV::VLM_V || Opcode == RISCV::VSM_V ||226         Opcode == RISCV::VLE8_V || Opcode == RISCV::VSE8_V ||227         Opcode == RISCV::VLE16_V || Opcode == RISCV::VSE16_V ||228         Opcode == RISCV::VLE32_V || Opcode == RISCV::VSE32_V ||229         Opcode == RISCV::VLE64_V || Opcode == RISCV::VSE64_V ||230         Opcode == RISCV::VLSE8_V || Opcode == RISCV::VSSE8_V ||231         Opcode == RISCV::VLSE16_V || Opcode == RISCV::VSSE16_V ||232         Opcode == RISCV::VLSE32_V || Opcode == RISCV::VSSE32_V ||233         Opcode == RISCV::VLSE64_V || Opcode == RISCV::VSSE64_V;234}235 236unsigned RISCVInstrumentManager::getSchedClassID(237    const MCInstrInfo &MCII, const MCInst &MCI,238    const llvm::SmallVector<Instrument *> &IVec) const {239  unsigned short Opcode = MCI.getOpcode();240  unsigned SchedClassID = MCII.get(Opcode).getSchedClass();241 242  // Unpack all possible RISC-V instruments from IVec.243  RISCVLMULInstrument *LI = nullptr;244  RISCVSEWInstrument *SI = nullptr;245  for (auto &I : IVec) {246    if (I->getDesc() == RISCVLMULInstrument::DESC_NAME)247      LI = static_cast<RISCVLMULInstrument *>(I);248    else if (I->getDesc() == RISCVSEWInstrument::DESC_NAME)249      SI = static_cast<RISCVSEWInstrument *>(I);250  }251 252  // Need LMUL or LMUL, SEW in order to override opcode. If no LMUL is provided,253  // then no option to override.254  if (!LI) {255    LDBG() << "RVCB: Did not use instrumentation to override Opcode.\n";256    return SchedClassID;257  }258  uint8_t LMUL = LI->getLMUL();259 260  // getBaseInfo works with (Opcode, LMUL, 0) if no SEW instrument,261  // or (Opcode, LMUL, SEW) if SEW instrument is active, and depends on LMUL262  // and SEW, or (Opcode, LMUL, 0) if does not depend on SEW.263  uint8_t SEW = SI ? SI->getSEW() : 0;264 265  std::optional<unsigned> VPOpcode;266  if (const auto *VXMO = RISCV::getVXMemOpInfo(Opcode)) {267    // Calculate the expected index EMUL. For indexed operations,268    // the DataEEW and DataEMUL are equal to SEW and LMUL, respectively.269    unsigned IndexEMUL = ((1 << VXMO->Log2IdxEEW) * LMUL) / SEW;270 271    if (!VXMO->NF) {272      // Indexed Load / Store.273      if (VXMO->IsStore) {274        if (const auto *VXP = RISCV::getVSXPseudo(275                /*Masked=*/0, VXMO->IsOrdered, VXMO->Log2IdxEEW, LMUL,276                IndexEMUL))277          VPOpcode = VXP->Pseudo;278      } else {279        if (const auto *VXP = RISCV::getVLXPseudo(280                /*Masked=*/0, VXMO->IsOrdered, VXMO->Log2IdxEEW, LMUL,281                IndexEMUL))282          VPOpcode = VXP->Pseudo;283      }284    } else {285      // Segmented Indexed Load / Store.286      if (VXMO->IsStore) {287        if (const auto *VXP =288                RISCV::getVSXSEGPseudo(VXMO->NF, /*Masked=*/0, VXMO->IsOrdered,289                                       VXMO->Log2IdxEEW, LMUL, IndexEMUL))290          VPOpcode = VXP->Pseudo;291      } else {292        if (const auto *VXP =293                RISCV::getVLXSEGPseudo(VXMO->NF, /*Masked=*/0, VXMO->IsOrdered,294                                       VXMO->Log2IdxEEW, LMUL, IndexEMUL))295          VPOpcode = VXP->Pseudo;296      }297    }298  } else if (opcodeHasEEWAndEMULInfo(Opcode)) {299    RISCVVType::VLMUL VLMUL = static_cast<RISCVVType::VLMUL>(LMUL);300    auto [EEW, EMUL] = getEEWAndEMUL(Opcode, VLMUL, SEW);301    if (const auto *RVV =302            RISCVVInversePseudosTable::getBaseInfo(Opcode, EMUL, EEW))303      VPOpcode = RVV->Pseudo;304  } else {305    // Check if it depends on LMUL and SEW306    const auto *RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, SEW);307    // Check if it depends only on LMUL308    if (!RVV)309      RVV = RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL, 0);310 311    if (RVV)312      VPOpcode = RVV->Pseudo;313  }314 315  // Not a RVV instr316  if (!VPOpcode) {317    LDBG() << "RVCB: Could not find PseudoInstruction for Opcode "318           << MCII.getName(Opcode)319           << ", LMUL=" << (LI ? LI->getData() : "Unspecified")320           << ", SEW=" << (SI ? SI->getData() : "Unspecified")321           << ". Ignoring instrumentation and using original SchedClassID="322           << SchedClassID << '\n';323    return SchedClassID;324  }325 326  // Override using pseudo327  LDBG() << "RVCB: Found Pseudo Instruction for Opcode " << MCII.getName(Opcode)328         << ", LMUL=" << LI->getData()329         << ", SEW=" << (SI ? SI->getData() : "Unspecified")330         << ". Overriding original SchedClassID=" << SchedClassID << " with "331         << MCII.getName(*VPOpcode) << '\n';332  return MCII.get(*VPOpcode).getSchedClass();333}334 335} // namespace mca336} // namespace llvm337 338using namespace llvm;339using namespace mca;340 341static InstrumentManager *342createRISCVInstrumentManager(const MCSubtargetInfo &STI,343                             const MCInstrInfo &MCII) {344  return new RISCVInstrumentManager(STI, MCII);345}346 347/// Extern function to initialize the targets for the RISC-V backend348extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void349LLVMInitializeRISCVTargetMCA() {350  TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(),351                                            createRISCVInstrumentManager);352  TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(),353                                            createRISCVInstrumentManager);354}355