Skip to content

Commit

Permalink
aix-small-local-dynamic-tls and aix-shared-lib-tls-model-opt interwor…
Browse files Browse the repository at this point in the history
…king example
  • Loading branch information
orcguru committed Mar 28, 2024
1 parent 162316a commit a173d24
Show file tree
Hide file tree
Showing 3 changed files with 271 additions and 5 deletions.
4 changes: 2 additions & 2 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1683,9 +1683,9 @@ const MCExpr *PPCAsmPrinter::getAdjustedLocalExecExpr(const MachineOperand &MO,
const GlobalValue *GValue = MO.getGlobal();
// TODO: handle aix-small-local-dynamic-tls none-zero offset case.
TLSModel::Model Model = TM.getTLSModel(GValue);
if (Model == TLSModel::LocalDynamic) {
const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
if (Model == TLSModel::LocalDynamic || FuncInfo->isAIXFuncUseTLSLD())
return nullptr;
}
assert(Model == TLSModel::LocalExec &&
"Only local-exec accesses are handled!");

Expand Down
8 changes: 5 additions & 3 deletions llvm/lib/Target/PowerPC/PPCMCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "MCTargetDesc/PPCMCExpr.h"
#include "PPC.h"
#include "PPCMachineFunctionInfo.h"
#include "PPCSubtarget.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
Expand Down Expand Up @@ -81,6 +82,8 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
}

const TargetMachine &TM = Printer.TM;
const MachineInstr *MI = MO.getParent();
const MachineFunction *MF = MI->getMF();

if (MO.getTargetFlags() == PPCII::MO_PLT)
RefKind = MCSymbolRefExpr::VK_PLT;
Expand All @@ -100,18 +103,17 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
MO.getTargetFlags() == PPCII::MO_TLSLD_FLAG) {
assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
// For the local-[exec|dynamic] TLS model, we may generate the offset from
// the TLS base as an immediate operand (instead of using a TOC entry). Set
// the relocation type in case the result is used for purposes other than a
// TOC reference. In TOC reference cases, this result is discarded.
if (Model == TLSModel::LocalExec)
RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE;
else if (Model == TLSModel::LocalDynamic)
else if (Model == TLSModel::LocalDynamic || FuncInfo->isAIXFuncUseTLSLD())
RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLD;
}

const MachineInstr *MI = MO.getParent();
const MachineFunction *MF = MI->getMF();
const Module *M = MF->getFunction().getParent();
const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
; RUN: -mattr=+aix-shared-lib-tls-model-opt -mattr=+aix-small-local-dynamic-tls --code-model=small < %s | FileCheck %s --check-prefixes=SMALL64
; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mattr=-altivec -mtriple powerpc64-ibm-aix-xcoff \
; RUN: -mattr=+aix-shared-lib-tls-model-opt -mattr=+aix-small-local-dynamic-tls --code-model=large < %s | FileCheck %s --check-prefixes=LARGE64

@VarTLSIE1 = internal thread_local(initialexec) global i32 42, align 4
@VarTLSIE2 = internal thread_local(initialexec) global i32 0, align 4
@VarTLSLD1 = internal thread_local(localdynamic) global i32 42, align 4
@VarTLSLD2 = internal thread_local(localdynamic) global i32 0, align 4

declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)

; Tune function level TLS model settings:
; Use initial-exec when we have a function accessing only one TLS variable.
; Use local-dynamic when we have a function accessing a handful or more different TLS variables.

define i32 @Single_IE_USE_IE(i32 %P, i32 %Q) {
; SMALL64-LABEL: Single_IE_USE_IE:
; SMALL64: # %bb.0: # %entry
; SMALL64-NEXT: and 4, 3, 4
; SMALL64-NEXT: ld 3, L..C0(2) # target-flags(ppc-tprel) @VarTLSIE1
; SMALL64-NEXT: cmpwi 4, -1
; SMALL64-NEXT: lwzx 3, 13, 3
; SMALL64-NEXT: blr
;
; LARGE64-LABEL: Single_IE_USE_IE:
; LARGE64: # %bb.0: # %entry
; LARGE64-NEXT: and 4, 3, 4
; LARGE64-NEXT: addis 3, L..C0@u(2)
; LARGE64-NEXT: ld 3, L..C0@l(3)
; LARGE64-NEXT: cmpwi 4, -1
; LARGE64-NEXT: lwzx 3, 13, 3
; LARGE64-NEXT: blr
entry:
%a = icmp slt i32 %P, 0
%b = icmp slt i32 %Q, 0
%c = and i1 %a, %b
%tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
%load1 = load i32, ptr %tls1, align 4
br i1 %c, label %bb1, label %return

bb1:
%tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
%load2 = load i32, ptr %tls2, align 4
ret i32 %load2

return:
ret i32 %load1
}

