[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:
Daniel Sanders 2015-01-09 17:21:30 +00:00
parent 2ce8169ed3
commit 1440bb2a26
5 changed files with 76 additions and 0 deletions

View File

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

View File

@ -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;

View File

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

View File

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

View File

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