1 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -verify-machineinstrs < %s | FileCheck %s 2 ; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s 3 4 @general_dynamic_var = external thread_local global i32 5 6 define i32 @test_generaldynamic() { 7 ; CHECK-LABEL: test_generaldynamic: 8 9 %val = load i32* @general_dynamic_var 10 ret i32 %val 11 12 ; FIXME: the adrp instructions are redundant (if harmless). 13 ; CHECK: adrp [[TLSDESC_HI:x[0-9]+]], :tlsdesc:general_dynamic_var 14 ; CHECK: add x0, [[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 15 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 16 ; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 17 ; CHECK: .tlsdesccall general_dynamic_var 18 ; CHECK-NEXT: blr [[CALLEE]] 19 20 ; CHECK: mrs x[[TP:[0-9]+]], TPIDR_EL0 21 ; CHECK: ldr w0, [x[[TP]], x0] 22 23 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE 24 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 25 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 26 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 27 28 } 29 30 define i32* @test_generaldynamic_addr() { 31 ; CHECK-LABEL: test_generaldynamic_addr: 32 33 ret i32* @general_dynamic_var 34 35 ; FIXME: the adrp instructions are redundant (if harmless). 36 ; CHECK: adrp [[TLSDESC_HI:x[0-9]+]], :tlsdesc:general_dynamic_var 37 ; CHECK: add x0, [[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 38 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 39 ; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 40 ; CHECK: .tlsdesccall general_dynamic_var 41 ; CHECK-NEXT: blr [[CALLEE]] 42 43 ; CHECK: mrs [[TP:x[0-9]+]], TPIDR_EL0 44 ; CHECK: add x0, [[TP]], x0 45 46 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE 47 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 48 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 49 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 50 } 51 52 @local_dynamic_var = external thread_local(localdynamic) global i32 53 54 define i32 @test_localdynamic() { 55 ; CHECK-LABEL: test_localdynamic: 56 57 %val = load i32* @local_dynamic_var 58 ret i32 %val 59 60 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 61 ; CHECK: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ 62 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 63 ; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 64 ; CHECK: .tlsdesccall _TLS_MODULE_BASE_ 65 ; CHECK-NEXT: blr [[CALLEE]] 66 67 ; CHECK: movz [[DTP_OFFSET:x[0-9]+]], #:dtprel_g1:local_dynamic_var 68 ; CHECK: movk [[DTP_OFFSET]], #:dtprel_g0_nc:local_dynamic_var 69 70 ; CHECK: add x[[TPREL:[0-9]+]], x0, [[DTP_OFFSET]] 71 72 ; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 73 74 ; CHECK: ldr w0, [x[[TPIDR]], x[[TPREL]]] 75 76 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE 77 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 78 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 79 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 80 81 } 82 83 define i32* @test_localdynamic_addr() { 84 ; CHECK-LABEL: test_localdynamic_addr: 85 86 ret i32* @local_dynamic_var 87 88 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 89 ; CHECK: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ 90 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 91 ; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 92 ; CHECK: .tlsdesccall _TLS_MODULE_BASE_ 93 ; CHECK-NEXT: blr [[CALLEE]] 94 95 ; CHECK: movz [[DTP_OFFSET:x[0-9]+]], #:dtprel_g1:local_dynamic_var 96 ; CHECK: movk [[DTP_OFFSET]], #:dtprel_g0_nc:local_dynamic_var 97 98 ; CHECK: add [[TPREL:x[0-9]+]], x0, [[DTP_OFFSET]] 99 100 ; CHECK: mrs [[TPIDR:x[0-9]+]], TPIDR_EL0 101 102 ; CHECK: add x0, [[TPIDR]], [[TPREL]] 103 104 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE 105 ; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 106 ; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 107 ; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 108 109 } 110 111 ; The entire point of the local-dynamic access model is to have a single call to 112 ; the expensive resolver. Make sure we achieve that goal. 113 114 @local_dynamic_var2 = external thread_local(localdynamic) global i32 115 116 define i32 @test_localdynamic_deduplicate() { 117 ; CHECK-LABEL: test_localdynamic_deduplicate: 118 119 %val = load i32* @local_dynamic_var 120 %val2 = load i32* @local_dynamic_var2 121 122 %sum = add i32 %val, %val2 123 ret i32 %sum 124 125 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 126 ; CHECK: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ 127 ; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 128 ; CHECK: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 129 ; CHECK: .tlsdesccall _TLS_MODULE_BASE_ 130 ; CHECK-NEXT: blr [[CALLEE]] 131 132 ; CHECK-NOT: _TLS_MODULE_BASE_ 133 134 ; CHECK: ret 135 } 136