define i32 @Single_LD_USE_IE(i32 %P, i32 %Q) {
; SMALL64-LABEL: Single_LD_USE_IE:
; SMALL64: # %bb.0: # %entry
; SMALL64-NEXT: and 4, 3, 4
; SMALL64-NEXT: ld 3, L..C1(2) # target-flags(ppc-tprel) @VarTLSLD1
; SMALL64-NEXT: cmpwi 4, -1
; SMALL64-NEXT: lwzx 3, 13, 3
; SMALL64-NEXT: blr
;
; LARGE64-LABEL: Single_LD_USE_IE:
; LARGE64: # %bb.0: # %entry
; LARGE64-NEXT: and 4, 3, 4
; LARGE64-NEXT: addis 3, L..C1@u(2)
; LARGE64-NEXT: ld 3, L..C1@l(3)
; LARGE64-NEXT: cmpwi 4, -1
; LARGE64-NEXT: lwzx 3, 13, 3
; LARGE64-NEXT: blr
entry:
%a = icmp slt i32 %P, 0
%b = icmp slt i32 %Q, 0
%c = and i1 %a, %b
%tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
%load1 = load i32, ptr %tls1, align 4
br i1 %c, label %bb1, label %return

bb1:
%tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
%load2 = load i32, ptr %tls2, align 4
ret i32 %load2

return:
ret i32 %load1
}

define i32 @Multiple_IE_USE_LD(i32 %P, i32 %Q) {
; SMALL64-LABEL: Multiple_IE_USE_LD:
; SMALL64: # %bb.0: # %entry
; SMALL64-NEXT: mflr 0
; SMALL64-NEXT: stdu 1, -48(1)
; SMALL64-NEXT: and 6, 3, 4
; SMALL64-NEXT: ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
; SMALL64-NEXT: std 0, 64(1)
; SMALL64-NEXT: bla .__tls_get_mod[PR]
; SMALL64-NEXT: cmpwi 6, -1
; SMALL64-NEXT: bgt 0, L..BB2_2
; SMALL64-NEXT: # %bb.1: # %bb1
; SMALL64-NEXT: lwz 3, VarTLSIE2[UL]@ld(3)
; SMALL64-NEXT: b L..BB2_3
; SMALL64-NEXT: L..BB2_2: # %return
; SMALL64-NEXT: lwz 3, VarTLSIE1[TL]@ld(3)
; SMALL64-NEXT: L..BB2_3: # %bb1
; SMALL64-NEXT: addi 1, 1, 48
; SMALL64-NEXT: ld 0, 16(1)
; SMALL64-NEXT: mtlr 0
; SMALL64-NEXT: blr
;
; LARGE64-LABEL: Multiple_IE_USE_LD:
; LARGE64: # %bb.0: # %entry
; LARGE64-NEXT: mflr 0
; LARGE64-NEXT: stdu 1, -48(1)
; LARGE64-NEXT: and 6, 3, 4
; LARGE64-NEXT: addis 3, L..C2@u(2)
; LARGE64-NEXT: std 0, 64(1)
; LARGE64-NEXT: ld 3, L..C2@l(3)
; LARGE64-NEXT: bla .__tls_get_mod[PR]
; LARGE64-NEXT: cmpwi 6, -1
; LARGE64-NEXT: bgt 0, L..BB2_2
; LARGE64-NEXT: # %bb.1: # %bb1
; LARGE64-NEXT: lwz 3, VarTLSIE2[UL]@ld(3)
; LARGE64-NEXT: b L..BB2_3
; LARGE64-NEXT: L..BB2_2: # %return
; LARGE64-NEXT: lwz 3, VarTLSIE1[TL]@ld(3)
; LARGE64-NEXT: L..BB2_3: # %bb1
; LARGE64-NEXT: addi 1, 1, 48
; LARGE64-NEXT: ld 0, 16(1)
; LARGE64-NEXT: mtlr 0
; LARGE64-NEXT: blr
entry:
%a = icmp slt i32 %P, 0
%b = icmp slt i32 %Q, 0
%c = and i1 %a, %b
%tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
%load1 = load i32, ptr %tls1, align 4
br i1 %c, label %bb1, label %return

bb1:
%tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE2)
%load2 = load i32, ptr %tls2, align 4
ret i32 %load2

return:
ret i32 %load1
}

