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 @@ -51,7 +51,16 @@ FMV_X_ANYEXTW_RV64, // READ_CYCLE_WIDE - A read of the 64-bit cycle CSR on a 32-bit target // (returns (Lo, Hi)). It takes a chain operand. - READ_CYCLE_WIDE + READ_CYCLE_WIDE, + // 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 }; } 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 @@ -2641,6 +2641,10 @@ return "RISCVISD::FMV_X_ANYEXTW_RV64"; case RISCVISD::READ_CYCLE_WIDE: return "RISCVISD::READ_CYCLE_WIDE"; + case RISCVISD::READ_CSR: + return "RISCVISD::READ_CSR"; + case RISCVISD::WRITE_CSR: + return "RISCVISD::WRITE_CSR"; } 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>]>; // Target-independent nodes, but with target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, @@ -52,6 +54,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]>; //===----------------------------------------------------------------------===// // Operand and SDNode transformation definitions. @@ -385,6 +391,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> @@ -392,6 +407,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 the above. +def CSRW : CSRW_ir<0b001, "csrw">; +def CSRS : CSRW_ir<0b010, "csrs">; +def CSRC : CSRW_ir<0b011, "csrc">; + +def CSRWI : CSRW_ii<0b101, "csrwi">; +def CSRSI : CSRW_ii<0b110, "csrsi">; +def CSRCI : CSRW_ii<0b111, "csrci">; + /// RV64I instructions let Predicates = [IsRV64] in { @@ -1163,6 +1197,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