1 //===-- RISCVInsertReadWriteCSR.cpp - Insert Read/Write of RISC-V CSR -----===//
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-exception
7 //===----------------------------------------------------------------------===//
8 // This file implements the machine function pass to insert read/write of CSR-s
9 // of the RISC-V instructions.
11 // Currently the pass implements:
12 // -Writing and saving frm before an RVV floating-point instruction with a
13 // static rounding mode and restores the value after.
15 //===----------------------------------------------------------------------===//
17 #include "MCTargetDesc/RISCVBaseInfo.h"
19 #include "RISCVSubtarget.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
23 #define DEBUG_TYPE "riscv-insert-read-write-csr"
24 #define RISCV_INSERT_READ_WRITE_CSR_NAME "RISC-V Insert Read/Write CSR Pass"
28 class RISCVInsertReadWriteCSR
: public MachineFunctionPass
{
29 const TargetInstrInfo
*TII
;
34 RISCVInsertReadWriteCSR() : MachineFunctionPass(ID
) {}
36 bool runOnMachineFunction(MachineFunction
&MF
) override
;
38 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
40 MachineFunctionPass::getAnalysisUsage(AU
);
43 StringRef
getPassName() const override
{
44 return RISCV_INSERT_READ_WRITE_CSR_NAME
;
48 bool emitWriteRoundingMode(MachineBasicBlock
&MBB
);
51 } // end anonymous namespace
53 char RISCVInsertReadWriteCSR::ID
= 0;
55 INITIALIZE_PASS(RISCVInsertReadWriteCSR
, DEBUG_TYPE
,
56 RISCV_INSERT_READ_WRITE_CSR_NAME
, false, false)
58 // This function also swaps frm and restores it when encountering an RVV
59 // floating point instruction with a static rounding mode.
60 bool RISCVInsertReadWriteCSR::emitWriteRoundingMode(MachineBasicBlock
&MBB
) {
62 for (MachineInstr
&MI
: MBB
) {
63 int FRMIdx
= RISCVII::getFRMOpNum(MI
.getDesc());
67 unsigned FRMImm
= MI
.getOperand(FRMIdx
).getImm();
69 // The value is a hint to this pass to not alter the frm value.
70 if (FRMImm
== RISCVFPRndMode::DYN
)
76 MachineRegisterInfo
*MRI
= &MBB
.getParent()->getRegInfo();
77 Register SavedFRM
= MRI
->createVirtualRegister(&RISCV::GPRRegClass
);
78 BuildMI(MBB
, MI
, MI
.getDebugLoc(), TII
->get(RISCV::SwapFRMImm
),
81 MI
.addOperand(MachineOperand::CreateReg(RISCV::FRM
, /*IsDef*/ false,
84 MachineInstrBuilder MIB
=
85 BuildMI(*MBB
.getParent(), {}, TII
->get(RISCV::WriteFRM
))
87 MBB
.insertAfter(MI
, MIB
);
92 bool RISCVInsertReadWriteCSR::runOnMachineFunction(MachineFunction
&MF
) {
93 // Skip if the vector extension is not enabled.
94 const RISCVSubtarget
&ST
= MF
.getSubtarget
<RISCVSubtarget
>();
95 if (!ST
.hasVInstructions())
98 TII
= ST
.getInstrInfo();
100 bool Changed
= false;
102 for (MachineBasicBlock
&MBB
: MF
)
103 Changed
|= emitWriteRoundingMode(MBB
);
108 FunctionPass
*llvm::createRISCVInsertReadWriteCSRPass() {
109 return new RISCVInsertReadWriteCSR();