[PowerPC] Implement Thread Local Storage Support for Local Exec

This patch is the initial support for the Local Exec Thread Local
Storage model to produce code sequence and relocations correct
to the ABI for the model when using PC relative memory operations.

Patch by: Kamau Bridgeman

Differential Revision: https://reviews.llvm.org/D83404
This commit is contained in:
Kamau Bridgeman 2020-09-11 10:33:33 -04:00 committed by Albion Fung
parent cc94720728
commit c0f199e566
11 changed files with 140 additions and 1 deletions

View File

@ -100,6 +100,7 @@
#undef R_PPC64_PCREL_OPT
#undef R_PPC64_PCREL34
#undef R_PPC64_GOT_PCREL34
#undef R_PPC64_TPREL34
#undef R_PPC64_GOT_TLSGD_PCREL34
#undef R_PPC64_GOT_TPREL_PCREL34
#undef R_PPC64_IRELATIVE
@ -200,6 +201,7 @@ ELF_RELOC(R_PPC64_REL24_NOTOC, 116)
ELF_RELOC(R_PPC64_PCREL_OPT, 123)
ELF_RELOC(R_PPC64_PCREL34, 132)
ELF_RELOC(R_PPC64_GOT_PCREL34, 133)
ELF_RELOC(R_PPC64_TPREL34, 146)
ELF_RELOC(R_PPC64_GOT_TLSGD_PCREL34, 148)
ELF_RELOC(R_PPC64_GOT_TPREL_PCREL34, 150)
ELF_RELOC(R_PPC64_IRELATIVE, 248)

View File

@ -419,7 +419,13 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
}
break;
case PPC::fixup_ppc_imm34:
report_fatal_error("Unsupported Modifier for fixup_ppc_imm34.");
switch (Modifier) {
default:
report_fatal_error("Unsupported Modifier for fixup_ppc_imm34.");
case MCSymbolRefExpr::VK_TPREL:
Type = ELF::R_PPC64_TPREL34;
break;
}
break;
case FK_Data_8:
switch (Modifier) {

View File

@ -691,6 +691,8 @@ bool PPCDAGToDAGISel::tryTLSXFormLoad(LoadSDNode *LD) {
SDValue Offset = LD->getOffset();
if (!Offset.isUndef())
return false;
if (Base.getOperand(1).getOpcode() == PPCISD::TLS_LOCAL_EXEC_MAT_ADDR)
return false;
SDLoc dl(LD);
EVT MemVT = LD->getMemoryVT();

View File

@ -1512,6 +1512,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
case PPCISD::MAT_PCREL_ADDR: return "PPCISD::MAT_PCREL_ADDR";
case PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR:
return "PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR";
case PPCISD::TLS_LOCAL_EXEC_MAT_ADDR:
return "PPCISD::TLS_LOCAL_EXEC_MAT_ADDR";
case PPCISD::LD_SPLAT: return "PPCISD::LD_SPLAT";
case PPCISD::FNMSUB: return "PPCISD::FNMSUB";
case PPCISD::STRICT_FADDRTZ:
@ -3015,6 +3017,15 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
TLSModel::Model Model = TM.getTLSModel(GV);
if (Model == TLSModel::LocalExec) {
if (Subtarget.isUsingPCRelativeCalls()) {
SDValue TLSReg = DAG.getRegister(PPC::X13, MVT::i64);
SDValue TGA = DAG.getTargetGlobalAddress(
GV, dl, PtrVT, 0, (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG));
SDValue MatAddr =
DAG.getNode(PPCISD::TLS_LOCAL_EXEC_MAT_ADDR, dl, PtrVT, TGA);
return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, MatAddr);
}
SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,
PPCII::MO_TPREL_HA);
SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,

View File

@ -441,6 +441,11 @@ namespace llvm {
/// through an add like PADDI.
TLS_DYNAMIC_MAT_PCREL_ADDR,
/// TLS_LOCAL_EXEC_MAT_ADDR = Materialize an address for TLS global address
/// when using local exec access models, and when prefixed instructions are
/// available. This is used with ADD_TLS to produce an add like PADDI.
TLS_LOCAL_EXEC_MAT_ADDR,
// Constrained conversion from floating point to int
STRICT_FCTIDZ = ISD::FIRST_TARGET_STRICTFP_OPCODE,
STRICT_FCTIWZ,

View File

@ -368,6 +368,8 @@ def PPCprobedalloca : SDNode<"PPCISD::PROBED_ALLOCA", SDTDynOp, [SDNPHasChain]>;
def PPCmatpcreladdr : SDNode<"PPCISD::MAT_PCREL_ADDR", SDTIntUnaryOp, []>;
def PPCtlsdynamatpcreladdr : SDNode<"PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR",
SDTIntUnaryOp, []>;
def PPCtlslocalexecmataddr : SDNode<"PPCISD::TLS_LOCAL_EXEC_MAT_ADDR",
SDTIntUnaryOp, []>;
//===----------------------------------------------------------------------===//
// PowerPC specific transformation functions and pattern fragments.

View File

@ -829,6 +829,10 @@ let Predicates = [PCRelativeMemops], AddedComplexity = 500 in {
// PPCtlsdynamatpcreladdr node is used for TLS dynamic models to materialize
// tls global address with paddi instruction.
def : Pat<(PPCtlsdynamatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>;
// PPCtlslocalexecmataddr node is used for TLS local exec models to
// materialize tls global address with paddi instruction.
def : Pat<(PPCaddTls i64:$in, (PPCtlslocalexecmataddr tglobaltlsaddr:$addr)),
(PADDI8 $in, $addr)>;
}
let Predicates = [PrefixInstrs] in {

View File

@ -86,6 +86,8 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
RefKind = MCSymbolRefExpr::VK_PCREL;
else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG))
RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL;
else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_TPREL_FLAG))
RefKind = MCSymbolRefExpr::VK_TPREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL;
else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG)

