llvm-project/llvm/test/CodeGen/AArch64/emutls.ll

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

218 lines
5.8 KiB
LLVM
Raw Normal View History

; RUN: llc -emulated-tls -mtriple=aarch64-linux-android \
; RUN: -relocation-model=pic -frame-pointer=all < %s | FileCheck -check-prefix=ARM64 %s
; RUN: llc -mtriple=aarch64-linux-android \
; RUN: -relocation-model=pic -frame-pointer=all < %s | FileCheck -check-prefix=ARM64 %s
; Copied from X86/emutls.ll
; Use my_emutls_get_address like __emutls_get_address.
@my_emutls_v_xyz = external global i8*, align 4
declare i8* @my_emutls_get_address(i8*)
define i32 @my_get_xyz() {
; ARM64-LABEL: my_get_xyz:
; ARM64: adrp x0, :got:my_emutls_v_xyz
; ARM64-NEXT: ldr x0, [x0, :got_lo12:my_emutls_v_xyz]
; ARM64-NEXT: bl my_emutls_get_address
; ARM64-NEXT: ldr w0, [x0]
; ARM64-NEXT: ldp x29, x30, [sp]
entry:
%call = call i8* @my_emutls_get_address(i8* bitcast (i8** @my_emutls_v_xyz to i8*))
%0 = bitcast i8* %call to i32*
%1 = load i32, i32* %0, align 4
ret i32 %1
}
@i1 = thread_local global i32 15
@i2 = external thread_local global i32
@i3 = internal thread_local global i32 15
@i4 = hidden thread_local global i32 15
@i5 = external hidden thread_local global i32
@s1 = thread_local global i16 15
@b1 = thread_local global i8 0
define i32 @f1() {
; ARM64-LABEL: f1:
; ARM64: adrp x0, :got:__emutls_v.i1
; ARM64-NEXT: ldr x0, [x0, :got_lo12:__emutls_v.i1]
; ARM64-NEXT: bl __emutls_get_address
; ARM64-NEXT: ldr w0, [x0]
; ARM64-NEXT: ldp x29, x30, [sp]
entry:
%tmp1 = load i32, i32* @i1
ret i32 %tmp1
}
define i32* @f2() {
; ARM64-LABEL: f2:
; ARM64: adrp x0, :got:__emutls_v.i1
; ARM64-NEXT: ldr x0, [x0, :got_lo12:__emutls_v.i1]
; ARM64-NEXT: bl __emutls_get_address
; ARM64-NEXT: ldp x29, x30, [sp]
entry:
ret i32* @i1
}
define i32 @f5() nounwind {
; ARM64-LABEL: f5:
; ARM64: adrp x0, __emutls_v.i3
; ARM64: add x0, x0, :lo12:__emutls_v.i3
; ARM64: bl __emutls_get_address
; ARM64-NEXT: ldr w0, [x0]
entry:
%tmp1 = load i32, i32* @i3
ret i32 %tmp1
}
define i32* @f6() {
; ARM64-LABEL: f6:
; ARM64: adrp x0, __emutls_v.i3
; ARM64: add x0, x0, :lo12:__emutls_v.i3
; ARM64-NEXT: bl __emutls_get_address
; ARM64-NEXT: ldp x29, x30, [sp]
entry:
ret i32* @i3
}
; Simple test of comdat __thread variables.
; template <class T> struct A { static __thread T x; };
; template <class T> T __thread A<T>::x;
; int getIntX() { return A<int>::x++; }
; float getFloatX() { return A<float>::x++; }
$_ZN1AIiE1xE = comdat any
$_ZN1AIfE1xE = comdat any
@_ZN1AIiE1xE = linkonce_odr thread_local global i32 0, comdat, align 4
@_ZN1AIfE1xE = linkonce_odr thread_local global float 0.000000e+00, comdat, align 4
define i32 @_Z7getIntXv() {
; ARM64-LABEL: _Z7getIntXv:
; ARM64: adrp x0, :got:__emutls_v._ZN1AIiE1xE
; ARM64: ldr x0, [x0, :got_lo12:__emutls_v._ZN1AIiE1xE]
; ARM64-NEXT: bl __emutls_get_address
; ARM64-NEXT: ldr {{.*}}, [x0]
; ARM64: add
; ARM64: str {{.*}}, [x0]
entry:
%0 = load i32, i32* @_ZN1AIiE1xE, align 4
%inc = add nsw i32 %0, 1
store i32 %inc, i32* @_ZN1AIiE1xE, align 4
ret i32 %0
}
define float @_Z9getFloatXv() {
; ARM64-LABEL: _Z9getFloatXv:
; ARM64: adrp x0, :got:__emutls_v._ZN1AIfE1xE
; ARM64: ldr x0, [x0, :got_lo12:__emutls_v._ZN1AIfE1xE]
; ARM64-NEXT: bl __emutls_get_address
; ARM64-NEXT: ldr {{.*}}, [x0]
; ARM64: fadd s{{.*}}, s
; ARM64: str s{{.*}}, [x0]
entry:
%0 = load float, float* @_ZN1AIfE1xE, align 4
%inc = fadd float %0, 1.000000e+00
store float %inc, float* @_ZN1AIfE1xE, align 4
ret float %0
}
;;;;;;;;;;;;;; 64-bit __emutls_v. and __emutls_t.
; ARM64: .data{{$}}
; ARM64: .globl __emutls_v.i1
; ARM64-LABEL: __emutls_v.i1:
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword __emutls_t.i1
; ARM64: .section .rodata,
; ARM64-LABEL: __emutls_t.i1:
; ARM64-NEXT: .word 15
; ARM64-NOT: __emutls_v.i2
; ARM64: .data{{$}}
; ARM64-NOT: .globl
; ARM64-LABEL: __emutls_v.i3:
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword __emutls_t.i3
; ARM64: .section .rodata,
; ARM64-LABEL: __emutls_t.i3:
; ARM64-NEXT: .word 15
; ARM64: .hidden __emutls_v.i4
; ARM64: .data{{$}}
; ARM64: .globl __emutls_v.i4
; ARM64-LABEL: __emutls_v.i4:
[AsmPrinter][ELF] Define local aliases (.Lfoo$local) for GlobalObjects For `MC_GlobalAddress` operands referencing **certain** GlobalObjects, we can lower them to STB_LOCAL aliases to avoid costs brought by assembler/linker's conservative decisions about symbol interposition: * An assembler conservatively assumes a global default visibility symbol interposable (ELF semantics). So relocations in object files are needed even if the code generator assumed the definition exact and non-interposable. * The relocations can cause the creation of PLT entries on some targets for -shared links. A linker conservatively assumes a global default visibility symbol interposable (if not otherwise constrained by -Bsymbolic/--dynamic-list/VER_NDX_LOCAL/etc). "certain" refers to GlobalObjects in the intersection of `hasExactDefinition() and !isInterposable()`: `external`, `appending`, `internal`, `private`. Local linkages (`internal` and `private`) cannot be interposed. `appending` is for very few objects LLVM interpret specially. So the set just includes `external`. This patch emits STB_LOCAL aliases (.Lfoo$local) for such GlobalObjects, so that targets can lower MC_GlobalAddress operands to STB_LOCAL aliases if applicable. We may extend the scope and include GlobalAlias in the future. LLVM's existing -fno-semantic-interposition behaviors give us license to do such optimizations: * Various optimizations (ipconstprop, inliner, sccp, sroa, etc) treat normal ExternalLinkage GlobalObjects as non-interposable. * Before D72197, MC resolved a PC-relative VK_None fixup to a non-local symbol at assembly time (no outstanding relocation), if the target is defined in the same section. Put it simply, even if IR optimizations failed to optimize and allowed interposition for the function call in `void foo() {} void bar() { foo(); }`, the assembler would disallow it. This patch sets up AsmPrinter infrastructure to make -fno-semantic-interposition more so. With and without the patch, the object file output should be identical: `.Lfoo$local` does not take a symbol table entry. Reviewed By: sfertile Differential Revision: https://reviews.llvm.org/D73228
2020-01-23 04:26:04 +08:00
; ARM64-NEXT: .L__emutls_v.i4$local:
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword __emutls_t.i4
; ARM64: .section .rodata,
; ARM64-LABEL: __emutls_t.i4:
[AsmPrinter][ELF] Define local aliases (.Lfoo$local) for GlobalObjects For `MC_GlobalAddress` operands referencing **certain** GlobalObjects, we can lower them to STB_LOCAL aliases to avoid costs brought by assembler/linker's conservative decisions about symbol interposition: * An assembler conservatively assumes a global default visibility symbol interposable (ELF semantics). So relocations in object files are needed even if the code generator assumed the definition exact and non-interposable. * The relocations can cause the creation of PLT entries on some targets for -shared links. A linker conservatively assumes a global default visibility symbol interposable (if not otherwise constrained by -Bsymbolic/--dynamic-list/VER_NDX_LOCAL/etc). "certain" refers to GlobalObjects in the intersection of `hasExactDefinition() and !isInterposable()`: `external`, `appending`, `internal`, `private`. Local linkages (`internal` and `private`) cannot be interposed. `appending` is for very few objects LLVM interpret specially. So the set just includes `external`. This patch emits STB_LOCAL aliases (.Lfoo$local) for such GlobalObjects, so that targets can lower MC_GlobalAddress operands to STB_LOCAL aliases if applicable. We may extend the scope and include GlobalAlias in the future. LLVM's existing -fno-semantic-interposition behaviors give us license to do such optimizations: * Various optimizations (ipconstprop, inliner, sccp, sroa, etc) treat normal ExternalLinkage GlobalObjects as non-interposable. * Before D72197, MC resolved a PC-relative VK_None fixup to a non-local symbol at assembly time (no outstanding relocation), if the target is defined in the same section. Put it simply, even if IR optimizations failed to optimize and allowed interposition for the function call in `void foo() {} void bar() { foo(); }`, the assembler would disallow it. This patch sets up AsmPrinter infrastructure to make -fno-semantic-interposition more so. With and without the patch, the object file output should be identical: `.Lfoo$local` does not take a symbol table entry. Reviewed By: sfertile Differential Revision: https://reviews.llvm.org/D73228
2020-01-23 04:26:04 +08:00
; ARM64-NEXT: .L__emutls_t.i4$local:
; ARM64-NEXT: .word 15
; ARM64-NOT: __emutls_v.i5:
; ARM64: .hidden __emutls_v.i5
; ARM64-NOT: __emutls_v.i5:
; ARM64: .data{{$}}
; ARM64: .globl __emutls_v.s1
; ARM64-LABEL: __emutls_v.s1:
; ARM64-NEXT: .xword 2
; ARM64-NEXT: .xword 2
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword __emutls_t.s1
; ARM64: .section .rodata,
; ARM64-LABEL: __emutls_t.s1:
; ARM64-NEXT: .hword 15
; ARM64: .data{{$}}
; ARM64-LABEL: __emutls_v.b1:
; ARM64-NEXT: .xword 1
; ARM64-NEXT: .xword 1
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword 0
; ARM64-NOT: __emutls_t.b1
; ARM64: .section .data.__emutls_v._ZN1AIiE1xE,{{.*}},__emutls_v._ZN1AIiE1xE,comdat
; ARM64: .weak __emutls_v._ZN1AIiE1xE
; ARM64: .p2align 3
; ARM64-LABEL: __emutls_v._ZN1AIiE1xE:
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword 0
; ARM64: .section .data.__emutls_v._ZN1AIfE1xE,{{.*}},__emutls_v._ZN1AIfE1xE,comdat
; ARM64: .weak __emutls_v._ZN1AIfE1xE
; ARM64: .p2align 3
; ARM64-LABEL: __emutls_v._ZN1AIfE1xE:
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword __emutls_t._ZN1AIfE1xE
; ARM64: .section .rodata.__emutls_t._ZN1AIfE1xE,{{.*}},__emutls_t._ZN1AIfE1xE,comdat
; ARM64: .weak __emutls_t._ZN1AIfE1xE
; ARM64: .p2align 2
; ARM64-LABEL: __emutls_t._ZN1AIfE1xE:
; ARM64-NEXT: .word 0
; ARM64-NEXT: .size