[RISCV] Implement the TargetLowering::getRegisterByName hook

Summary: The hook should work for any RISC-V register. Non-allocatable registers
do not need to be reserved, for the remaining the hook will only succeed
if you pass clang the -ffixed-xX flag. This builds upon D67185, which
currently only allows reserving GPRs.

Reviewers: asb, lenary

Reviewed By: lenary

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69130
This commit is contained in:
Luís Marques 2019-11-04 11:21:51 +00:00
parent 91167e22ec
commit 51b4b17eb7
5 changed files with 110 additions and 0 deletions

View File

@ -2894,3 +2894,22 @@ bool RISCVTargetLowering::shouldExtendTypeInLibCall(EVT Type) const {
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;
}

View File

@ -147,6 +147,13 @@ public:
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<ISD::InputArg> &Ins,

View File

@ -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"}

View File

@ -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"}

View File

@ -0,0 +1,34 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: not llc < %s -mtriple=riscv32 -mattr +reserve-x8 2>&1 \
; RUN: | FileCheck -check-prefix=NO-RESERVE-A1 %s
; RUN: not llc < %s -mtriple=riscv32 -mattr +reserve-x11 2>&1 \
; RUN: | FileCheck -check-prefix=NO-RESERVE-FP %s
; RUN: llc < %s -mtriple=riscv32 -mattr +reserve-x8 -mattr +reserve-x11 \
; RUN: | FileCheck -check-prefix=RESERVE %s
define i32 @get_reg_a1() nounwind {
; NO-RESERVE-A1: Trying to obtain non-reserved register "a1".
; RESERVE-LABEL: get_reg_a1:
; RESERVE: # %bb.0: # %entry
; RESERVE-NEXT: mv a0, a1
; RESERVE-NEXT: ret
entry:
%a1 = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %a1
}
define i32 @get_reg_fp() nounwind {
; NO-RESERVE-FP: Trying to obtain non-reserved register "fp".
; RESERVE-LABEL: get_reg_fp:
; RESERVE: # %bb.0: # %entry
; RESERVE-NEXT: mv a0, s0
; RESERVE-NEXT: ret
entry:
%fp = call i32 @llvm.read_register.i32(metadata !1)
ret i32 %fp
}
declare i32 @llvm.read_register.i32(metadata) nounwind
!0 = !{!"a1\00"}
!1 = !{!"fp\00"}