[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 25 06:08:21 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-codegen
Author: None (nikola-tesic-ns)
<details>
<summary>Changes</summary>
This patch fixes compiler generated code in `tls_init` function to access TLS variable (`tls_guard`) via llvm.threadlocal.address intrinsic.
Related discussion:
https://discourse.llvm.org/t/address-thread-identification-problems-with-coroutine/62015/57?u=ntesic
---
Full diff: https://github.com/llvm/llvm-project/pull/96633.diff
6 Files Affected:
- (modified) clang/lib/CodeGen/CGDeclCXX.cpp (+19-10)
- (modified) clang/test/CodeGenCXX/cxx11-thread-local.cpp (+6-3)
- (modified) clang/test/CodeGenCXX/static-initializer-branch-weights.cpp (+2-1)
- (modified) clang/test/OpenMP/parallel_copyin_codegen.cpp (+4-2)
- (modified) clang/test/OpenMP/target_has_device_addr_codegen.cpp (+4-2)
- (modified) clang/test/OpenMP/threadprivate_codegen.cpp (+20-10)
``````````diff
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index e18b339b31d24..0663a083bf3e8 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -1059,9 +1059,10 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
if (Guard.isValid()) {
// If we have a guard variable, check whether we've already performed
// these initializations. This happens for TLS initialization functions.
- llvm::Value *GuardVal = Builder.CreateLoad(Guard);
- llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,
- "guard.uninitialized");
+ llvm::Value *GuardVal = EmitLoadOfScalar(
+ MakeAddrLValue(Guard, getContext().IntTy), SourceLocation());
+ llvm::Value *Uninit =
+ Builder.CreateIsNull(GuardVal, "guard.uninitialized");
llvm::BasicBlock *InitBlock = createBasicBlock("init");
ExitBlock = createBasicBlock("exit");
EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock,
@@ -1070,13 +1071,21 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
// Mark as initialized before initializing anything else. If the
// initializers use previously-initialized thread_local vars, that's
// probably supposed to be OK, but the standard doesn't say.
- Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
-
- // The guard variable can't ever change again.
- EmitInvariantStart(
- Guard.getPointer(),
- CharUnits::fromQuantity(
- CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())));
+ EmitStoreOfScalar(llvm::ConstantInt::get(GuardVal->getType(), 1),
+ MakeAddrLValue(Guard, getContext().IntTy));
+
+ // Emit invariant start for TLS guard address.
+ if (CGM.getCodeGenOpts().OptimizationLevel > 0) {
+ uint64_t Width =
+ CGM.getDataLayout().getTypeAllocSize(GuardVal->getType());
+ llvm::Value *TLSAddr = Guard.getPointer();
+ // Get the thread-local address via intrinsic.
+ if (auto *GV = dyn_cast<llvm::GlobalValue>(Guard.getPointer()))
+ if (GV->isThreadLocal())
+ TLSAddr = Builder.CreateThreadLocalAddress(Guard.getPointer());
+ Builder.CreateInvariantStart(
+ TLSAddr, llvm::ConstantInt::getSigned(Int64Ty, Width));
+ }
}
RunCleanupsScope Scope(*this);
diff --git a/clang/test/CodeGenCXX/cxx11-thread-local.cpp b/clang/test/CodeGenCXX/cxx11-thread-local.cpp
index bcc490bc32e6e..e9a0799cf8d9a 100644
--- a/clang/test/CodeGenCXX/cxx11-thread-local.cpp
+++ b/clang/test/CodeGenCXX/cxx11-thread-local.cpp
@@ -358,12 +358,15 @@ void set_anon_i() {
// CHECK: define {{.*}}@__tls_init()
-// CHECK: load i8, ptr @__tls_guard
+// CHECK: [[TLS_GUARD_ADDR_1:%.+]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK: load i8, ptr [[TLS_GUARD_ADDR_1]]
// CHECK: %[[NEED_TLS_INIT:.*]] = icmp eq i8 %{{.*}}, 0
// CHECK: br i1 %[[NEED_TLS_INIT]],
// init:
-// CHECK: store i8 1, ptr @__tls_guard
-// CHECK-OPT: call ptr @llvm.invariant.start.p0(i64 1, ptr @__tls_guard)
+// CHECK: [[TLS_GUARD_ADDR_2:%.+]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK: store i8 1, ptr [[TLS_GUARD_ADDR_2]]
+// CHECK-OPT: [[TLS_GUARD_ADDR_3:%.+]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-OPT: call ptr @llvm.invariant.start.p0(i64 1, ptr [[TLS_GUARD_ADDR_3]])
// CHECK-NOT: call void @[[V_M_INIT]]()
// CHECK: call void @[[A_INIT]]()
// CHECK-NOT: call void @[[V_M_INIT]]()
diff --git a/clang/test/CodeGenCXX/static-initializer-branch-weights.cpp b/clang/test/CodeGenCXX/static-initializer-branch-weights.cpp
index 121b9b2029959..e855f54643eae 100644
--- a/clang/test/CodeGenCXX/static-initializer-branch-weights.cpp
+++ b/clang/test/CodeGenCXX/static-initializer-branch-weights.cpp
@@ -118,7 +118,8 @@ void use_b() {
}
// CHECK-LABEL: define {{.*}}tls_init()
-// CHECK: load i8, ptr @__tls_guard, align 1
+// CHECK: [[TLS_GUARD_ADDR:%.+]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK: load i8, ptr [[TLS_GUARD_ADDR]], align 1
// CHECK: icmp eq i8 {{.*}}, 0
// CHECK: br i1 {{.*}}, !prof ![[WEIGHTS_THREAD_LOCAL]]
diff --git a/clang/test/OpenMP/parallel_copyin_codegen.cpp b/clang/test/OpenMP/parallel_copyin_codegen.cpp
index e653a7734161b..aa2ea78c4fe09 100644
--- a/clang/test/OpenMP/parallel_copyin_codegen.cpp
+++ b/clang/test/OpenMP/parallel_copyin_codegen.cpp
@@ -1760,11 +1760,13 @@ void foo() {
// CHECK16-LABEL: define {{[^@]+}}@__tls_init
// CHECK16-SAME: () #[[ATTR0]] {
// CHECK16-NEXT: entry:
-// CHECK16-NEXT: [[TMP0:%.*]] = load i8, ptr @__tls_guard, align 1
+// CHECK16-NEXT: [[TLS_ADR_1:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK16-NEXT: [[TMP0:%.*]] = load i8, ptr [[TLS_ADR_1]], align 1
// CHECK16-NEXT: [[GUARD_UNINITIALIZED:%.*]] = icmp eq i8 [[TMP0]], 0
// CHECK16-NEXT: br i1 [[GUARD_UNINITIALIZED]], label [[INIT:%.*]], label [[EXIT:%.*]], !prof [[PROF5:![0-9]+]]
// CHECK16: init:
-// CHECK16-NEXT: store i8 1, ptr @__tls_guard, align 1
+// CHECK16-NEXT: [[TLS_ADR_2:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK16-NEXT: store i8 1, ptr [[TLS_ADR_2]], align 1
// CHECK16-NEXT: call void @__cxx_global_var_init()
// CHECK16-NEXT: br label [[EXIT]]
// CHECK16: exit:
diff --git a/clang/test/OpenMP/target_has_device_addr_codegen.cpp b/clang/test/OpenMP/target_has_device_addr_codegen.cpp
index ba1b618ed8bdd..71dd92eb9fe48 100644
--- a/clang/test/OpenMP/target_has_device_addr_codegen.cpp
+++ b/clang/test/OpenMP/target_has_device_addr_codegen.cpp
@@ -1304,11 +1304,13 @@ void use_template() {
// CHECK-LABEL: define {{[^@]+}}@__tls_init
// CHECK-SAME: () #[[ATTR0]] {
// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr @__tls_guard, align 1
+// CHECK-NEXT: [[TLS_ADR_1:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TLS_ADR_1]], align 1
// CHECK-NEXT: [[GUARD_UNINITIALIZED:%.*]] = icmp eq i8 [[TMP0]], 0
// CHECK-NEXT: br i1 [[GUARD_UNINITIALIZED]], label [[INIT:%.*]], label [[EXIT:%.*]], !prof [[PROF18:![0-9]+]]
// CHECK: init:
-// CHECK-NEXT: store i8 1, ptr @__tls_guard, align 1
+// CHECK-NEXT: [[TLS_ADR_2:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-NEXT: store i8 1, ptr [[TLS_ADR_2]], align 1
// CHECK-NEXT: call void @__cxx_global_var_init.4()
// CHECK-NEXT: br label [[EXIT]]
// CHECK: exit:
diff --git a/clang/test/OpenMP/threadprivate_codegen.cpp b/clang/test/OpenMP/threadprivate_codegen.cpp
index b5eb4651d6c33..2dbdfc5eb6095 100644
--- a/clang/test/OpenMP/threadprivate_codegen.cpp
+++ b/clang/test/OpenMP/threadprivate_codegen.cpp
@@ -958,11 +958,13 @@ int foobar() {
// OMP50-TLS: define {{.*}}void [[ST_S4_ST_DTOR2]](ptr {{.*}})
// CHECK-TLS: define internal void @__tls_init()
-// CHECK-TLS: [[GRD:%.*]] = load i8, ptr @__tls_guard
+// CHECK-TLS: [[TLS_ADR_1:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS-NEXT: [[GRD:%.*]] = load i8, ptr [[TLS_ADR_1]]
// CHECK-TLS-NEXT: [[IS_INIT:%.*]] = icmp eq i8 [[GRD]], 0
// CHECK-TLS-NEXT: br i1 [[IS_INIT]], label %[[INIT_LABEL:[^,]+]], label %[[DONE_LABEL:[^,]+]]{{.*}}
// CHECK-TLS: [[INIT_LABEL]]
-// CHECK-TLS-NEXT: store i8 1, ptr @__tls_guard
+// CHECK-TLS-NEXT: [[TLS_ADR_2:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS-NEXT: store i8 1, ptr [[TLS_ADR_2]]
// CHECK-TLS: call void [[GS1_CXX_INIT]]
// CHECK-TLS-NOT: call void [[GS2_CXX_INIT]]
// CHECK-TLS: call void [[ARR_X_CXX_INIT]]
@@ -3829,11 +3831,13 @@ int foobar() {
// CHECK-TLS1-LABEL: define {{[^@]+}}@__tls_init
// CHECK-TLS1-SAME: () #[[ATTR0]] {
// CHECK-TLS1-NEXT: entry:
-// CHECK-TLS1-NEXT: [[TMP0:%.*]] = load i8, ptr @__tls_guard, align 1
+// CHECK-TLS1-NEXT: [[TLS_ADR_3:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS1-NEXT: [[TMP0:%.*]] = load i8, ptr [[TLS_ADR_3]], align 1
// CHECK-TLS1-NEXT: [[GUARD_UNINITIALIZED:%.*]] = icmp eq i8 [[TMP0]], 0
// CHECK-TLS1-NEXT: br i1 [[GUARD_UNINITIALIZED]], label [[INIT:%.*]], label [[EXIT:%.*]], !prof [[PROF3]]
// CHECK-TLS1: init:
-// CHECK-TLS1-NEXT: store i8 1, ptr @__tls_guard, align 1
+// CHECK-TLS1-NEXT: [[TLS_ADR_4:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS1-NEXT: store i8 1, ptr [[TLS_ADR_4]], align 1
// CHECK-TLS1-NEXT: call void @__cxx_global_var_init()
// CHECK-TLS1-NEXT: call void @__cxx_global_var_init.2()
// CHECK-TLS1-NEXT: br label [[EXIT]]
@@ -4366,11 +4370,13 @@ int foobar() {
// CHECK-TLS2-LABEL: define {{[^@]+}}@__tls_init
// CHECK-TLS2-SAME: () #[[ATTR6]] {
// CHECK-TLS2-NEXT: entry:
-// CHECK-TLS2-NEXT: [[TMP0:%.*]] = load i8, ptr @__tls_guard, align 1
+// CHECK-TLS2-NEXT: [[TLS_ADR_5:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS2-NEXT: [[TMP0:%.*]] = load i8, ptr [[TLS_ADR_5]], align 1
// CHECK-TLS2-NEXT: [[GUARD_UNINITIALIZED:%.*]] = icmp eq i8 [[TMP0]], 0
// CHECK-TLS2-NEXT: br i1 [[GUARD_UNINITIALIZED]], label [[INIT:%.*]], label [[EXIT:%.*]], !prof [[PROF3]]
// CHECK-TLS2: init:
-// CHECK-TLS2-NEXT: store i8 1, ptr @__tls_guard, align 1
+// CHECK-TLS2-NEXT: [[TLS_ADR_6:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS2-NEXT: store i8 1, ptr [[TLS_ADR_6]], align 1
// CHECK-TLS2-NEXT: call void @__cxx_global_var_init()
// CHECK-TLS2-NEXT: call void @__cxx_global_var_init.2()
// CHECK-TLS2-NEXT: br label [[EXIT]]
@@ -4918,11 +4924,13 @@ int foobar() {
// CHECK-TLS3-LABEL: define {{[^@]+}}@__tls_init
// CHECK-TLS3-SAME: () #[[ATTR0]] !dbg [[DBG326:![0-9]+]] {
// CHECK-TLS3-NEXT: entry:
-// CHECK-TLS3-NEXT: [[TMP0:%.*]] = load i8, ptr @__tls_guard, align 1, !dbg [[DBG327:![0-9]+]]
+// CHECK-TLS3-NEXT: [[TLS_ADR_7:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS3-NEXT: [[TMP0:%.*]] = load i8, ptr [[TLS_ADR_7]], align 1, !dbg [[DBG327:![0-9]+]]
// CHECK-TLS3-NEXT: [[GUARD_UNINITIALIZED:%.*]] = icmp eq i8 [[TMP0]], 0, !dbg [[DBG327]]
// CHECK-TLS3-NEXT: br i1 [[GUARD_UNINITIALIZED]], label [[INIT:%.*]], label [[EXIT:%.*]], !dbg [[DBG327]], !prof [[PROF206]]
// CHECK-TLS3: init:
-// CHECK-TLS3-NEXT: store i8 1, ptr @__tls_guard, align 1, !dbg [[DBG327]]
+// CHECK-TLS3-NEXT: [[TLS_ADR_8:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS3-NEXT: store i8 1, ptr [[TLS_ADR_8]], align 1, !dbg [[DBG327]]
// CHECK-TLS3-NEXT: call void @__cxx_global_var_init(), !dbg [[DBG327]]
// CHECK-TLS3-NEXT: call void @__cxx_global_var_init.2(), !dbg [[DBG327]]
// CHECK-TLS3-NEXT: br label [[EXIT]], !dbg [[DBG327]]
@@ -5482,11 +5490,13 @@ int foobar() {
// CHECK-TLS4-LABEL: define {{[^@]+}}@__tls_init
// CHECK-TLS4-SAME: () #[[ATTR6]] !dbg [[DBG326:![0-9]+]] {
// CHECK-TLS4-NEXT: entry:
-// CHECK-TLS4-NEXT: [[TMP0:%.*]] = load i8, ptr @__tls_guard, align 1, !dbg [[DBG327:![0-9]+]]
+// CHECK-TLS4-NEXT: [[TLS_ADR_9:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS4-NEXT: [[TMP0:%.*]] = load i8, ptr [[TLS_ADR_9]], align 1, !dbg [[DBG327:![0-9]+]]
// CHECK-TLS4-NEXT: [[GUARD_UNINITIALIZED:%.*]] = icmp eq i8 [[TMP0]], 0, !dbg [[DBG327]]
// CHECK-TLS4-NEXT: br i1 [[GUARD_UNINITIALIZED]], label [[INIT:%.*]], label [[EXIT:%.*]], !dbg [[DBG327]], !prof [[PROF119]]
// CHECK-TLS4: init:
-// CHECK-TLS4-NEXT: store i8 1, ptr @__tls_guard, align 1, !dbg [[DBG327]]
+// CHECK-TLS4-NEXT: [[TLS_ADR_10:%.*]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @__tls_guard)
+// CHECK-TLS4-NEXT: store i8 1, ptr [[TLS_ADR_10]], align 1, !dbg [[DBG327]]
// CHECK-TLS4-NEXT: call void @__cxx_global_var_init(), !dbg [[DBG327]]
// CHECK-TLS4-NEXT: call void @__cxx_global_var_init.2(), !dbg [[DBG327]]
// CHECK-TLS4-NEXT: br label [[EXIT]], !dbg [[DBG327]]
``````````
</details>
https://github.com/llvm/llvm-project/pull/96633
More information about the cfe-commits
mailing list