Index: llvm/lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.h +++ llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -147,6 +147,13 @@ bool shouldExtendTypeInLibCall(EVT Type) const override; + /// Returns the register with the specified architectural or ABI name. This + /// method is necessary to lower the llvm.read_register.* and + /// llvm.write_register.* intrinsics. Allocatable registers must be reserved + /// with the clang -ffixed-xX flag for access to be allowed. + Register getRegisterByName(const char *RegName, EVT VT, + const MachineFunction &MF) const override; + private: void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, const SmallVectorImpl &Ins, Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2886,3 +2886,22 @@ 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) + "\".")); + BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF); + if (!ReservedRegs.test(Reg) && !Subtarget.isRegisterReservedByUser(Reg)) + report_fatal_error(Twine("Trying to obtain non-reserved register \"" + + StringRef(RegName) + "\".")); + return Reg; +} Index: llvm/test/CodeGen/RISCV/get-register-invalid.ll =================================================================== --- /dev/null +++ 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_invalid_reg() nounwind { +entry: +; CHECK: Invalid register name "notareg". + %reg = call i32 @llvm.read_register.i32(metadata !0) + ret i32 %reg +} + +declare i32 @llvm.read_register.i32(metadata) nounwind + +!0 = !{!"notareg\00"} Index: llvm/test/CodeGen/RISCV/get-register-noreserve.ll =================================================================== --- /dev/null +++ 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"} Index: llvm/test/CodeGen/RISCV/get-register-reserve.ll =================================================================== --- /dev/null +++ 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"}