brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · 7b9e9fb Raw
198 lines · cpp
1//===-- RISCVInsertReadWriteCSR.cpp - Insert Read/Write of RISC-V CSR -----===//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// This file implements the machine function pass to insert read/write of CSR-s9// of the RISC-V instructions.10//11// Currently the pass implements:12// -Writing and saving frm before an RVV floating-point instruction with a13//  static rounding mode and restores the value after.14//15//===----------------------------------------------------------------------===//16 17#include "MCTargetDesc/RISCVBaseInfo.h"18#include "RISCV.h"19#include "RISCVSubtarget.h"20#include "llvm/CodeGen/MachineFunctionPass.h"21using namespace llvm;22 23#define DEBUG_TYPE "riscv-insert-read-write-csr"24#define RISCV_INSERT_READ_WRITE_CSR_NAME "RISC-V Insert Read/Write CSR Pass"25 26static cl::opt<bool>27    DisableFRMInsertOpt("riscv-disable-frm-insert-opt", cl::init(false),28                        cl::Hidden,29                        cl::desc("Disable optimized frm insertion."));30 31namespace {32 33class RISCVInsertReadWriteCSR : public MachineFunctionPass {34  const TargetInstrInfo *TII;35 36public:37  static char ID;38 39  RISCVInsertReadWriteCSR() : MachineFunctionPass(ID) {}40 41  bool runOnMachineFunction(MachineFunction &MF) override;42 43  void getAnalysisUsage(AnalysisUsage &AU) const override {44    AU.setPreservesCFG();45    MachineFunctionPass::getAnalysisUsage(AU);46  }47 48  StringRef getPassName() const override {49    return RISCV_INSERT_READ_WRITE_CSR_NAME;50  }51 52private:53  bool emitWriteRoundingMode(MachineBasicBlock &MBB);54  bool emitWriteRoundingModeOpt(MachineBasicBlock &MBB);55};56 57} // end anonymous namespace58 59char RISCVInsertReadWriteCSR::ID = 0;60 61INITIALIZE_PASS(RISCVInsertReadWriteCSR, DEBUG_TYPE,62                RISCV_INSERT_READ_WRITE_CSR_NAME, false, false)63 64// TODO: Use more accurate rounding mode at the start of MBB.65bool RISCVInsertReadWriteCSR::emitWriteRoundingModeOpt(MachineBasicBlock &MBB) {66  bool Changed = false;67  MachineInstr *LastFRMChanger = nullptr;68  unsigned CurrentRM = RISCVFPRndMode::DYN;69  Register SavedFRM;70 71  for (MachineInstr &MI : MBB) {72    if (MI.getOpcode() == RISCV::SwapFRMImm ||73        MI.getOpcode() == RISCV::WriteFRMImm) {74      CurrentRM = MI.getOperand(0).getImm();75      SavedFRM = Register();76      continue;77    }78 79    if (MI.getOpcode() == RISCV::WriteFRM) {80      CurrentRM = RISCVFPRndMode::DYN;81      SavedFRM = Register();82      continue;83    }84 85    if (MI.isCall() || MI.isInlineAsm() ||86        MI.readsRegister(RISCV::FRM, /*TRI=*/nullptr)) {87      // Restore FRM before unknown operations.88      if (SavedFRM.isValid())89        BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::WriteFRM))90            .addReg(SavedFRM);91      CurrentRM = RISCVFPRndMode::DYN;92      SavedFRM = Register();93      continue;94    }95 96    assert(!MI.modifiesRegister(RISCV::FRM, /*TRI=*/nullptr) &&97           "Expected that MI could not modify FRM.");98 99    int FRMIdx = RISCVII::getFRMOpNum(MI.getDesc());100    if (FRMIdx < 0)101      continue;102    unsigned InstrRM = MI.getOperand(FRMIdx).getImm();103 104    LastFRMChanger = &MI;105 106    // Make MI implicit use FRM.107    MI.addOperand(MachineOperand::CreateReg(RISCV::FRM, /*IsDef*/ false,108                                            /*IsImp*/ true));109    Changed = true;110 111    // Skip if MI uses same rounding mode as FRM.112    if (InstrRM == CurrentRM)113      continue;114 115    if (!SavedFRM.isValid()) {116      // Save current FRM value to SavedFRM.117      MachineRegisterInfo *MRI = &MBB.getParent()->getRegInfo();118      SavedFRM = MRI->createVirtualRegister(&RISCV::GPRRegClass);119      BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::SwapFRMImm), SavedFRM)120          .addImm(InstrRM);121    } else {122      // Don't need to save current FRM when SavedFRM having value.123      BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::WriteFRMImm))124          .addImm(InstrRM);125    }126    CurrentRM = InstrRM;127  }128 129  // Restore FRM if needed.130  if (SavedFRM.isValid()) {131    assert(LastFRMChanger && "Expected valid pointer.");132    MachineInstrBuilder MIB =133        BuildMI(*MBB.getParent(), {}, TII->get(RISCV::WriteFRM))134            .addReg(SavedFRM);135    MBB.insertAfter(LastFRMChanger, MIB);136  }137 138  return Changed;139}140 141// This function also swaps frm and restores it when encountering an RVV142// floating point instruction with a static rounding mode.143bool RISCVInsertReadWriteCSR::emitWriteRoundingMode(MachineBasicBlock &MBB) {144  bool Changed = false;145  for (MachineInstr &MI : MBB) {146    int FRMIdx = RISCVII::getFRMOpNum(MI.getDesc());147    if (FRMIdx < 0)148      continue;149 150    unsigned FRMImm = MI.getOperand(FRMIdx).getImm();151 152    // The value is a hint to this pass to not alter the frm value.153    if (FRMImm == RISCVFPRndMode::DYN)154      continue;155 156    Changed = true;157 158    // Save159    MachineRegisterInfo *MRI = &MBB.getParent()->getRegInfo();160    Register SavedFRM = MRI->createVirtualRegister(&RISCV::GPRRegClass);161    BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::SwapFRMImm),162            SavedFRM)163        .addImm(FRMImm);164    MI.addOperand(MachineOperand::CreateReg(RISCV::FRM, /*IsDef*/ false,165                                            /*IsImp*/ true));166    // Restore167    MachineInstrBuilder MIB =168        BuildMI(*MBB.getParent(), {}, TII->get(RISCV::WriteFRM))169            .addReg(SavedFRM);170    MBB.insertAfter(MI, MIB);171  }172  return Changed;173}174 175bool RISCVInsertReadWriteCSR::runOnMachineFunction(MachineFunction &MF) {176  // Skip if the vector extension is not enabled.177  const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();178  if (!ST.hasVInstructions())179    return false;180 181  TII = ST.getInstrInfo();182 183  bool Changed = false;184 185  for (MachineBasicBlock &MBB : MF) {186    if (DisableFRMInsertOpt)187      Changed |= emitWriteRoundingMode(MBB);188    else189      Changed |= emitWriteRoundingModeOpt(MBB);190  }191 192  return Changed;193}194 195FunctionPass *llvm::createRISCVInsertReadWriteCSRPass() {196  return new RISCVInsertReadWriteCSR();197}198