mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-09 13:41:35 +00:00
7da5357aca
In PIC mode we were previously computing global variable addresses (or GOT entry addresses) by adding the PC, the PC-relative GOT displacement and the GOT-relative symbol/GOT entry displacement. Because the latter two displacements are fixed, we ended up performing one more addition than necessary. This change causes us to compute addresses using a single PC-relative displacement, resulting in a shorter code sequence. This reduces code size by about 4% in a recent build of Chromium for Android. As a result of this change we no longer need to compute the GOT base address in the ARM backend, which allows us to remove the Global Base Reg pass and SDAG lowering for the GOT. We also now no longer use the GOT when addressing a symbol which is known to be defined in the same linkage unit. Specifically, the symbol must have either hidden visibility or a strong definition in the current module in order to not use the the GOT. This is a change from the previous behaviour where we would use the GOT to address externally visible symbols defined in the same module. I think the only cases where this could matter are cases involving symbol interposition, but we don't really support that well anyway. Differential Revision: http://reviews.llvm.org/D13650 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251322 91177308-0d34-0410-b5e6-96231b3b80d8
259 lines
5.3 KiB
LLVM
259 lines
5.3 KiB
LLVM
; RUN: llc -emulated-tls -mtriple=arm-linux-android \
|
|
; RUN: -relocation-model=pic < %s | FileCheck -check-prefix=ARM32 %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() {
|
|
; ARM32-LABEL: my_get_xyz:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl my_emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldr r0, [r0]
|
|
|
|
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() {
|
|
; ARM32-LABEL: f1:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldr r0, [r0]
|
|
|
|
entry:
|
|
%tmp1 = load i32, i32* @i1
|
|
ret i32 %tmp1
|
|
}
|
|
|
|
define i32* @f2() {
|
|
; ARM32-LABEL: f2:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: pop
|
|
|
|
entry:
|
|
ret i32* @i1
|
|
}
|
|
|
|
define i32 @f3() nounwind {
|
|
; ARM32-LABEL: f3:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldr r0, [r0]
|
|
|
|
entry:
|
|
%tmp1 = load i32, i32* @i2
|
|
ret i32 %tmp1
|
|
}
|
|
|
|
define i32* @f4() {
|
|
; ARM32-LABEL: f4:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: pop
|
|
|
|
entry:
|
|
ret i32* @i2
|
|
}
|
|
|
|
define i32 @f5() nounwind {
|
|
; ARM32-LABEL: f5:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldr r0, [r0]
|
|
|
|
entry:
|
|
%tmp1 = load i32, i32* @i3
|
|
ret i32 %tmp1
|
|
}
|
|
|
|
define i32* @f6() {
|
|
; ARM32-LABEL: f6:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: pop
|
|
|
|
entry:
|
|
ret i32* @i3
|
|
}
|
|
|
|
define i32 @f7() {
|
|
; ARM32-LABEL: f7:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldr r0, [r0]
|
|
|
|
entry:
|
|
%tmp1 = load i32, i32* @i4
|
|
ret i32 %tmp1
|
|
}
|
|
|
|
define i32* @f8() {
|
|
; ARM32-LABEL: f8:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: pop
|
|
|
|
entry:
|
|
ret i32* @i4
|
|
}
|
|
|
|
define i32 @f9() {
|
|
; ARM32-LABEL: f9:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldr r0, [r0]
|
|
|
|
entry:
|
|
%tmp1 = load i32, i32* @i5
|
|
ret i32 %tmp1
|
|
}
|
|
|
|
define i32* @f10() {
|
|
; ARM32-LABEL: f10:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: pop
|
|
|
|
entry:
|
|
ret i32* @i5
|
|
}
|
|
|
|
define i16 @f11() {
|
|
; ARM32-LABEL: f11:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldrh r0, [r0]
|
|
|
|
entry:
|
|
%tmp1 = load i16, i16* @s1
|
|
ret i16 %tmp1
|
|
}
|
|
|
|
define i32 @f12() {
|
|
; ARM32-LABEL: f12:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldrsh r0, [r0]
|
|
|
|
entry:
|
|
%tmp1 = load i16, i16* @s1
|
|
%tmp2 = sext i16 %tmp1 to i32
|
|
ret i32 %tmp2
|
|
}
|
|
|
|
define i8 @f13() {
|
|
; ARM32-LABEL: f13:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldrb r0, [r0]
|
|
; ARM32-NEXT: pop
|
|
|
|
entry:
|
|
%tmp1 = load i8, i8* @b1
|
|
ret i8 %tmp1
|
|
}
|
|
|
|
define i32 @f14() {
|
|
; ARM32-LABEL: f14:
|
|
; ARM32: ldr r0,
|
|
; ARM32: ldr r0, [pc, r0]
|
|
; ARM32-NEXT: bl __emutls_get_address(PLT)
|
|
; ARM32-NEXT: ldrsb r0, [r0]
|
|
; ARM32-NEXT: pop
|
|
|
|
entry:
|
|
%tmp1 = load i8, i8* @b1
|
|
%tmp2 = sext i8 %tmp1 to i32
|
|
ret i32 %tmp2
|
|
}
|
|
|
|
;;;;;;;;;;;;;; 32-bit __emutls_v. and __emutls_t.
|
|
|
|
; ARM32 .section .data.rel.local,
|
|
; ARM32-LABEL: __emutls_v.i1:
|
|
; ARM32-NEXT: .long 4
|
|
; ARM32-NEXT: .long 4
|
|
; ARM32-NEXT: .long 0
|
|
; ARM32-NEXT: .long __emutls_t.i1
|
|
|
|
; ARM32 .section .rodata,
|
|
; ARM32-LABEL: __emutls_t.i1:
|
|
; ARM32-NEXT: .long 15
|
|
|
|
; ARM32-NOT: __emutls_v.i2
|
|
|
|
; ARM32 .section .data.rel.local,
|
|
; ARM32-LABEL: __emutls_v.i3:
|
|
; ARM32-NEXT: .long 4
|
|
; ARM32-NEXT: .long 4
|
|
; ARM32-NEXT: .long 0
|
|
; ARM32-NEXT: .long __emutls_t.i3
|
|
|
|
; ARM32 .section .rodata,
|
|
; ARM32-LABEL: __emutls_t.i3:
|
|
; ARM32-NEXT: .long 15
|
|
|
|
; ARM32 .section .data.rel.local,
|
|
; ARM32-LABEL: __emutls_v.i4:
|
|
; ARM32-NEXT: .long 4
|
|
; ARM32-NEXT: .long 4
|
|
; ARM32-NEXT: .long 0
|
|
; ARM32-NEXT: .long __emutls_t.i4
|
|
|
|
; ARM32 .section .rodata,
|
|
; ARM32-LABEL: __emutls_t.i4:
|
|
; ARM32-NEXT: .long 15
|
|
|
|
; ARM32-NOT: __emutls_v.i5:
|
|
; ARM32 .hidden __emutls_v.i5
|
|
; ARM32-NOT: __emutls_v.i5:
|
|
|
|
; ARM32 .section .data.rel.local,
|
|
; ARM32-LABEL: __emutls_v.s1:
|
|
; ARM32-NEXT: .long 2
|
|
; ARM32-NEXT: .long 2
|
|
; ARM32-NEXT: .long 0
|
|
; ARM32-NEXT: .long __emutls_t.s1
|
|
|
|
; ARM32 .section .rodata,
|
|
; ARM32-LABEL: __emutls_t.s1:
|
|
; ARM32-NEXT: .short 15
|
|
|
|
; ARM32 .section .data.rel.local,
|
|
; ARM32-LABEL: __emutls_v.b1:
|
|
; ARM32-NEXT: .long 1
|
|
; ARM32-NEXT: .long 1
|
|
; ARM32-NEXT: .long 0
|
|
; ARM32-NEXT: .long 0
|
|
|
|
; ARM32-NOT: __emutls_t.b1
|