forked from OSchip/llvm-project
[mips] Add support for accessing $gp as a named register.
Summary: Mips Linux uses $gp to hold a pointer to thread info structure and accesses it with a named register. This makes this work for LLVM. The N32 ABI doesn't quite work yet since the frontend generates incorrect IR for this case. It neglects to truncate the 64-bit GPR to a 32-bit value before converting to a pointer. Given correct IR (as in the testcase in this patch), it works correctly. Reviewers: sstankovic, vmedic, atanasyan Reviewed By: atanasyan Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D6893 llvm-svn: 225529
This commit is contained in:
parent
2ce8169ed3
commit
1440bb2a26
|
@ -3839,3 +3839,25 @@ MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB,
|
|||
|
||||
return BB;
|
||||
}
|
||||
|
||||
// FIXME? Maybe this could be a TableGen attribute on some registers and
|
||||
// this table could be generated automatically from RegInfo.
|
||||
unsigned MipsTargetLowering::getRegisterByName(const char* RegName,
|
||||
EVT VT) const {
|
||||
// Named registers is expected to be fairly rare. For now, just support $28
|
||||
// since the linux kernel uses it.
|
||||
if (Subtarget.isGP64bit()) {
|
||||
unsigned Reg = StringSwitch<unsigned>(RegName)
|
||||
.Case("$28", Mips::GP_64)
|
||||
.Default(0);
|
||||
if (Reg)
|
||||
return Reg;
|
||||
} else {
|
||||
unsigned Reg = StringSwitch<unsigned>(RegName)
|
||||
.Case("$28", Mips::GP)
|
||||
.Default(0);
|
||||
if (Reg)
|
||||
return Reg;
|
||||
}
|
||||
report_fatal_error("Invalid register name global variable");
|
||||
}
|
||||
|
|
|
@ -262,6 +262,8 @@ namespace llvm {
|
|||
|
||||
void HandleByVal(CCState *, unsigned &, unsigned) const override;
|
||||
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT) const override;
|
||||
|
||||
protected:
|
||||
SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
; RUN: llc -march=mips64 -relocation-model=static -mattr=+noabicalls,-n64,+n32 < %s | FileCheck %s
|
||||
|
||||
define i32* @get_gp() {
|
||||
entry:
|
||||
%0 = call i64 @llvm.read_register.i64(metadata !0)
|
||||
%1 = trunc i64 %0 to i32
|
||||
%2 = inttoptr i32 %1 to i32*
|
||||
ret i32* %2
|
||||
}
|
||||
|
||||
; CHECK-LABEL: get_gp:
|
||||
; CHECK: sll $2, $gp, 0
|
||||
|
||||
declare i64 @llvm.read_register.i64(metadata)
|
||||
|
||||
!llvm.named.register.$28 = !{!0}
|
||||
|
||||
!0 = !{!"$28"}
|
|
@ -0,0 +1,17 @@
|
|||
; RUN: llc -march=mips64 -relocation-model=static -mattr=+noabicalls < %s | FileCheck %s
|
||||
|
||||
define i32* @get_gp() {
|
||||
entry:
|
||||
%0 = call i64 @llvm.read_register.i64(metadata !0)
|
||||
%1 = inttoptr i64 %0 to i32*
|
||||
ret i32* %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: get_gp:
|
||||
; CHECK: move $2, $gp
|
||||
|
||||
declare i64 @llvm.read_register.i64(metadata)
|
||||
|
||||
!llvm.named.register.$28 = !{!0}
|
||||
|
||||
!0 = !{!"$28"}
|
|
@ -0,0 +1,17 @@
|
|||
; RUN: llc -march=mips -relocation-model=static -mattr=+noabicalls < %s | FileCheck %s
|
||||
|
||||
define i32* @get_gp() {
|
||||
entry:
|
||||
%0 = call i32 @llvm.read_register.i32(metadata !0)
|
||||
%1 = inttoptr i32 %0 to i32*
|
||||
ret i32* %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: get_gp:
|
||||
; CHECK: move $2, $gp
|
||||
|
||||
declare i32 @llvm.read_register.i32(metadata)
|
||||
|
||||
!llvm.named.register.$28 = !{!0}
|
||||
|
||||
!0 = !{!"$28"}
|
Loading…
Reference in New Issue