1; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -verify-machineinstrs < %s | FileCheck %s 2; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s 3; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-NOLD %s 4; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-NOLD-RELOC %s 5 6@general_dynamic_var = external thread_local global i32 7 8define i32 @test_generaldynamic() { 9; CHECK-LABEL: test_generaldynamic: 10 11 %val = load i32, i32* @general_dynamic_var 12 ret i32 %val 13 14; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 15; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 16; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 17; CHECK-NEXT: .tlsdesccall general_dynamic_var 18; CHECK-NEXT: blr [[CALLEE]] 19 20; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 21; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 22; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 23; CHECK-NOLD-NEXT: .tlsdesccall general_dynamic_var 24; CHECK-NOLD-NEXT: blr [[CALLEE]] 25 26 27; CHECK: mrs x[[TP:[0-9]+]], TPIDR_EL0 28; CHECK: ldr w0, [x[[TP]], x0] 29; CHECK-NOLD: mrs x[[TP:[0-9]+]], TPIDR_EL0 30; CHECK-NOLD: ldr w0, [x[[TP]], x0] 31 32; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 33; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 34; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 35; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 36 37; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 38; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 39; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 40; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 41 42} 43 44define i32* @test_generaldynamic_addr() { 45; CHECK-LABEL: test_generaldynamic_addr: 46 47 ret i32* @general_dynamic_var 48 49; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var 50; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var] 51; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var 52; CHECK-NEXT: .tlsdesccall general_dynamic_var 53; CHECK-NEXT: blr [[CALLEE]] 54 55; CHECK: mrs [[TP:x[0-9]+]], TPIDR_EL0 56; CHECK: add x0, [[TP]], x0 57 58; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 59; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 60; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 61; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 62 63; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 64; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 65; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 66; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 67 68} 69 70@local_dynamic_var = external thread_local(localdynamic) global i32 71 72define i32 @test_localdynamic() { 73; CHECK-LABEL: test_localdynamic: 74 75 %val = load i32, i32* @local_dynamic_var 76 ret i32 %val 77 78; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 79; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 80; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ 81; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ 82; CHECK-NEXT: blr [[CALLEE]] 83; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var 84; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var 85; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 86; CHECK: ldr w0, [x[[TPIDR]], x[[TPOFF]]] 87 88; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var 89; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var] 90; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var 91; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var 92; CHECK-NOLD-NEXT: blr [[CALLEE]] 93; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 94; CHECK-NOLD: ldr w0, [x[[TPIDR]], x0] 95 96 97; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 98; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 99; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 100; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 101; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12 102; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 103 104; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 105; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 106; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 107; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 108 109} 110 111define i32* @test_localdynamic_addr() { 112; CHECK-LABEL: test_localdynamic_addr: 113 114; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 115; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 116; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_ 117; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ 118; CHECK-NEXT: blr [[CALLEE]] 119; CHECK-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var 120; CHECK-NEXT: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var 121; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 122; CHECK: add x0, x[[TPIDR]], x[[TPOFF]] 123 124; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var 125; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var] 126; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var 127; CHECK-NOLD-NEXT: .tlsdesccall local_dynamic_var 128; CHECK-NOLD-NEXT: blr [[CALLEE]] 129; CHECK-NOLD: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 130; CHECK-NOLD: add x0, x[[TPIDR]], x0 131 ret i32* @local_dynamic_var 132 133; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 134; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 135; CHECK-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 136; CHECK-RELOC: R_AARCH64_TLSDESC_CALL 137; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_HI12 138; CHECK-RELOC: R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 139 140; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21 141; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_LD64_LO12_NC 142; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_ADD_LO12_NC 143; CHECK-NOLD-RELOC: R_AARCH64_TLSDESC_CALL 144} 145 146; The entire point of the local-dynamic access model is to have a single call to 147; the expensive resolver. Make sure we achieve that goal. 148 149@local_dynamic_var2 = external thread_local(localdynamic) global i32 150 151define i32 @test_localdynamic_deduplicate() { 152; CHECK-LABEL: test_localdynamic_deduplicate: 153 154 %val = load i32, i32* @local_dynamic_var 155 %val2 = load i32, i32* @local_dynamic_var2 156 157 %sum = add i32 %val, %val2 158 ret i32 %sum 159 160; CHECK: adrp x[[DTPREL_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_ 161; CHECK-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[DTPREL_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_] 162; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE 163; CHECK-NEXT: .tlsdesccall _TLS_MODULE_BASE_ 164; CHECK-NEXT: blr [[CALLEE]] 165 166; CHECK-NOT: _TLS_MODULE_BASE_ 167 168; CHECK: ret 169} 170