diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td --- a/llvm/include/llvm/IR/IntrinsicsRISCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -141,6 +141,12 @@ ImmArg>, ImmArg>]>; + def int_riscv_vsetvxrm : Intrinsic<[], + [llvm_anyint_ty], + [IntrNoMem, IntrHasSideEffects]>; + def int_riscv_vgetvxrm : Intrinsic<[llvm_anyint_ty], + [], + [IntrNoMem, IntrHasSideEffects]>; // For unit stride load // Input: (pointer, vl) class RISCVUSLoad diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -4017,6 +4017,14 @@ switch (IntNo) { default: break; + case Intrinsic::riscv_vgetvxrm: { + SDLoc DL(Op); + SDValue SysRegNo = + DAG.getTargetConstant(RISCVSysReg::lookupSysRegByName("VXRM")->Encoding, + DL, Subtarget.getXLenVT()); + return DAG.getNode(RISCVISD::READ_CSR, DL, Op->getVTList(), + Op.getOperand(0), SysRegNo); + } case Intrinsic::riscv_masked_strided_load: { SDLoc DL(Op); MVT XLenVT = Subtarget.getXLenVT(); @@ -4076,6 +4084,14 @@ switch (IntNo) { default: break; + case Intrinsic::riscv_vsetvxrm: { + SDLoc DL(Op); + SDValue SysRegNo = + DAG.getTargetConstant(RISCVSysReg::lookupSysRegByName("VXRM")->Encoding, + DL, Subtarget.getXLenVT()); + return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Op.getOperand(0), + SysRegNo, Op.getOperand(2)); + } case Intrinsic::riscv_masked_strided_store: { SDLoc DL(Op); MVT XLenVT = Subtarget.getXLenVT(); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1335,6 +1335,12 @@ def WriteFRM : WriteSysReg; def WriteFRMImm : WriteSysRegImm; +let hasSideEffects = true in { +def ReadVXRM : ReadSysReg; +def WriteVXRM: WriteSysReg; +def WriteVXRMImm: WriteSysRegImm; +} + /// Other pseudo-instructions // Pessimistically assume the stack pointer will be clobbered diff --git a/llvm/lib/Target/RISCV/RISCVSystemOperands.td b/llvm/lib/Target/RISCV/RISCVSystemOperands.td --- a/llvm/lib/Target/RISCV/RISCVSystemOperands.td +++ b/llvm/lib/Target/RISCV/RISCVSystemOperands.td @@ -384,7 +384,7 @@ //===----------------------------------------------- def : SysReg<"vstart", 0x008>; def : SysReg<"vxsat", 0x009>; -def : SysReg<"vxrm", 0x00A>; +def SysRegVXRM : SysReg<"vxrm", 0x00A>; def : SysReg<"vcsr", 0x00F>; def : SysReg<"vl", 0xC20>; def : SysReg<"vtype", 0xC21>; diff --git a/llvm/test/CodeGen/RISCV/rvv/vxrm-access.ll b/llvm/test/CodeGen/RISCV/rvv/vxrm-access.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/vxrm-access.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+experimental-v \ +; RUN: -verify-machineinstrs | FileCheck --check-prefix=CHECK %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+experimental-v \ +; RUN: -verify-machineinstrs | FileCheck --check-prefix=CHECK %s + +declare iXLen @llvm.riscv.vgetvxrm(); +declare void @llvm.riscv.vsetvxrm.iXLen(iXLen %roundmode); + +define iXLen @readvxrm() nounwind +; CHECK-LABEL: readvxrm: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vxrm +; CHECK-NEXT: ret +{ + %ret = call iXLen @llvm.riscv.vgetvxrm() + ret iXLen %ret +} + +define void @writevxrm(iXLen %roundmode) nounwind +; CHECK-LABEL: writevxrm: +; CHECK: # %bb.0: +; CHECK-NEXT: csrw vxrm, a0 +; CHECK-NEXT: ret +{ + call void @llvm.riscv.vsetvxrm.iXLen(iXLen %roundmode) + ret void +} + +define void @writevxrmimm() nounwind +; CHECK-LABEL: writevxrmimm: +; CHECK: # %bb.0: +; CHECK-NEXT: csrwi vxrm, 3 +; CHECK-NEXT: ret +{ + call void @llvm.riscv.vsetvxrm.iXLen(iXLen 3) + ret void +}