[clang] [Clang][SPIR-V] Fix convergence tokens for dtor (PR #133469)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 28 09:54:29 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: Nathan Gauër (Keenuts)
<details>
<summary>Changes</summary>
Destructor calls were emitted without convergence
intrinsics when building for SPIR-V, which means invalid IR since we mixed controlled and non-controlled convergence.
---
Full diff: https://github.com/llvm/llvm-project/pull/133469.diff
2 Files Affected:
- (modified) clang/lib/CodeGen/CGDeclCXX.cpp (+4-1)
- (modified) clang/test/CodeGenHLSL/GlobalDestructors.hlsl (+28-12)
``````````diff
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 1ad34ae61f96a..b142aaf3fe0ee 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -1152,7 +1152,7 @@ void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(
llvm::Constant *Arg;
std::tie(CalleeTy, Callee, Arg) = DtorsOrStermFinalizers[e - i - 1];
- llvm::CallInst *CI = nullptr;
+ llvm::CallBase *CI = nullptr;
if (Arg == nullptr) {
assert(
CGM.getCXXABI().useSinitAndSterm() &&
@@ -1164,6 +1164,9 @@ void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(
// Make sure the call and the callee agree on calling convention.
if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
CI->setCallingConv(F->getCallingConv());
+
+ if (CGM.shouldEmitConvergenceTokens() && CI->isConvergent())
+ CI = addConvergenceControlToken(CI);
}
}
diff --git a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
index f98318601134b..9f90971bafd05 100644
--- a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE,CHECK
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE,CHECK
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE-SPIRV,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE-DXIL,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE-DXIL,CHECK
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
@@ -57,11 +58,19 @@ void main(unsigned GI : SV_GroupIndex) {
// CHECK: define void @main()
// CHECK-NEXT: entry:
// Verify destructor is emitted
-// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
-// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
-// NOINLINE-NEXT: call void @_Z4mainj(i32 %0)
-// NOINLINE-NEXT: call void @_GLOBAL__D_a()
-// NOINLINE-NEXT: ret void
+// NOINLINE-DXIL-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
+// NOINLINE-DXIL-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-DXIL-NEXT: call void @_Z4mainj(i32 %0)
+// NOINLINE-DXIL-NEXT: call void @_GLOBAL__D_a()
+// NOINLINE-DXIL-NEXT: ret void
+
+// NOINLINE-SPIRV-NEXT: %0 = call token @llvm.experimental.convergence.entry()
+// NOINLINE-SPIRV-NEXT: call spir_func void @_GLOBAL__sub_I_GlobalDestructors.hlsl() [ "convergencectrl"(token %0) ]
+// NOINLINE-SPIRV-NEXT: %1 = call i32 @llvm.spv.flattened.thread.id.in.group()
+// NOINLINE-SPIRV-NEXT: call spir_func void @_Z4mainj(i32 %1) [ "convergencectrl"(token %0) ]
+// NOINLINE-SPIRV-NEXT: call spir_func void @_GLOBAL__D_a() [ "convergencectrl"(token %0) ]
+// NOINLINE-SPIRV-NEXT: ret void
+
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// INLINE: ret void
@@ -69,10 +78,17 @@ void main(unsigned GI : SV_GroupIndex) {
// This is really just a sanity check I needed for myself to verify that
// function scope static variables also get destroyed properly.
-// NOINLINE: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
-// NOINLINE-NEXT: entry:
-// NOINLINE-NEXT: call void @_ZN4TailD1Ev(ptr @_ZZ3WagvE1T)
-// NOINLINE-NEXT: call void @_ZN6PupperD1Ev(ptr @GlobalPup)
-// NOINLINE-NEXT: ret void
+// NOINLINE-DXIL: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
+// NOINLINE-DXIL-NEXT: entry:
+// NOINLINE-DXIL-NEXT: call void @_ZN4TailD1Ev(ptr @_ZZ3WagvE1T)
+// NOINLINE-DXIL-NEXT: call void @_ZN6PupperD1Ev(ptr @GlobalPup)
+// NOINLINE-DXIL-NEXT: ret void
+
+// NOINLINE-SPIRV: define internal spir_func void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
+// NOINLINE-SPIRV-NEXT: entry:
+// NOINLINE-SPIRV-NEXT: %0 = call token @llvm.experimental.convergence.entry()
+// NOINLINE-SPIRV-NEXT: call spir_func void @_ZN4TailD1Ev(ptr @_ZZ3WagvE1T) [ "convergencectrl"(token %0) ]
+// NOINLINE-SPIRV-NEXT: call spir_func void @_ZN6PupperD1Ev(ptr @GlobalPup) [ "convergencectrl"(token %0) ]
+// NOINLINE-SPIRV-NEXT: ret void
// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
``````````
</details>
https://github.com/llvm/llvm-project/pull/133469
More information about the cfe-commits
mailing list