Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInsertReadWriteCSR.cpp
35266 views
//===-- RISCVInsertReadWriteCSR.cpp - Insert Read/Write of RISC-V CSR -----===//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// This file implements the machine function pass to insert read/write of CSR-s8// of the RISC-V instructions.9//10// Currently the pass implements:11// -Writing and saving frm before an RVV floating-point instruction with a12// static rounding mode and restores the value after.13//14//===----------------------------------------------------------------------===//1516#include "MCTargetDesc/RISCVBaseInfo.h"17#include "RISCV.h"18#include "RISCVSubtarget.h"19#include "llvm/CodeGen/MachineFunctionPass.h"20using namespace llvm;2122#define DEBUG_TYPE "riscv-insert-read-write-csr"23#define RISCV_INSERT_READ_WRITE_CSR_NAME "RISC-V Insert Read/Write CSR Pass"2425static cl::opt<bool>26DisableFRMInsertOpt("riscv-disable-frm-insert-opt", cl::init(false),27cl::Hidden,28cl::desc("Disable optimized frm insertion."));2930namespace {3132class RISCVInsertReadWriteCSR : public MachineFunctionPass {33const TargetInstrInfo *TII;3435public:36static char ID;3738RISCVInsertReadWriteCSR() : MachineFunctionPass(ID) {}3940bool runOnMachineFunction(MachineFunction &MF) override;4142void getAnalysisUsage(AnalysisUsage &AU) const override {43AU.setPreservesCFG();44MachineFunctionPass::getAnalysisUsage(AU);45}4647StringRef getPassName() const override {48return RISCV_INSERT_READ_WRITE_CSR_NAME;49}5051private:52bool emitWriteRoundingMode(MachineBasicBlock &MBB);53bool emitWriteRoundingModeOpt(MachineBasicBlock &MBB);54};5556} // end anonymous namespace5758char RISCVInsertReadWriteCSR::ID = 0;5960INITIALIZE_PASS(RISCVInsertReadWriteCSR, DEBUG_TYPE,61RISCV_INSERT_READ_WRITE_CSR_NAME, false, false)6263// TODO: Use more accurate rounding mode at the start of MBB.64bool RISCVInsertReadWriteCSR::emitWriteRoundingModeOpt(MachineBasicBlock &MBB) {65bool Changed = false;66MachineInstr *LastFRMChanger = nullptr;67unsigned CurrentRM = RISCVFPRndMode::DYN;68Register SavedFRM;6970for (MachineInstr &MI : MBB) {71if (MI.getOpcode() == RISCV::SwapFRMImm ||72MI.getOpcode() == RISCV::WriteFRMImm) {73CurrentRM = MI.getOperand(0).getImm();74SavedFRM = Register();75continue;76}7778if (MI.getOpcode() == RISCV::WriteFRM) {79CurrentRM = RISCVFPRndMode::DYN;80SavedFRM = Register();81continue;82}8384if (MI.isCall() || MI.isInlineAsm() ||85MI.readsRegister(RISCV::FRM, /*TRI=*/nullptr)) {86// Restore FRM before unknown operations.87if (SavedFRM.isValid())88BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::WriteFRM))89.addReg(SavedFRM);90CurrentRM = RISCVFPRndMode::DYN;91SavedFRM = Register();92continue;93}9495assert(!MI.modifiesRegister(RISCV::FRM, /*TRI=*/nullptr) &&96"Expected that MI could not modify FRM.");9798int FRMIdx = RISCVII::getFRMOpNum(MI.getDesc());99if (FRMIdx < 0)100continue;101unsigned InstrRM = MI.getOperand(FRMIdx).getImm();102103LastFRMChanger = &MI;104105// Make MI implicit use FRM.106MI.addOperand(MachineOperand::CreateReg(RISCV::FRM, /*IsDef*/ false,107/*IsImp*/ true));108Changed = true;109110// Skip if MI uses same rounding mode as FRM.111if (InstrRM == CurrentRM)112continue;113114if (!SavedFRM.isValid()) {115// Save current FRM value to SavedFRM.116MachineRegisterInfo *MRI = &MBB.getParent()->getRegInfo();117SavedFRM = MRI->createVirtualRegister(&RISCV::GPRRegClass);118BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::SwapFRMImm), SavedFRM)119.addImm(InstrRM);120} else {121// Don't need to save current FRM when SavedFRM having value.122BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::WriteFRMImm))123.addImm(InstrRM);124}125CurrentRM = InstrRM;126}127128// Restore FRM if needed.129if (SavedFRM.isValid()) {130assert(LastFRMChanger && "Expected valid pointer.");131MachineInstrBuilder MIB =132BuildMI(*MBB.getParent(), {}, TII->get(RISCV::WriteFRM))133.addReg(SavedFRM);134MBB.insertAfter(LastFRMChanger, MIB);135}136137return Changed;138}139140// This function also swaps frm and restores it when encountering an RVV141// floating point instruction with a static rounding mode.142bool RISCVInsertReadWriteCSR::emitWriteRoundingMode(MachineBasicBlock &MBB) {143bool Changed = false;144for (MachineInstr &MI : MBB) {145int FRMIdx = RISCVII::getFRMOpNum(MI.getDesc());146if (FRMIdx < 0)147continue;148149unsigned FRMImm = MI.getOperand(FRMIdx).getImm();150151// The value is a hint to this pass to not alter the frm value.152if (FRMImm == RISCVFPRndMode::DYN)153continue;154155Changed = true;156157// Save158MachineRegisterInfo *MRI = &MBB.getParent()->getRegInfo();159Register SavedFRM = MRI->createVirtualRegister(&RISCV::GPRRegClass);160BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::SwapFRMImm),161SavedFRM)162.addImm(FRMImm);163MI.addOperand(MachineOperand::CreateReg(RISCV::FRM, /*IsDef*/ false,164/*IsImp*/ true));165// Restore166MachineInstrBuilder MIB =167BuildMI(*MBB.getParent(), {}, TII->get(RISCV::WriteFRM))168.addReg(SavedFRM);169MBB.insertAfter(MI, MIB);170}171return Changed;172}173174bool RISCVInsertReadWriteCSR::runOnMachineFunction(MachineFunction &MF) {175// Skip if the vector extension is not enabled.176const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();177if (!ST.hasVInstructions())178return false;179180TII = ST.getInstrInfo();181182bool Changed = false;183184for (MachineBasicBlock &MBB : MF) {185if (DisableFRMInsertOpt)186Changed |= emitWriteRoundingMode(MBB);187else188Changed |= emitWriteRoundingModeOpt(MBB);189}190191return Changed;192}193194FunctionPass *llvm::createRISCVInsertReadWriteCSRPass() {195return new RISCVInsertReadWriteCSR();196}197198199