View File

@ -0,0 +1,74 @@
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
; RUN: -enable-ppc-pcrel-tls -mcpu=pwr10 -ppc-asm-full-reg-names \
; RUN: < %s | FileCheck %s --check-prefix=CHECK-S
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
; RUN: -enable-ppc-pcrel-tls -mcpu=pwr10 -ppc-asm-full-reg-names \
; RUN: --filetype=obj < %s | llvm-objdump --no-show-raw-insn --mcpu=pwr10 -dr - \
; RUN: | FileCheck %s --check-prefix=CHECK-O
; These test cases are to ensure that when using pc relative memory operations
; ABI correct code and relocations are produced for the Local Exec TLS Model.
@x = thread_local global i32 0, align 4
@y = thread_local global [5 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0], align 4
define i32* @LocalExecAddressLoad() {
; CHECK-S-LABEL: LocalExecAddressLoad:
; CHECK-S: # %bb.0: # %entry
; CHECK-S-NEXT: paddi r3, r13, x@TPREL, 0
; CHECK-S-NEXT: blr
; CHECK-O-LABEL: <LocalExecAddressLoad>:
; CHECK-O: 0: paddi 3, 13, 0, 0
; CHECK-O-NEXT: 0000000000000000: R_PPC64_TPREL34 x
; CHECK-O-NEXT: 8: blr
entry:
ret i32* @x
}
define i32 @LocalExecValueLoad() {
; CHECK-S-LABEL: LocalExecValueLoad:
; CHECK-S: # %bb.0: # %entry
; CHECK-S-NEXT: paddi r3, r13, x@TPREL, 0
; CHECK-S-NEXT: lwz r3, 0(r3)
; CHECK-S-NEXT: blr
; CHECK-O-LABEL: <LocalExecValueLoad>:
; CHECK-O: 20: paddi 3, 13, 0, 0
; CHECK-O-NEXT: 0000000000000020: R_PPC64_TPREL34 x
; CHECK-O-NEXT: 28: lwz 3, 0(3)
; CHECK-O-NEXT: 2c: blr
entry:
%0 = load i32, i32* @x, align 4
ret i32 %0
}
define i32 @LocalExecValueLoadOffset() {
; CHECK-S-LABEL: LocalExecValueLoadOffset:
; CHECK-S: # %bb.0: # %entry
; CHECK-S-NEXT: paddi r3, r13, y@TPREL, 0
; CHECK-S-NEXT: lwz r3, 12(r3)
; CHECK-S-NEXT: blr
; CHECK-O-LABEL: <LocalExecValueLoadOffset>:
; CHECK-O: 40: paddi 3, 13, 0, 0
; CHECK-O-NEXT: 0000000000000040: R_PPC64_TPREL34 y
; CHECK-O-NEXT: 48: lwz 3, 12(3)
; CHECK-O-NEXT: 4c: blr
entry:
%0 = load i32, i32* getelementptr inbounds ([5 x i32], [5 x i32]* @y, i64 0, i64 3), align 4
ret i32 %0
}
define i32* @LocalExecValueLoadOffsetNoLoad() {
; CHECK-S-LABEL: LocalExecValueLoadOffsetNoLoad:
; CHECK-S: # %bb.0: # %entry
; CHECK-S-NEXT: paddi r3, r13, y@TPREL, 0
; CHECK-S-NEXT: addi r3, r3, 12
; CHECK-S-NEXT: blr
; CHECK-O-LABEL: <LocalExecValueLoadOffsetNoLoad>:
; CHECK-O: 60: paddi 3, 13, 0, 0
; CHECK-O-NEXT: 0000000000000060: R_PPC64_TPREL34 y
; CHECK-O-NEXT: 68: addi 3, 3, 12
; CHECK-O-NEXT: 6c: blr
entry:
ret i32* getelementptr inbounds ([5 x i32], [5 x i32]* @y, i64 0, i64 3)
}

View File

@ -0,0 +1,15 @@
# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \
# RUN: FileCheck %s -check-prefix=MC
# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \
# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ
# This test checks that on Power PC we can correctly convert x@TPREL
# into R_PPC64_TPREL34 for local exec relocations with address loaded.
# MC-NOT: error: invalid variant
# READOBJ: 0x0 R_PPC64_TPREL34 x 0x0
LocalExec:
paddi 3, 13, x@TPREL, 0
blr

View File

@ -0,0 +1,16 @@
# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \
# RUN: FileCheck %s -check-prefix=MC
# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \
# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ
# This test checks that on Power PC we can correctly convert x@TPREL
# into R_PPC64_TPREL34 for local exec relocations with the value loaded.
# MC-NOT: error: invalid variant
# READOBJ: 0x0 R_PPC64_TPREL34 x 0x0
LocalExecLoad:
paddi 3, 13, x@TPREL, 0
lwz 3, 0(3)
blr