diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -114,6 +114,15 @@ // float to single-width float, rounding towards odd). Takes a double-width // float vector and produces a single-width float vector. VFNCVT_ROD, + // Reads value of CSR. + // The first operand is a chain pointer. The second specifies address of the + // required CSR. Two results are produced, the read value and chain pointer. + READ_CSR, + // Write value to CSR. + // The first operand is a chain pointer, the second specifies address of the + // required CSR and the third is the value to write. The result is chain + // pointer. + WRITE_CSR }; } // namespace RISCVISD 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 @@ -4151,6 +4151,8 @@ NODE_NAME_CASE(VSLIDEDOWN) NODE_NAME_CASE(VID) NODE_NAME_CASE(VFNCVT_ROD) + NODE_NAME_CASE(READ_CSR) + NODE_NAME_CASE(WRITE_CSR) } // clang-format on return nullptr; 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 @@ -25,6 +25,8 @@ def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, SDTCisSameAs<0, 4>, SDTCisSameAs<4, 5>]>; +def SDT_ReadCSR : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>]>; +def SDT_WriteCSR : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisInt<1>]>; def SDT_RISCVReadCycleWide : SDTypeProfile<2, 0, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; @@ -53,6 +55,10 @@ def riscv_sllw : SDNode<"RISCVISD::SLLW", SDTIntShiftOp>; def riscv_sraw : SDNode<"RISCVISD::SRAW", SDTIntShiftOp>; def riscv_srlw : SDNode<"RISCVISD::SRLW", SDTIntShiftOp>; +def riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_ReadCSR, + [SDNPHasChain]>; +def riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_WriteCSR, + [SDNPHasChain]>; def riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE", SDT_RISCVReadCycleWide, @@ -397,6 +403,15 @@ : RVInstI, Sched<[WriteCSR, ReadCSR]>; +// Write-only variant of CSR_ir. +let hasNoSchedulingInfo = 1, + hasSideEffects = 1, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1 in +class CSRW_ir funct3, string opcodestr> + : RVInstI, Sched<[WriteCSR]> { + let rd = 0; +} + let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class CSR_ii funct3, string opcodestr> @@ -404,6 +419,16 @@ (ins csr_sysreg:$imm12, uimm5:$rs1), opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; +// Write-only variant of CSR_ii. +let hasNoSchedulingInfo = 1, + hasSideEffects = 1, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1 in +class CSRW_ii funct3, string opcodestr> + : RVInstI, Sched<[WriteCSR]> { + let rd = 0; +} + let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ShiftW_ri funct3, string opcodestr> : RVInstIShiftW; def CSRRCI : CSR_ii<0b111, "csrrci">; +// Write-only variants of CSRRW*. +def CSRW : CSRW_ir<0b001, "csrw">; +def CSRWI : CSRW_ii<0b101, "csrwi">; + /// RV64I instructions let Predicates = [IsRV64] in { @@ -1237,6 +1266,13 @@ defm : StPat; } // Predicates = [IsRV64] +def : Pat<(riscv_read_csr simm12:$csr), + (CSRRS simm12:$csr, X0)>; +def : Pat<(riscv_write_csr simm12:$csr, GPR:$rs1), + (CSRW simm12:$csr, GPR:$rs1)>; +def : Pat<(riscv_write_csr simm12:$csr, uimm5:$imm), + (CSRWI simm12:$csr, uimm5:$imm)>; + /// readcyclecounter // On RV64, we can directly read the 64-bit "cycle" CSR. let Predicates = [IsRV64] in