1fe013be4SDimitry Andric //===-- RISCVInsertReadWriteCSR.cpp - Insert Read/Write of RISC-V CSR -----===//
2fe013be4SDimitry Andric //
3fe013be4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe013be4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe013be4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe013be4SDimitry Andric //
7fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
8fe013be4SDimitry Andric // This file implements the machine function pass to insert read/write of CSR-s
9fe013be4SDimitry Andric // of the RISC-V instructions.
10fe013be4SDimitry Andric //
11*c9157d92SDimitry Andric // Currently the pass implements:
12*c9157d92SDimitry Andric // -Writing and saving frm before an RVV floating-point instruction with a
13*c9157d92SDimitry Andric // static rounding mode and restores the value after.
14fe013be4SDimitry Andric //
15fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
16fe013be4SDimitry Andric
17fe013be4SDimitry Andric #include "MCTargetDesc/RISCVBaseInfo.h"
18fe013be4SDimitry Andric #include "RISCV.h"
19fe013be4SDimitry Andric #include "RISCVSubtarget.h"
20fe013be4SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
21fe013be4SDimitry Andric using namespace llvm;
22fe013be4SDimitry Andric
23fe013be4SDimitry Andric #define DEBUG_TYPE "riscv-insert-read-write-csr"
24fe013be4SDimitry Andric #define RISCV_INSERT_READ_WRITE_CSR_NAME "RISC-V Insert Read/Write CSR Pass"
25fe013be4SDimitry Andric
26fe013be4SDimitry Andric namespace {
27fe013be4SDimitry Andric
28fe013be4SDimitry Andric class RISCVInsertReadWriteCSR : public MachineFunctionPass {
29fe013be4SDimitry Andric const TargetInstrInfo *TII;
30fe013be4SDimitry Andric
31fe013be4SDimitry Andric public:
32fe013be4SDimitry Andric static char ID;
33fe013be4SDimitry Andric
RISCVInsertReadWriteCSR()34*c9157d92SDimitry Andric RISCVInsertReadWriteCSR() : MachineFunctionPass(ID) {}
35fe013be4SDimitry Andric
36fe013be4SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
37fe013be4SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const38fe013be4SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
39fe013be4SDimitry Andric AU.setPreservesCFG();
40fe013be4SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
41fe013be4SDimitry Andric }
42fe013be4SDimitry Andric
getPassName() const43fe013be4SDimitry Andric StringRef getPassName() const override {
44fe013be4SDimitry Andric return RISCV_INSERT_READ_WRITE_CSR_NAME;
45fe013be4SDimitry Andric }
46fe013be4SDimitry Andric
47fe013be4SDimitry Andric private:
48fe013be4SDimitry Andric bool emitWriteRoundingMode(MachineBasicBlock &MBB);
49fe013be4SDimitry Andric };
50fe013be4SDimitry Andric
51fe013be4SDimitry Andric } // end anonymous namespace
52fe013be4SDimitry Andric
53fe013be4SDimitry Andric char RISCVInsertReadWriteCSR::ID = 0;
54fe013be4SDimitry Andric
INITIALIZE_PASS(RISCVInsertReadWriteCSR,DEBUG_TYPE,RISCV_INSERT_READ_WRITE_CSR_NAME,false,false)55fe013be4SDimitry Andric INITIALIZE_PASS(RISCVInsertReadWriteCSR, DEBUG_TYPE,
56fe013be4SDimitry Andric RISCV_INSERT_READ_WRITE_CSR_NAME, false, false)
57fe013be4SDimitry Andric
58*c9157d92SDimitry Andric // This function also swaps frm and restores it when encountering an RVV
59*c9157d92SDimitry Andric // floating point instruction with a static rounding mode.
60fe013be4SDimitry Andric bool RISCVInsertReadWriteCSR::emitWriteRoundingMode(MachineBasicBlock &MBB) {
61fe013be4SDimitry Andric bool Changed = false;
62fe013be4SDimitry Andric for (MachineInstr &MI : MBB) {
63*c9157d92SDimitry Andric int FRMIdx = RISCVII::getFRMOpNum(MI.getDesc());
64*c9157d92SDimitry Andric if (FRMIdx < 0)
65*c9157d92SDimitry Andric continue;
66fe013be4SDimitry Andric
67*c9157d92SDimitry Andric unsigned FRMImm = MI.getOperand(FRMIdx).getImm();
68fe013be4SDimitry Andric
69fe013be4SDimitry Andric // The value is a hint to this pass to not alter the frm value.
70fe013be4SDimitry Andric if (FRMImm == RISCVFPRndMode::DYN)
71fe013be4SDimitry Andric continue;
72fe013be4SDimitry Andric
73fe013be4SDimitry Andric Changed = true;
74fe013be4SDimitry Andric
75fe013be4SDimitry Andric // Save
76fe013be4SDimitry Andric MachineRegisterInfo *MRI = &MBB.getParent()->getRegInfo();
77fe013be4SDimitry Andric Register SavedFRM = MRI->createVirtualRegister(&RISCV::GPRRegClass);
78fe013be4SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(RISCV::SwapFRMImm),
79fe013be4SDimitry Andric SavedFRM)
80fe013be4SDimitry Andric .addImm(FRMImm);
81fe013be4SDimitry Andric MI.addOperand(MachineOperand::CreateReg(RISCV::FRM, /*IsDef*/ false,
82fe013be4SDimitry Andric /*IsImp*/ true));
83fe013be4SDimitry Andric // Restore
84fe013be4SDimitry Andric MachineInstrBuilder MIB =
85fe013be4SDimitry Andric BuildMI(*MBB.getParent(), {}, TII->get(RISCV::WriteFRM))
86fe013be4SDimitry Andric .addReg(SavedFRM);
87fe013be4SDimitry Andric MBB.insertAfter(MI, MIB);
88fe013be4SDimitry Andric }
89fe013be4SDimitry Andric return Changed;
90fe013be4SDimitry Andric }
91fe013be4SDimitry Andric
runOnMachineFunction(MachineFunction & MF)92fe013be4SDimitry Andric bool RISCVInsertReadWriteCSR::runOnMachineFunction(MachineFunction &MF) {
93fe013be4SDimitry Andric // Skip if the vector extension is not enabled.
94fe013be4SDimitry Andric const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
95fe013be4SDimitry Andric if (!ST.hasVInstructions())
96fe013be4SDimitry Andric return false;
97fe013be4SDimitry Andric
98fe013be4SDimitry Andric TII = ST.getInstrInfo();
99fe013be4SDimitry Andric
100fe013be4SDimitry Andric bool Changed = false;
101fe013be4SDimitry Andric
102fe013be4SDimitry Andric for (MachineBasicBlock &MBB : MF)
103fe013be4SDimitry Andric Changed |= emitWriteRoundingMode(MBB);
104fe013be4SDimitry Andric
105fe013be4SDimitry Andric return Changed;
106fe013be4SDimitry Andric }
107fe013be4SDimitry Andric
createRISCVInsertReadWriteCSRPass()108fe013be4SDimitry Andric FunctionPass *llvm::createRISCVInsertReadWriteCSRPass() {
109fe013be4SDimitry Andric return new RISCVInsertReadWriteCSR();
110fe013be4SDimitry Andric }
111