176 lines · plain
1; This test checks experimental Emscripten-specific `generaldynamic` TLS support. See `tls-local-exec.ll` for non-Emscripten targets (since it lowers all TLS to `localexec`).2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory,atomics | FileCheck %s --check-prefixes=CHECK,TLS3; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory,atomics -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS4; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=-bulk-memory,atomics | FileCheck %s --check-prefixes=CHECK,NO-TLS5target triple = "wasm32-unknown-emscripten"6 7; CHECK-LABEL: address_of_tls:8; CHECK-NEXT: .functype address_of_tls () -> (i32)9define i32 @address_of_tls() {10 ; TLS-DAG: global.get __tls_base11 ; TLS-DAG: i32.const tls@TLSREL12 ; TLS-NEXT: i32.add13 ; TLS-NEXT: return14 15 ; NO-TLS-NEXT: i32.const tls16 ; NO-TLS-NEXT: return17 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls)18 %r = ptrtoint ptr %p to i3219 ret i32 %r20}21 22; CHECK-LABEL: address_of_tls_external:23; CHECK-NEXT: .functype address_of_tls_external () -> (i32)24define i32 @address_of_tls_external() {25 ; TLS-DAG: global.get tls_external@GOT@TLS26 ; TLS-NEXT: return27 28 ; NO-TLS-NEXT: i32.const tls_external29 ; NO-TLS-NEXT: return30 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls_external)31 %r = ptrtoint ptr %p to i3232 ret i32 %r33}34 35; CHECK-LABEL: ptr_to_tls:36; CHECK-NEXT: .functype ptr_to_tls () -> (i32)37define ptr @ptr_to_tls() {38 ; TLS-DAG: global.get __tls_base39 ; TLS-DAG: i32.const tls@TLSREL40 ; TLS-NEXT: i32.add41 ; TLS-NEXT: return42 43 ; NO-TLS-NEXT: i32.const tls44 ; NO-TLS-NEXT: return45 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls)46 ret ptr %p47}48 49; CHECK-LABEL: ptr_to_tls_external:50; CHECK-NEXT: .functype ptr_to_tls_external () -> (i32)51define ptr @ptr_to_tls_external() {52 ; TLS-DAG: global.get tls_external@GOT@TLS53 ; TLS-NEXT: return54 55 ; NO-TLS-NEXT: i32.const tls_external56 ; NO-TLS-NEXT: return57 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls_external)58 ret ptr %p59}60 61; CHECK-LABEL: tls_load:62; CHECK-NEXT: .functype tls_load () -> (i32)63define i32 @tls_load() {64 ; TLS-DAG: global.get __tls_base65 ; TLS-DAG: i32.const tls@TLSREL66 ; TLS-NEXT: i32.add67 ; TLS-NEXT: i32.load 068 ; TLS-NEXT: return69 70 ; NO-TLS-NEXT: i32.const 071 ; NO-TLS-NEXT: i32.load tls72 ; NO-TLS-NEXT: return73 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls)74 %tmp = load i32, ptr %p, align 475 ret i32 %tmp76}77 78; CHECK-LABEL: tls_load_external:79; CHECK-NEXT: .functype tls_load_external () -> (i32)80define i32 @tls_load_external() {81 ; TLS-DAG: global.get tls_external@GOT@TLS82 ; TLS-NEXT: i32.load 083 ; TLS-NEXT: return84 85 ; NO-TLS-NEXT: i32.const 086 ; NO-TLS-NEXT: i32.load tls_external87 ; NO-TLS-NEXT: return88 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls_external)89 %tmp = load i32, ptr %p, align 490 ret i32 %tmp91}92 93; CHECK-LABEL: tls_store:94; CHECK-NEXT: .functype tls_store (i32) -> ()95define void @tls_store(i32 %x) {96 ; TLS-DAG: global.get __tls_base97 ; TLS-DAG: i32.const tls@TLSREL98 ; TLS-NEXT: i32.add99 ; TLS-NEXT: i32.store 0100 ; TLS-NEXT: return101 102 ; NO-TLS-NEXT: i32.const 0103 ; NO-TLS-NEXT: i32.store tls104 ; NO-TLS-NEXT: return105 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls)106 store i32 %x, ptr %p, align 4107 ret void108}109 110; CHECK-LABEL: tls_store_external:111; CHECK-NEXT: .functype tls_store_external (i32) -> ()112define void @tls_store_external(i32 %x) {113 ; TLS-DAG: global.get tls_external@GOT@TLS114 ; TLS-NEXT: i32.store 0115 ; TLS-NEXT: return116 117 ; NO-TLS-NEXT: i32.const 0118 ; NO-TLS-NEXT: i32.store tls_external119 ; NO-TLS-NEXT: return120 %p = call ptr @llvm.threadlocal.address.p0(ptr @tls_external)121 store i32 %x, ptr %p, align 4122 ret void123}124 125; CHECK-LABEL: tls_size:126; CHECK-NEXT: .functype tls_size () -> (i32)127define i32 @tls_size() {128; CHECK-NEXT: global.get __tls_size129; CHECK-NEXT: return130 %1 = call i32 @llvm.wasm.tls.size.i32()131 ret i32 %1132}133 134; CHECK-LABEL: tls_align:135; CHECK-NEXT: .functype tls_align () -> (i32)136define i32 @tls_align() {137; CHECK-NEXT: global.get __tls_align138; CHECK-NEXT: return139 %1 = call i32 @llvm.wasm.tls.align.i32()140 ret i32 %1141}142 143; CHECK-LABEL: tls_base:144; CHECK-NEXT: .functype tls_base () -> (i32)145define ptr @tls_base() {146; CHECK-NEXT: global.get __tls_base147; CHECK-NEXT: return148 %1 = call ptr @llvm.wasm.tls.base()149 ret ptr %1150}151 152; CHECK-LABEL: tls_base_write:153; CHECK-NEXT: .functype tls_base_write (i32) -> ()154define void @tls_base_write(ptr %output) {155; CHECK-NEXT: global.get __tls_base156; CHECK-NEXT: i32.store 0157; CHECK-NEXT: return158 %1 = call ptr @llvm.wasm.tls.base()159 store ptr %1, ptr %output160 ret void161}162 163; CHECK: .type tls,@object164; TLS-NEXT: .section .tbss.tls,"T",@165; NO-TLS-NEXT: .section .bss.tls,"",@166; CHECK-NEXT: .p2align 2167; CHECK-NEXT: tls:168; CHECK-NEXT: .int32 0169@tls = internal thread_local global i32 0170 171@tls_external = external thread_local global i32, align 4172 173declare i32 @llvm.wasm.tls.size.i32()174declare i32 @llvm.wasm.tls.align.i32()175declare ptr @llvm.wasm.tls.base()176