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 @@ -147,6 +147,9 @@ bool shouldExtendTypeInLibCall(EVT Type) const override; + Register getRegisterByName(const char *RegName, EVT VT, + const MachineFunction &MF) const override; + private: void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, const SmallVectorImpl &Ins, 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 @@ -2886,3 +2886,25 @@ return true; } + +#define GET_REGISTER_MATCHER +#include "RISCVGenAsmMatcher.inc" + +Register +RISCVTargetLowering::getRegisterByName(const char *RegName, EVT VT, + const MachineFunction &MF) const { + Register Reg = MatchRegisterAltName(RegName); + if (Reg == RISCV::NoRegister) + Reg = MatchRegisterName(RegName); + if (Reg == RISCV::NoRegister) + report_fatal_error( + Twine("Invalid register name \"" + StringRef(RegName) + "\".")); + if (!(Reg >= RISCV::X0 && Reg <= RISCV::X4)) { + if (!Subtarget.isRegisterReservedByUser(Reg)) { + report_fatal_error(Twine("Trying to obtain non-reserved register \"" + + StringRef(RegName) + "\".")); + return RISCV::NoRegister; + } + } + return Reg; +} diff --git a/llvm/test/CodeGen/RISCV/get-register-invalid.ll b/llvm/test/CodeGen/RISCV/get-register-invalid.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/get-register-invalid.ll @@ -0,0 +1,12 @@ +; RUN: not llc < %s -mtriple=riscv32 2>&1 | FileCheck %s + +define i32 @get_reg() nounwind { +entry: +; CHECK: Invalid register name "notareg". + %sp = call i32 @llvm.read_register.i32(metadata !0) + ret i32 %sp +} + +declare i32 @llvm.read_register.i32(metadata) nounwind + +!0 = !{!"notareg\00"} diff --git a/llvm/test/CodeGen/RISCV/get-register-noreserve.ll b/llvm/test/CodeGen/RISCV/get-register-noreserve.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/get-register-noreserve.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=riscv32 | FileCheck %s + +define i32 @get_stack() nounwind { +; CHECK-LABEL: get_stack: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mv a0, sp +; CHECK-NEXT: ret +entry: + %sp = call i32 @llvm.read_register.i32(metadata !0) + ret i32 %sp +} + +define void @set_stack(i32 %val) nounwind { +; CHECK-LABEL: set_stack: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mv sp, a0 +; CHECK-NEXT: ret +entry: + call void @llvm.write_register.i32(metadata !0, i32 %val) + ret void +} + +define i32 @get_tp_arch_name() nounwind { +; CHECK-LABEL: get_tp_arch_name: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mv a0, tp +; CHECK-NEXT: ret +entry: + %sp = call i32 @llvm.read_register.i32(metadata !1) + 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"} diff --git a/llvm/test/CodeGen/RISCV/get-register-reserve.ll b/llvm/test/CodeGen/RISCV/get-register-reserve.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/get-register-reserve.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: not llc < %s -mtriple=riscv32 2>&1 | FileCheck -check-prefix=NO-RESERVE %s +; RUN: llc < %s -mtriple=riscv32 -mattr +reserve-x11 | FileCheck -check-prefix=RESERVE %s + +define i32 @get_reg() nounwind { +; RESERVE-LABEL: get_reg: +; RESERVE: # %bb.0: # %entry +; RESERVE-NEXT: mv a0, a1 +; RESERVE-NEXT: ret +; NO-RESERVE: Trying to obtain non-reserved register "a1". +entry: + %sp = call i32 @llvm.read_register.i32(metadata !0) + ret i32 %sp +} + +declare i32 @llvm.read_register.i32(metadata) nounwind + +!0 = !{!"a1\00"}