| // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s --check-prefix=CIR-BEFORE-LPP |
| // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s --check-prefix=CIR |
| // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM-BOTH,LLVM |
| // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM-BOTH,OGCG |
| |
| int get_i(); |
| struct CtorDtor { |
| constexpr CtorDtor(int i) : i(i){} |
| ~CtorDtor(){} |
| int i; |
| }; |
| |
| // LLVM-BOTH-DAG: @__tls_guard = internal thread_local global i8 0, align 1 |
| // LLVM-BOTH-DAG: @__dso_handle = external hidden global i8 |
| // LLVM-BOTH-DAG: @tls_cd = thread_local global %struct.CtorDtor { i32 5 }, align 4 |
| // LLVM-BOTH-DAG: @tls_cd_dyn = thread_local global %struct.CtorDtor zeroinitializer, align 4 |
| // LLVM-BOTH-DAG: @tls_cd_ref = thread_local global ptr null, align 8 |
| // LLVM-BOTH-DAG: @tls_cd_dyn_not_used = thread_local global %struct.CtorDtor zeroinitializer, align 4 |
| // |
| // LLVM-BOTH-DAG: @_ZTH19tls_cd_dyn_not_used = alias void (), ptr @__tls_init |
| // LLVM-BOTH-DAG: @_ZTH10tls_cd_ref = alias void (), ptr @__tls_init |
| // LLVM-BOTH-DAG: @_ZTH10tls_cd_dyn = alias void (), ptr @__tls_init |
| // LLVM-BOTH-DAG: @_ZTH6tls_cd = alias void (), ptr @__tls_init |
| |
| // Wrappers & aliases. |
| // CIR: cir.global internal tls_dyn @__tls_guard = #cir.int<0> : !s8i {alignment = 1 : i64} |
| // CIR-LABEL: cir.func comdat weak_odr private hidden @_ZTW19tls_cd_dyn_not_used() -> !cir.ptr<!rec_CtorDtor> { |
| // CIR: cir.call @_ZTH19tls_cd_dyn_not_used() : () -> () |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.return %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.func @_ZTH19tls_cd_dyn_not_used() alias(@__tls_init) |
| |
| // CIR-LABEL: cir.func comdat weak_odr private hidden @_ZTW10tls_cd_ref() -> !cir.ptr<!cir.ptr<!rec_CtorDtor>> { |
| // CIR: cir.call @_ZTH10tls_cd_ref() : () -> () |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // CIR: cir.return %[[GET_GLOB]] : !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // CIR: cir.func @_ZTH10tls_cd_ref() alias(@__tls_init) |
| |
| // CIR-LABEL: cir.func comdat weak_odr private hidden @_ZTW10tls_cd_dyn() -> !cir.ptr<!rec_CtorDtor> { |
| // CIR: cir.call @_ZTH10tls_cd_dyn() : () -> () |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.return %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.func @_ZTH10tls_cd_dyn() alias(@__tls_init) |
| |
| // CIR-LABEL: cir.func comdat weak_odr private hidden @_ZTW6tls_cd() -> !cir.ptr<!rec_CtorDtor> { |
| // CIR: cir.call @_ZTH6tls_cd() : () -> () |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.return %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.func @_ZTH6tls_cd() alias(@__tls_init) |
| |
| // CIR-LABEL: cir.func internal private @__tls_init() { |
| // CIR: %[[GET_GUARD:.*]] = cir.get_global thread_local @__tls_guard : !cir.ptr<!s8i> |
| // CIR: %[[LOAD_GUARD:.*]] = cir.load align(1) %[[GET_GUARD]] : !cir.ptr<!s8i>, !s8i |
| // CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s8i |
| // CIR: %[[CMP:.*]] = cir.cmp eq %[[LOAD_GUARD]], %[[ZERO]] : !s8i |
| // CIR: cir.if %[[CMP]] { |
| // CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s8i |
| // CIR: cir.store %[[ONE]], %[[GET_GUARD]] : !s8i, !cir.ptr<!s8i> |
| // CIR: cir.call @[[TLS_CD_INIT:.*]]() : () -> () |
| // CIR: cir.call @[[TLS_CD_DYN_INIT:.*]]() : () -> () |
| // CIR: cir.call @[[TLS_CD_REF_INIT:.*]]() : () -> () |
| // CIR: cir.call @[[TLS_CD_DYN_NOT_USED_INIT:.*]]() : () -> () |
| // CIR: } |
| // CIR: cir.return |
| |
| // LLVM: define weak_odr hidden ptr @_ZTW19tls_cd_dyn_not_used() { |
| // LLVM: call void @_ZTH19tls_cd_dyn_not_used() |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn_not_used) |
| // LLVM: ret ptr %[[GET_GLOB]] |
| // LLVM: } |
| // |
| // LLVM: define weak_odr hidden ptr @_ZTW10tls_cd_ref() { |
| // LLVM: call void @_ZTH10tls_cd_ref() |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_ref) |
| // LLVM: ret ptr %[[GET_GLOB]] |
| // LLVM: } |
| // |
| // LLVM: define weak_odr hidden ptr @_ZTW10tls_cd_dyn() { |
| // LLVM: call void @_ZTH10tls_cd_dyn() |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn) |
| // LLVM: ret ptr %[[GET_GLOB]] |
| // LLVM: } |
| // |
| // LLVM: define weak_odr hidden ptr @_ZTW6tls_cd() { |
| // LLVM: call void @_ZTH6tls_cd() |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd) |
| // LLVM: ret ptr %[[GET_GLOB]] |
| // LLVM: } |
| // |
| // LLVM: define internal void @__tls_init() { |
| // LLVM: %[[GET_GUARD:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @__tls_guard) |
| // LLVM: %[[LOAD_GUARD:.*]] = load i8, ptr %[[GET_GUARD]], align 1 |
| // LLVM: %[[IS_UNINIT:.*]] = icmp eq i8 %[[LOAD_GUARD]], 0 |
| // LLVM: br i1 %[[IS_UNINIT]] |
| // LLVM |
| // LLVM: store i8 1, ptr %[[GET_GUARD]], align 1 |
| // LLVM: call void @[[TLS_CD_INIT:.*]]() |
| // LLVM: call void @[[TLS_CD_DYN_INIT:.*]]() |
| // LLVM: call void @[[TLS_CD_REF_INIT:.*]]() |
| // LLVM: call void @[[TLS_CD_DYN_NOT_USED_INIT:.*]]() |
| |
| thread_local CtorDtor tls_cd = 5; |
| // CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW6tls_cd", "_ZTH6tls_cd"> @tls_cd = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_CtorDtor dtor { |
| // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd : !cir.ptr<!rec_CtorDtor> |
| // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorD1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_CtorDtor>) -> () |
| // CIR-BEFORE-LPP: } |
| // CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW6tls_cd", "_ZTH6tls_cd"> @tls_cd = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_CtorDtor |
| // CIR: cir.func internal private @[[TLS_CD_INIT]]() { |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd : !cir.ptr<!rec_CtorDtor> |
| // CIR: %[[GET_DTOR:.*]] = cir.get_global @_ZN8CtorDtorD1Ev : !cir.ptr<!cir.func<(!cir.ptr<!rec_CtorDtor>)>> |
| // CIR: %[[DTOR_DECAY:.*]] = cir.cast bitcast %[[GET_DTOR]] : !cir.ptr<!cir.func<(!cir.ptr<!rec_CtorDtor>)>> -> !cir.ptr<!cir.func<(!cir.ptr<!void>)>> |
| // CIR: %[[GLOB_DECAY:.*]] = cir.cast bitcast %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor> -> !cir.ptr<!void> |
| // CIR: %[[DSOHANDLE:.*]] = cir.get_global @__dso_handle : !cir.ptr<i8> |
| // CIR: cir.call @__cxa_thread_atexit(%[[DTOR_DECAY]], %[[GLOB_DECAY]], %[[DSOHANDLE]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>)>>, !cir.ptr<!void>, !cir.ptr<i8>) -> !s32i |
| // CIR: cir.return |
| // |
| // LLVM: define internal void @[[TLS_CD_INIT]]() { |
| // OGCG: define internal void @[[TLS_CD_INIT:.*]]() {{.*}}{ |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd) |
| // LLVM: call i32 @__cxa_thread_atexit(ptr @_ZN8CtorDtorD1Ev, ptr %[[GET_GLOB]], ptr @__dso_handle) |
| // OGCG: call i32 @__cxa_thread_atexit(ptr @_ZN8CtorDtorD1Ev, ptr @tls_cd, ptr @__dso_handle) |
| // LLVM-BOTH: ret void |
| |
| thread_local CtorDtor tls_cd_dyn = get_i(); |
| // CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = ctor : !rec_CtorDtor { |
| // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> |
| // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) |
| // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) : (!cir.ptr<!rec_CtorDtor> |
| // CIR-BEFORE-LPP: } dtor { |
| // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> |
| // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorD1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_CtorDtor>) -> () |
| // CIR-BEFORE-LPP: } |
| // CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = #cir.zero : !rec_CtorDtor |
| // CIR: cir.func internal private @[[TLS_CD_DYN_INIT]]() { |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> |
| // CIR: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) |
| // CIR: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> |
| // CIR: %[[GET_DTOR:.*]] = cir.get_global @_ZN8CtorDtorD1Ev : !cir.ptr<!cir.func<(!cir.ptr<!rec_CtorDtor>)>> |
| // CIR: %[[DTOR_DECAY:.*]] = cir.cast bitcast %[[GET_DTOR]] : !cir.ptr<!cir.func<(!cir.ptr<!rec_CtorDtor>)>> -> !cir.ptr<!cir.func<(!cir.ptr<!void>)>> |
| // CIR: %[[GLOB_DECAY:.*]] = cir.cast bitcast %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor> -> !cir.ptr<!void> |
| // CIR: %[[DSOHANDLE:.*]] = cir.get_global @__dso_handle : !cir.ptr<i8> |
| // CIR: cir.call @__cxa_thread_atexit(%[[DTOR_DECAY]], %[[GLOB_DECAY]], %[[DSOHANDLE]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>)>>, !cir.ptr<!void>, !cir.ptr<i8>) -> !s32i |
| // CIR: cir.return |
| // |
| // LLVM: define internal void @[[TLS_CD_DYN_INIT]]() { |
| // OGCG: define internal void @[[TLS_CD_DYN_INIT:.*]]() {{.*}} { |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn) |
| // LLVM-BOTH: %[[CALL:.*]] = call noundef i32 @_Z5get_iv() |
| // LLVM: call void @_ZN8CtorDtorC1Ei(ptr {{.*}}%[[GET_GLOB]], i32 {{.*}}%[[CALL]]) |
| // OGCG: call void @_ZN8CtorDtorC1Ei(ptr {{.*}}@tls_cd_dyn, i32 {{.*}}%[[CALL]]) |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn) |
| // LLVM: call i32 @__cxa_thread_atexit(ptr @_ZN8CtorDtorD1Ev, ptr %[[GET_GLOB]], ptr @__dso_handle) |
| // OGCG: call i32 @__cxa_thread_atexit(ptr @_ZN8CtorDtorD1Ev, ptr @tls_cd_dyn, ptr @__dso_handle) |
| // LLVM-BOTH: ret void |
| |
| thread_local CtorDtor &tls_cd_ref = tls_cd_dyn; |
| // CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = ctor : !cir.ptr<!rec_CtorDtor> { |
| // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> |
| // CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor>, !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // CIR-BEFORE-LPP: } |
| // CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = #cir.ptr<null> : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.func internal private @[[TLS_CD_REF_INIT]]() { |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // CIR: %[[GET_DYN:.*]] = cir.call @_ZTW10tls_cd_dyn() : () -> !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.store align(8) %[[GET_DYN]], %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor>, !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // CIR: cir.return |
| // |
| // LLVM: define internal void @[[TLS_CD_REF_INIT]]() { |
| // OGCG: define internal void @[[TLS_CD_REF_INIT:.*]]() {{.*}} { |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_ref) |
| // LLVM-BOTH: %[[CALL:.*]] = call ptr @_ZTW10tls_cd_dyn() |
| // OGCG: %[[GET_GLOB:.*]] = call {{.*}}ptr @llvm.threadlocal.address.p0(ptr {{.*}}@tls_cd_ref) |
| // LLVM-BOTH: store ptr %[[CALL]], ptr %[[GET_GLOB]], align 8 |
| // LLVM-BOTH: ret void |
| // |
| // OGCG: define weak_odr hidden noundef ptr @_ZTW10tls_cd_dyn() {{.*}} comdat { |
| // OGCG: call void @_ZTH10tls_cd_dyn() |
| // OGCG: %[[GET_GLOB:.*]] = call {{.*}}ptr @llvm.threadlocal.address.p0(ptr {{.*}}@tls_cd_dyn) |
| // OGCG: ret ptr %[[GET_GLOB]] |
| // OGCG: } |
| |
| thread_local CtorDtor tls_cd_dyn_not_used = get_i(); |
| // CIR-BEFORE-LPP: cir.global external tls_dyn dyn_tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = ctor : !rec_CtorDtor { |
| // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> |
| // CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) |
| // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) |
| // CIR-BEFORE-LPP: } dtor { |
| // CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> |
| // CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorD1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_CtorDtor>) -> () |
| // CIR-BEFORE-LPP: } |
| // CIR: cir.global external tls_dyn dyn_tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = #cir.zero : !rec_CtorDtor |
| // CIR: cir.func internal private @[[TLS_CD_DYN_NOT_USED_INIT]]() { |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> |
| // CIR: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef}) |
| // CIR: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) |
| // CIR: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor> |
| // CIR: %[[GET_DTOR:.*]] = cir.get_global @_ZN8CtorDtorD1Ev : !cir.ptr<!cir.func<(!cir.ptr<!rec_CtorDtor>)>> |
| // CIR: %[[DTOR_DECAY:.*]] = cir.cast bitcast %[[GET_DTOR]] : !cir.ptr<!cir.func<(!cir.ptr<!rec_CtorDtor>)>> -> !cir.ptr<!cir.func<(!cir.ptr<!void>)>> |
| // CIR: %[[GLOB_DECAY:.*]] = cir.cast bitcast %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor> -> !cir.ptr<!void> |
| // CIR: %[[DSOHANDLE:.*]] = cir.get_global @__dso_handle : !cir.ptr<i8> |
| // CIR: cir.call @__cxa_thread_atexit(%[[DTOR_DECAY]], %[[GLOB_DECAY]], %[[DSOHANDLE]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>)>>, !cir.ptr<!void>, !cir.ptr<i8>) -> !s32i |
| // CIR: cir.return |
| // |
| // LLVM: define internal void @[[TLS_CD_DYN_NOT_USED_INIT]]() { |
| // OGCG: define internal void @[[TLS_CD_DYN_NOT_USED_INIT:.*]]() {{.*}} { |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn_not_used) |
| // LLVM-BOTH: %[[CALL:.*]] = call noundef i32 @_Z5get_iv() |
| // LLVM: call void @_ZN8CtorDtorC1Ei(ptr {{.*}}%[[GET_GLOB]], i32 {{.*}}%[[CALL]]) |
| // OGCG: call void @_ZN8CtorDtorC1Ei(ptr {{.*}}@tls_cd_dyn_not_used, i32 {{.*}}%[[CALL]]) |
| // LLVM: %[[GET_GLOB:.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls_cd_dyn_not_used) |
| // LLVM: call i32 @__cxa_thread_atexit(ptr @_ZN8CtorDtorD1Ev, ptr %[[GET_GLOB]], ptr @__dso_handle) |
| // OGCG: call i32 @__cxa_thread_atexit(ptr @_ZN8CtorDtorD1Ev, ptr @tls_cd_dyn_not_used, ptr @__dso_handle) |
| // LLVM-BOTH: ret void |
| |
| void uses() { |
| auto a = tls_cd; |
| // CIR-BEFORE-LPP: cir.get_global thread_local @tls_cd : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.call @_ZTW6tls_cd() : () -> !cir.ptr<!rec_CtorDtor> |
| // LLVM-BOTH: call ptr @_ZTW6tls_cd() |
| auto b = tls_cd_dyn; |
| // CIR-BEFORE-LPP: cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor> |
| // CIR: cir.call @_ZTW10tls_cd_dyn() : () -> !cir.ptr<!rec_CtorDtor> |
| // LLVM-BOTH: call ptr @_ZTW10tls_cd_dyn() |
| auto c = tls_cd_ref; |
| // CIR-BEFORE-LPP: cir.get_global thread_local @tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // CIR: cir.call @_ZTW10tls_cd_ref() : () -> !cir.ptr<!cir.ptr<!rec_CtorDtor>> |
| // LLVM-BOTH: call ptr @_ZTW10tls_cd_ref() |
| } |
| |
| // OGCG: define weak_odr hidden noundef ptr @_ZTW6tls_cd() {{.*}} comdat { |
| // OGCG: call void @_ZTH6tls_cd() |
| // OGCG: %[[GET_GLOB:.*]] = call {{.*}}ptr @llvm.threadlocal.address.p0(ptr {{.*}}@tls_cd) |
| // OGCG: ret ptr %[[GET_GLOB]] |
| // OGCG: } |
| // |
| // OGCG: define weak_odr hidden noundef ptr @_ZTW10tls_cd_ref() {{.*}} comdat { |
| // OGCG: call void @_ZTH10tls_cd_ref() |
| // OGCG: %[[GET_GLOB:.*]] = call {{.*}}ptr @llvm.threadlocal.address.p0(ptr {{.*}}@tls_cd_ref) |
| // OGCG: %[[LOAD_GLOB:.*]] = load ptr, ptr %[[GET_GLOB]], align 8 |
| // OGCG: ret ptr %[[LOAD_GLOB]] |
| // OGCG: } |
| // |
| // OGCG: define internal void @__tls_init() {{.*}} { |
| // OGCG: %[[GET_GUARD:.*]] = load i8, ptr @__tls_guard, align 1 |
| // OGCG: %[[IS_UNINIT:.*]] = icmp eq i8 %[[GET_GUARD]], 0 |
| // OGCG: br i1 %[[IS_UNINIT]] |
| // OGCG |
| // OGCG: store i8 1, ptr @__tls_guard, align 1 |
| // OGCG: call void @[[TLS_CD_INIT]]() |
| // OGCG: call void @[[TLS_CD_DYN_INIT]]() |
| // OGCG: call void @[[TLS_CD_REF_INIT]]() |
| // OGCG: call void @[[TLS_CD_DYN_NOT_USED_INIT]]() |
| // |
| // OGCG: define weak_odr hidden noundef ptr @_ZTW19tls_cd_dyn_not_used() {{.*}} comdat { |
| // OGCG: call void @_ZTH19tls_cd_dyn_not_used() |
| // OGCG: %[[GET_GLOB:.*]] = call {{.*}} ptr @llvm.threadlocal.address.p0(ptr {{.*}} @tls_cd_dyn_not_used) |
| // OGCG: ret ptr %[[GET_GLOB]] |
| // OGCG: } |
| // |