diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -134,6 +134,9 @@ return ISD::SIGN_EXTEND; } + Register getRegisterByName(const char *RegName, LLT VT, + const MachineFunction &MF) const override; + private: /// Target-specific function used to lower LoongArch calling conventions. typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI, diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -2374,3 +2374,24 @@ } TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); } + +#define GET_REGISTER_MATCHER +#include "LoongArchGenAsmMatcher.inc" + +Register +LoongArchTargetLowering::getRegisterByName(const char *RegName, LLT VT, + const MachineFunction &MF) const { + std::pair Name = StringRef(RegName).split('$'); + std::string NewRegName = Name.second.str(); + Register Reg = MatchRegisterAltName(NewRegName); + if (Reg == LoongArch::NoRegister) + Reg = MatchRegisterName(NewRegName); + if (Reg == LoongArch::NoRegister) + report_fatal_error( + Twine("Invalid register name \"" + StringRef(RegName) + "\".")); + BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF); + if (!ReservedRegs.test(Reg)) + report_fatal_error(Twine("Trying to obtain non-reserved register \"" + + StringRef(RegName) + "\".")); + return Reg; +} diff --git a/llvm/test/CodeGen/LoongArch/get-noreg.ll b/llvm/test/CodeGen/LoongArch/get-noreg.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/get-noreg.ll @@ -0,0 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: not --crash llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s + +define i64 @get_noreg() nounwind { +; CHECK: Invalid register name "notreg". +entry: + %noreg = call i64 @llvm.read_register.i64(metadata !0) + ret i64 %noreg +} + +declare i64 @llvm.read_register.i64(metadata) nounwind + +!0 = !{!"notreg\00"} diff --git a/llvm/test/CodeGen/LoongArch/get-reg-error.ll b/llvm/test/CodeGen/LoongArch/get-reg-error.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/get-reg-error.ll @@ -0,0 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: not --crash llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s + +define i64 @get_a1() nounwind { +; CHECK: Trying to obtain non-reserved register "$a1". +entry: + %a1 = call i64 @llvm.read_register.i64(metadata !0) + ret i64 %a1 +} + +declare i64 @llvm.read_register.i64(metadata) nounwind + +!0 = !{!"$a1\00"} diff --git a/llvm/test/CodeGen/LoongArch/get-reg-reserve.ll b/llvm/test/CodeGen/LoongArch/get-reg-reserve.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/get-reg-reserve.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s --mtriple=loongarch64 | FileCheck %s + +define i64 @get_stack() nounwind { +; CHECK-LABEL: get_stack: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: move $a0, $sp +; CHECK-NEXT: ret +entry: + %sp = call i64 @llvm.read_register.i64(metadata !0) + ret i64 %sp +} + +define void @set_stack(i64 %val) nounwind { +; CHECK-LABEL: set_stack: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: move $sp, $a0 +; CHECK-NEXT: ret +entry: + call void @llvm.write_register.i64(metadata !0, i64 %val) + ret void +} + +declare i64 @llvm.read_register.i64(metadata) nounwind +declare void @llvm.write_register.i64(metadata, i64) nounwind + +!0 = !{!"$sp\00"}