define i32 @Multiple_LD_USE_LD(i32 %P, i32 %Q) {
; SMALL64-LABEL: Multiple_LD_USE_LD:
; SMALL64: # %bb.0: # %entry
; SMALL64-NEXT: mflr 0
; SMALL64-NEXT: stdu 1, -48(1)
; SMALL64-NEXT: and 6, 3, 4
; SMALL64-NEXT: ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
; SMALL64-NEXT: std 0, 64(1)
; SMALL64-NEXT: bla .__tls_get_mod[PR]
; SMALL64-NEXT: cmpwi 6, -1
; SMALL64-NEXT: bgt 0, L..BB3_2
; SMALL64-NEXT: # %bb.1: # %bb1
; SMALL64-NEXT: lwz 3, VarTLSLD2[UL]@ld(3)
; SMALL64-NEXT: b L..BB3_3
; SMALL64-NEXT: L..BB3_2: # %return
; SMALL64-NEXT: lwz 3, VarTLSLD1[TL]@ld(3)
; SMALL64-NEXT: L..BB3_3: # %bb1
; SMALL64-NEXT: addi 1, 1, 48
; SMALL64-NEXT: ld 0, 16(1)
; SMALL64-NEXT: mtlr 0
; SMALL64-NEXT: blr
;
; LARGE64-LABEL: Multiple_LD_USE_LD:
; LARGE64: # %bb.0: # %entry
; LARGE64-NEXT: mflr 0
; LARGE64-NEXT: stdu 1, -48(1)
; LARGE64-NEXT: and 6, 3, 4
; LARGE64-NEXT: addis 3, L..C2@u(2)
; LARGE64-NEXT: std 0, 64(1)
; LARGE64-NEXT: ld 3, L..C2@l(3)
; LARGE64-NEXT: bla .__tls_get_mod[PR]
; LARGE64-NEXT: cmpwi 6, -1
; LARGE64-NEXT: bgt 0, L..BB3_2
; LARGE64-NEXT: # %bb.1: # %bb1
; LARGE64-NEXT: lwz 3, VarTLSLD2[UL]@ld(3)
; LARGE64-NEXT: b L..BB3_3
; LARGE64-NEXT: L..BB3_2: # %return
; LARGE64-NEXT: lwz 3, VarTLSLD1[TL]@ld(3)
; LARGE64-NEXT: L..BB3_3: # %bb1
; LARGE64-NEXT: addi 1, 1, 48
; LARGE64-NEXT: ld 0, 16(1)
; LARGE64-NEXT: mtlr 0
; LARGE64-NEXT: blr
entry:
%a = icmp slt i32 %P, 0
%b = icmp slt i32 %Q, 0
%c = and i1 %a, %b
%tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
%load1 = load i32, ptr %tls1, align 4
br i1 %c, label %bb1, label %return

bb1:
%tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD2)
%load2 = load i32, ptr %tls2, align 4
ret i32 %load2

return:
ret i32 %load1
}

define i32 @Multiple_MIX_USE_LD(i32 %P, i32 %Q) {
; SMALL64-LABEL: Multiple_MIX_USE_LD:
; SMALL64: # %bb.0: # %entry
; SMALL64-NEXT: mflr 0
; SMALL64-NEXT: stdu 1, -48(1)
; SMALL64-NEXT: and 6, 3, 4
; SMALL64-NEXT: ld 3, L..C2(2) # target-flags(ppc-tlsldm) @"_$TLSML"
; SMALL64-NEXT: std 0, 64(1)
; SMALL64-NEXT: bla .__tls_get_mod[PR]
; SMALL64-NEXT: cmpwi 6, -1
; SMALL64-NEXT: bgt 0, L..BB4_2
; SMALL64-NEXT: # %bb.1: # %bb1
; SMALL64-NEXT: lwz 3, VarTLSLD1[TL]@ld(3)
; SMALL64-NEXT: b L..BB4_3
; SMALL64-NEXT: L..BB4_2: # %return
; SMALL64-NEXT: lwz 3, VarTLSIE1[TL]@ld(3)
; SMALL64-NEXT: L..BB4_3: # %bb1
; SMALL64-NEXT: addi 1, 1, 48
; SMALL64-NEXT: ld 0, 16(1)
; SMALL64-NEXT: mtlr 0
; SMALL64-NEXT: blr
;
; LARGE64-LABEL: Multiple_MIX_USE_LD:
; LARGE64: # %bb.0: # %entry
; LARGE64-NEXT: mflr 0
; LARGE64-NEXT: stdu 1, -48(1)
; LARGE64-NEXT: and 6, 3, 4
; LARGE64-NEXT: addis 3, L..C2@u(2)
; LARGE64-NEXT: std 0, 64(1)
; LARGE64-NEXT: ld 3, L..C2@l(3)
; LARGE64-NEXT: bla .__tls_get_mod[PR]
; LARGE64-NEXT: cmpwi 6, -1
; LARGE64-NEXT: bgt 0, L..BB4_2
; LARGE64-NEXT: # %bb.1: # %bb1
; LARGE64-NEXT: lwz 3, VarTLSLD1[TL]@ld(3)
; LARGE64-NEXT: b L..BB4_3
; LARGE64-NEXT: L..BB4_2: # %return
; LARGE64-NEXT: lwz 3, VarTLSIE1[TL]@ld(3)
; LARGE64-NEXT: L..BB4_3: # %bb1
; LARGE64-NEXT: addi 1, 1, 48
; LARGE64-NEXT: ld 0, 16(1)
; LARGE64-NEXT: mtlr 0
; LARGE64-NEXT: blr
entry:
%a = icmp slt i32 %P, 0
%b = icmp slt i32 %Q, 0
%c = and i1 %a, %b
%tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSIE1)
%load1 = load i32, ptr %tls1, align 4
br i1 %c, label %bb1, label %return

bb1:
%tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @VarTLSLD1)
%load2 = load i32, ptr %tls2, align 4
ret i32 %load2

return:
ret i32 %load1
}

0 comments on commit a173d24

Please sign in to comment.