[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-25 Thread via cfe-commits

https://github.com/nikola-tesic-ns created 
https://github.com/llvm/llvm-project/pull/96633

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

>From 41427a3de345517025477257bfd4f614f06cbcfe Mon Sep 17 00:00:00 2001
From: Nikola Tesic 
Date: Tue, 25 Jun 2024 15:58:18 +0300
Subject: [PATCH] [Clang] Access tls_guard via llvm.threadlocal.address

This patch fixes compiler generated code in `tls_init` function to access
TLS variable (`tls_guard`) via llvm.threadlocal.address intrinsic.
---
 clang/lib/CodeGen/CGDeclCXX.cpp   | 29 +++---
 clang/test/CodeGenCXX/cxx11-thread-local.cpp  |  9 --
 .../static-initializer-branch-weights.cpp |  3 +-
 clang/test/OpenMP/parallel_copyin_codegen.cpp |  6 ++--
 .../OpenMP/target_has_device_addr_codegen.cpp |  6 ++--
 clang/test/OpenMP/threadprivate_codegen.cpp   | 30 ---
 6 files changed, 55 insertions(+), 28 deletions(-)

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(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/Code

[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-25 Thread via cfe-commits

github-actions[bot] wrote:



Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from 
other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-25 Thread via cfe-commits

llvmbot wrote:



@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: None (nikola-tesic-ns)


Changes

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(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_g

[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-25 Thread via cfe-commits

nikola-tesic-ns wrote:

@nikic @ChuanqiXu9 
I couldn't add you to the reviewers list. Please, take a look at this fix. 
Thanks!

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-25 Thread Chuanqi Xu via cfe-commits


@@ -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());

ChuanqiXu9 wrote:

I am slightly not happy with the use of `MakeAddrLValue` since the term 
`LValue` is a language concept in my mind and here are some codes for 
implementing details for the language to me. I may feel better to implement 
this with the `CreateThreadLocalAddress` API directly.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread via cfe-commits

https://github.com/nikola-tesic-ns updated 
https://github.com/llvm/llvm-project/pull/96633

>From 41427a3de345517025477257bfd4f614f06cbcfe Mon Sep 17 00:00:00 2001
From: Nikola Tesic 
Date: Tue, 25 Jun 2024 15:58:18 +0300
Subject: [PATCH 1/2] [Clang] Access tls_guard via llvm.threadlocal.address

This patch fixes compiler generated code in `tls_init` function to access
TLS variable (`tls_guard`) via llvm.threadlocal.address intrinsic.
---
 clang/lib/CodeGen/CGDeclCXX.cpp   | 29 +++---
 clang/test/CodeGenCXX/cxx11-thread-local.cpp  |  9 --
 .../static-initializer-branch-weights.cpp |  3 +-
 clang/test/OpenMP/parallel_copyin_codegen.cpp |  6 ++--
 .../OpenMP/target_has_device_addr_codegen.cpp |  6 ++--
 clang/test/OpenMP/threadprivate_codegen.cpp   | 30 ---
 6 files changed, 55 insertions(+), 28 deletions(-)

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(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_

[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread via cfe-commits


@@ -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());

nikola-tesic-ns wrote:

Makes sense, thanks.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread Chuanqi Xu via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;

ChuanqiXu9 wrote:

It looks like the change can be simpler if we don't introduce new the  variable 
`GuardAddr`, is it?

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread Chuanqi Xu via cfe-commits


@@ -1070,13 +1076,26 @@ 
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(;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())

ChuanqiXu9 wrote:

ditto

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread Chuanqi Xu via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())
+  GuardAddr = GuardAddr.withPointer(
+  Builder.CreateThreadLocalAddress(GV), NotKnownNonNull);
+  llvm::Value *GuardVal = Builder.CreateLoad(GuardAddr);

ChuanqiXu9 wrote:

These lines are not changed. So we'd better to not touch them.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread Chuanqi Xu via cfe-commits


@@ -1070,13 +1076,26 @@ 
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(;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())
+  GuardAddr = GuardAddr.withPointer(
+  Builder.CreateThreadLocalAddress(GV), NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // 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();
+if (auto *GV = dyn_cast(Guard.getPointer()))
+  // Get the thread-local address via intrinsic.
+  if (GV->isThreadLocal())
+TLSAddr = Builder.CreateThreadLocalAddress(GV);
+Builder.CreateInvariantStart(

ChuanqiXu9 wrote:

Why do the ABI used change?  And is it necessary? If not, can we remove it?

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread Chuanqi Xu via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())

ChuanqiXu9 wrote:

```suggestion
  // Get the thread-local address via intrinsic.
  if (auto *GV = dyn_cast(Guard.getPointer());
   GV && GV->isThreadLocal())
```

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-26 Thread John McCall via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;
+  if (auto *GV = dyn_cast(Guard.getPointer()))

rjmccall wrote:

We need to do this unconditionally, and we should be able to do because `Guard` 
is a constant address.  But if there's some code pattern where that's not true, 
we need to fix that code pattern rather than silently just not using this 
intrinsic.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-27 Thread via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;

nikola-tesic-ns wrote:

The `Guard` is a `ConstantAddress`, so I cannot change it, that's why I 
introduced new variable. If you have some suggestion, I would be happy to adapt 
the code.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-27 Thread via cfe-commits


@@ -1070,13 +1076,26 @@ 
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(;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())
+  GuardAddr = GuardAddr.withPointer(
+  Builder.CreateThreadLocalAddress(GV), NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // 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();
+if (auto *GV = dyn_cast(Guard.getPointer()))
+  // Get the thread-local address via intrinsic.
+  if (GV->isThreadLocal())
+TLSAddr = Builder.CreateThreadLocalAddress(GV);
+Builder.CreateInvariantStart(

nikola-tesic-ns wrote:

I am not sure I understood this, sorry.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-27 Thread via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;
+  if (auto *GV = dyn_cast(Guard.getPointer()))

nikola-tesic-ns wrote:

There is a code pattern where this "guarded initialization" is done for non-TLS 
var ([partitions.cpp 
test](https://github.com/nextsilicon/next-llvm-project/blob/b36811cc9baf1c72de2fa1c8b5d8fc30bae9a15c/clang/test/CodeGenCXX/partitions.cpp)).
 That's the reason I've introduced these checks.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-27 Thread Chuanqi Xu via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;

ChuanqiXu9 wrote:

OK, I didn't look into the context.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-27 Thread Chuanqi Xu via cfe-commits


@@ -1070,13 +1076,26 @@ 
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(;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())
+  GuardAddr = GuardAddr.withPointer(
+  Builder.CreateThreadLocalAddress(GV), NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // 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();
+if (auto *GV = dyn_cast(Guard.getPointer()))
+  // Get the thread-local address via intrinsic.
+  if (GV->isThreadLocal())
+TLSAddr = Builder.CreateThreadLocalAddress(GV);
+Builder.CreateInvariantStart(

ChuanqiXu9 wrote:

I mean, it used  `EmitInvariantStart` but now it uses  `CreateInvariantStart`. 
(Sorry, I meant to use API)

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-27 Thread via cfe-commits


@@ -1070,13 +1076,26 @@ 
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(;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())
+  GuardAddr = GuardAddr.withPointer(
+  Builder.CreateThreadLocalAddress(GV), NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // 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();
+if (auto *GV = dyn_cast(Guard.getPointer()))
+  // Get the thread-local address via intrinsic.
+  if (GV->isThreadLocal())
+TLSAddr = Builder.CreateThreadLocalAddress(GV);
+Builder.CreateInvariantStart(

nikola-tesic-ns wrote:

Ok, well `EmitInvariantStart` expects Constant value, which `TLSAddr` cannot be 
if we are going to set it conditionally. (But maybe it should be 
unconditionally)

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-06-27 Thread John McCall via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;
+  if (auto *GV = dyn_cast(Guard.getPointer()))

rjmccall wrote:

Then you should pass down whether this is for TLS.

What I'm trying to avoid is some situation where we silently don't emit the 
intrinsic for a thread local because the guard address we pass in is not 
directly a `GlobalValue`.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread via cfe-commits

https://github.com/nikola-tesic-ns updated 
https://github.com/llvm/llvm-project/pull/96633

>From 41427a3de345517025477257bfd4f614f06cbcfe Mon Sep 17 00:00:00 2001
From: Nikola Tesic 
Date: Tue, 25 Jun 2024 15:58:18 +0300
Subject: [PATCH 1/3] [Clang] Access tls_guard via llvm.threadlocal.address

This patch fixes compiler generated code in `tls_init` function to access
TLS variable (`tls_guard`) via llvm.threadlocal.address intrinsic.
---
 clang/lib/CodeGen/CGDeclCXX.cpp   | 29 +++---
 clang/test/CodeGenCXX/cxx11-thread-local.cpp  |  9 --
 .../static-initializer-branch-weights.cpp |  3 +-
 clang/test/OpenMP/parallel_copyin_codegen.cpp |  6 ++--
 .../OpenMP/target_has_device_addr_codegen.cpp |  6 ++--
 clang/test/OpenMP/threadprivate_codegen.cpp   | 30 ---
 6 files changed, 55 insertions(+), 28 deletions(-)

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(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_

[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;
+  if (auto *GV = dyn_cast(Guard.getPointer()))

nikola-tesic-ns wrote:

I've added changes to pass down `IsTLS` flag from the point where variable is 
created. That should ensure we always emit TLS intrinsic.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread via cfe-commits


@@ -1059,9 +1059,15 @@ 
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");
+  Address GuardAddr = Guard;
+  if (auto *GV = dyn_cast(Guard.getPointer()))
+// Get the thread-local address via intrinsic.
+if (GV->isThreadLocal())
+  GuardAddr = GuardAddr.withPointer(
+  Builder.CreateThreadLocalAddress(GV), NotKnownNonNull);
+  llvm::Value *GuardVal = Builder.CreateLoad(GuardAddr);

nikola-tesic-ns wrote:

I think this is related to the conversation in the other comment
> The Guard is a ConstantAddress, so I cannot change it, that's why I 
> introduced new variable. If you have some suggestion, I would be happy to 
> adapt the code.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread via cfe-commits

https://github.com/nikola-tesic-ns edited 
https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread John McCall via cfe-commits


@@ -769,9 +777,10 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) 
{
   CharUnits GuardAlign = CharUnits::One();
   Guard->setAlignment(GuardAlign.getAsAlign());
   GuardAddr = ConstantAddress(Guard, Int8Ty, GuardAlign);
+  IsTLS = Guard->isThreadLocal();
 }
-CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits,
- GuardAddr);
+CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits, 
GuardAddr,
+ IsTLS);

rjmccall wrote:

```suggestion
 /*IsTLS*/ false);
```

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread John McCall via cfe-commits


@@ -769,9 +777,10 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) 
{
   CharUnits GuardAlign = CharUnits::One();
   Guard->setAlignment(GuardAlign.getAsAlign());
   GuardAddr = ConstantAddress(Guard, Int8Ty, GuardAlign);
+  IsTLS = Guard->isThreadLocal();

rjmccall wrote:

This is always just `false`.  And I believe that's correct, module 
initialization is global, not thread-local.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread John McCall via cfe-commits


@@ -1070,13 +1084,20 @@ 
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.
+  // Get the thread-local address via intrinsic.
+  if (IsTLS)
+GuardAddr = GuardAddr.withPointer(
+Builder.CreateThreadLocalAddress(Guard.getPointer()),
+NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // Emit invariant start for TLS guard address.
   EmitInvariantStart(
   Guard.getPointer(),
   CharUnits::fromQuantity(
-  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType(;
+  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())),
+  IsTLS);

rjmccall wrote:

Just use `GuardAddr` here, please, instead of passing a flag down.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-03 Thread John McCall via cfe-commits


@@ -2933,7 +2933,8 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
 Guard->setAlignment(GuardAlign.getAsAlign());
 
 CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(
-InitFunc, OrderedInits, ConstantAddress(Guard, CGM.Int8Ty, 
GuardAlign));
+InitFunc, OrderedInits, ConstantAddress(Guard, CGM.Int8Ty, GuardAlign),
+Guard->isThreadLocal());

rjmccall wrote:

```suggestion
/*IsTLS*/ true);
```

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-04 Thread via cfe-commits


@@ -1070,13 +1084,20 @@ 
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.
+  // Get the thread-local address via intrinsic.
+  if (IsTLS)
+GuardAddr = GuardAddr.withPointer(
+Builder.CreateThreadLocalAddress(Guard.getPointer()),
+NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // Emit invariant start for TLS guard address.
   EmitInvariantStart(
   Guard.getPointer(),
   CharUnits::fromQuantity(
-  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType(;
+  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())),
+  IsTLS);

nikola-tesic-ns wrote:

Am I allowed to reuse TLS address for invariant start intrinsic (example 1), or 
I need to access via intrinsic each time (example 2)? If the latter is true, I 
would need to recalculate the `GuardAddr` again.
example 1:
```
   %tls_addr1 = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 
@__tls_guard)
   store i8 1, ptr %tls_addr1, align 1
   %3 = call ptr @llvm.invariant.start.p0(i64 1, ptr %tls_addr1)
```
example 2:
```
  %tls_addr1 = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 
@__tls_guard)
  store i8 1, ptr %tls_addr1, align 1
  %tls_addr2 = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 
@__tls_guard)
  %4 = call ptr @llvm.invariant.start.p0(i64 1, ptr %tls_addr2)
```

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-05 Thread John McCall via cfe-commits


@@ -1070,13 +1084,20 @@ 
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.
+  // Get the thread-local address via intrinsic.
+  if (IsTLS)
+GuardAddr = GuardAddr.withPointer(
+Builder.CreateThreadLocalAddress(Guard.getPointer()),
+NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // Emit invariant start for TLS guard address.
   EmitInvariantStart(
   Guard.getPointer(),
   CharUnits::fromQuantity(
-  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType(;
+  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())),
+  IsTLS);

rjmccall wrote:

Yes, and in fact, sometimes that's required.  The way I think about it is that 
`threadlocal.address` is a real dynamic operation that resolves the address of 
the thread-local variable for a specific thread: namely, the current thread at 
the execution point where `threadlocal.address` appears. When we're doing a 
complicated operation on a specific thread-local variable, it's important to 
call `threadlocal.address` at the right point and then use that result 
throughout the operation.  Otherwise, a suspension in the middle of the 
operation will leave us working on a different thread-local variable at 
different points in the operation, which is not semantically allowed.

In this case, we initialize a thread-local variable and then enter an invariant 
region for it.  We need this to:
1. resolve the address of the TLV for the current thread, prior to performing 
any initialization;
2. initialize the TLV, which may include suspensions that change the current 
thread; and
3. enter an invariant region for the TLV we initialized, *not* the TLV for the 
new thread.  The new thread's TLV may not yet be in an invariant region.

Now, this may actually be moot, because I'm not sure it's actually allowed (or 
at least I'm not sure it *should* be allowed) to have a coroutine suspension in 
the middle of the initialization of a thread-local variable.  The interaction 
of thread-locals with coroutines that actually switch threads is deeply 
problematic; notably, the TLV for the new thread can actually be uninitialized 
when you go to use it.  I haven't checked what the standard says here, but 
honestly this might have to have undefined behavior, in which case we just need 
to make sure we generate reasonable code as long as the thread *doesn't* change.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-05 Thread via cfe-commits


@@ -1070,13 +1084,20 @@ 
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.
+  // Get the thread-local address via intrinsic.
+  if (IsTLS)
+GuardAddr = GuardAddr.withPointer(
+Builder.CreateThreadLocalAddress(Guard.getPointer()),
+NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // Emit invariant start for TLS guard address.
   EmitInvariantStart(
   Guard.getPointer(),
   CharUnits::fromQuantity(
-  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType(;
+  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())),
+  IsTLS);

nikola-tesic-ns wrote:

I had similar concerns. IIUC, the safe(st possible) bet is to generate 
`threadlocal.address` at each access. In the view of this PR:
1. for the load of `tls_guard`
2. for the store into `tls_guard`
3. for the `invariant.start` intrinsic for `tls_guard`

I am not sure if there is a case where coroutine context switch could happen 
between `threadlocal.address` and its user instruction. If that is the case, 
then there is no guarantee for other use cases of `threadlocal.address` as well.
Do you agree or I am missing something?

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-05 Thread John McCall via cfe-commits


@@ -1070,13 +1084,20 @@ 
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.
+  // Get the thread-local address via intrinsic.
+  if (IsTLS)
+GuardAddr = GuardAddr.withPointer(
+Builder.CreateThreadLocalAddress(Guard.getPointer()),
+NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // Emit invariant start for TLS guard address.
   EmitInvariantStart(
   Guard.getPointer(),
   CharUnits::fromQuantity(
-  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType(;
+  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())),
+  IsTLS);

rjmccall wrote:

That's exactly backwards — it is semantically incorrect to access different 
guard variables at different points during the initialization; that does not 
correctly implement the guard pattern.  Fortunately, I've been able to verify 
that it doesn't matter, because [expr.await]p3 says:

> An *await-expression* shall not appear in the initializer of a block variable 
> with static or thread storage duration.

Therefore, it is fine to just do a single use of `threadlocal.address`, and 
it's preferable because it's less code and likely easier to optimize.

(Unfortunately, this restriction doesn't completely eliminate the coherence 
problems with coroutines and `thread_local`.  In particular, a coroutine that 
declares a `thread_local` local variable can observe it in an uninitialized 
state if the thread has changed since the initialization, and I don't see 
anything in the standard that addresses this.)

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-05 Thread John McCall via cfe-commits

https://github.com/rjmccall edited 
https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-05 Thread John McCall via cfe-commits

https://github.com/rjmccall edited 
https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-08 Thread via cfe-commits


@@ -1070,13 +1084,20 @@ 
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.
+  // Get the thread-local address via intrinsic.
+  if (IsTLS)
+GuardAddr = GuardAddr.withPointer(
+Builder.CreateThreadLocalAddress(Guard.getPointer()),
+NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // Emit invariant start for TLS guard address.
   EmitInvariantStart(
   Guard.getPointer(),
   CharUnits::fromQuantity(
-  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType(;
+  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())),
+  IsTLS);

nikola-tesic-ns wrote:

Ok, thanks for your effort and detailed explanation!
Do you think the best we can do (in this case) is to get `threadlocal.address` 
from `__tls_guard` at the first access in `__tls_init` function and reuse it in 
the whole function (example below)?

```
define internal void @__tls_init() {
  %tls_addr = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 
@__tls_guard)
  %1 = load i8, ptr %1, align 1
  %2 = icmp eq i8 %1, 0
  br i1 %2, label %3, label %5

3:
  store i8 1, ptr %tls_addr, align 1
  %4 = call ptr @llvm.invariant.start.p0(i64 1, ptr %tls_addr)
  call void @__cxx_global_var_init()
  br label %5

5:
  ret void
}
```

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-08 Thread John McCall via cfe-commits


@@ -1070,13 +1084,20 @@ 
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.
+  // Get the thread-local address via intrinsic.
+  if (IsTLS)
+GuardAddr = GuardAddr.withPointer(
+Builder.CreateThreadLocalAddress(Guard.getPointer()),
+NotKnownNonNull);
+  Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1),
+  GuardAddr);
+
+  // Emit invariant start for TLS guard address.
   EmitInvariantStart(
   Guard.getPointer(),
   CharUnits::fromQuantity(
-  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType(;
+  CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())),
+  IsTLS);

rjmccall wrote:

I feel like we just need to file a DR with WG21 on this general question.  The 
alternatives I can see:

1. Forbid TLVs in coroutines. Source-breaking.
2. Continue to eagerly initialize local TLVs in coroutines, but bind the name 
permanently to the TLV that was initialized. This means it is potentially a 
cross-thread reference after a suspension. It is the user's responsibility to 
make that not a problem. A semantics change for most (if not at all) existing 
compilers.
3. Like #2, but give references to the TLV undefined behavior if the thread has 
changed. The most compatible option, sadly.
4. Like #2, but make the program statically ill-formed if a suspension 
potentially intervenes between the initialization and a reference to the TLV. 
Source-breaking. Also a significant new implementation burden for compilers.
5. Switch local TLVs in coroutines to the same lazy-initialization model as 
global TLVs.  Every reference to the variable dynamically resolves to the TLV 
for the current thread.  Because of the model change, the variable is always 
initialized. A semantics change for most (if not all) existing compilers.
6. Like #5, but require the initializer to be a constant expression just to try 
to minimize the semantic impact.

Note that a cross-thread reference can race not just with read/write or 
write/write conflicts between threads, but also with the destruction of the 
other thread.  Because of the latter, it will be a potentially-dangling 
reference for most async-like use cases.

https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-08 Thread John McCall via cfe-commits

https://github.com/rjmccall edited 
https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-08 Thread John McCall via cfe-commits

https://github.com/rjmccall edited 
https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Access tls_guard via llvm.threadlocal.address (PR #96633)

2024-07-08 Thread John McCall via cfe-commits

https://github.com/rjmccall edited 
https://github.com/llvm/llvm-project/pull/96633
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits