Commit c0ab938b authored by Daniel Sanders's avatar Daniel Sanders
Browse files

Merging r225529:

------------------------------------------------------------------------
r225529 | dsanders | 2015-01-09 17:21:30 +0000 (Fri, 09 Jan 2015) | 18 lines

[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: 231466
parent 81155380
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -3721,3 +3721,25 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size,

  State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs);
}

// 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");
}
+2 −0
Original line number Diff line number Diff line
@@ -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;

+18 −0
Original line number Diff line number Diff line
; 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 = metadata !{metadata !"$28"}
+17 −0
Original line number Diff line number Diff line
; 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 = metadata !{metadata !"$28"}
+17 −0
Original line number Diff line number Diff line
; 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 = metadata !{metadata !"$28"}