diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -264,6 +264,16 @@ return; } + // Handle copy from csr + // TODO: Handle sysreg lookup generically and remove vlenb restriction. + if (RISCV::VCSRRegClass.contains(SrcReg) && SrcReg == RISCV::VLENB && + RISCV::GPRRegClass.contains(DstReg)) { + BuildMI(MBB, MBBI, DL, get(RISCV::CSRRS), DstReg) + .addImm(RISCVSysReg::lookupSysRegByName("VLENB")->Encoding) + .addReg(RISCV::X0); + return; + } + // FPR->FPR copies and VR->VR copies. unsigned Opc; bool IsScalableVector = true; diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -102,6 +102,7 @@ markSuperRegs(Reserved, RISCV::VTYPE); markSuperRegs(Reserved, RISCV::VXSAT); markSuperRegs(Reserved, RISCV::VXRM); + markSuperRegs(Reserved, RISCV::VLENB); // vlenb (constant) // Floating point environment registers. markSuperRegs(Reserved, RISCV::FRM); diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -462,6 +462,12 @@ DwarfRegNum<[!add(4096, SysRegVLENB.Encoding)]>; } +def VCSR : RegisterClass<"RISCV", [XLenVT], 32, + (add VTYPE, VL, VLENB)> { + let RegInfos = XLenRI; +} + + foreach m = [1, 2, 4] in { foreach n = NFList.L in { def "VN" # n # "M" # m # "NoV0": RegisterTuples< diff --git a/llvm/test/CodeGen/RISCV/get-register-noreserve.ll b/llvm/test/CodeGen/RISCV/get-register-noreserve.ll --- a/llvm/test/CodeGen/RISCV/get-register-noreserve.ll +++ b/llvm/test/CodeGen/RISCV/get-register-noreserve.ll @@ -31,8 +31,20 @@ ret i32 %sp } +define i32 @get_csr_vlenb() nounwind { +; CHECK-LABEL: get_csr_vlenb: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: ret +entry: + %sp = call i32 @llvm.read_register.i32(metadata !2) + ret i32 %sp +} + + declare i32 @llvm.read_register.i32(metadata) nounwind declare void @llvm.write_register.i32(metadata, i32) nounwind !0 = !{!"sp\00"} !1 = !{!"x4\00"} +!2 = !{!"vlenb"}