Skip to content

Commit da5fb42

Browse files
authored
[Clang][SPIR-V] Fix convergence tokens for dtor (#133469)
Destructor calls were emitted without convergence intrinsics when building for SPIR-V, which means invalid IR since we mixed controlled and non-controlled convergence.
1 parent 197ead7 commit da5fb42

File tree

2 files changed

+32
-13
lines changed

2 files changed

+32
-13
lines changed

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(
11501150
llvm::Constant *Arg;
11511151
std::tie(CalleeTy, Callee, Arg) = DtorsOrStermFinalizers[e - i - 1];
11521152

1153-
llvm::CallInst *CI = nullptr;
1153+
llvm::CallBase *CI = nullptr;
11541154
if (Arg == nullptr) {
11551155
assert(
11561156
CGM.getCXXABI().useSinitAndSterm() &&
@@ -1162,6 +1162,9 @@ void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(
11621162
// Make sure the call and the callee agree on calling convention.
11631163
if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
11641164
CI->setCallingConv(F->getCallingConv());
1165+
1166+
if (CGM.shouldEmitConvergenceTokens() && CI->isConvergent())
1167+
CI = addConvergenceControlToken(CI);
11651168
}
11661169
}
11671170

clang/test/CodeGenHLSL/GlobalDestructors.hlsl

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE,CHECK
2-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE,CHECK
1+
// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE-SPIRV,CHECK
2+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE-DXIL,CHECK
3+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE-DXIL,CHECK
34
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
45
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
56

@@ -57,22 +58,37 @@ void main(unsigned GI : SV_GroupIndex) {
5758
// CHECK: define void @main()
5859
// CHECK-NEXT: entry:
5960
// Verify destructor is emitted
60-
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
61-
// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
62-
// NOINLINE-NEXT: call void @_Z4mainj(i32 %0)
63-
// NOINLINE-NEXT: call void @_GLOBAL__D_a()
64-
// NOINLINE-NEXT: ret void
61+
// NOINLINE-DXIL-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
62+
// NOINLINE-DXIL-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
63+
// NOINLINE-DXIL-NEXT: call void @_Z4mainj(i32 %0)
64+
// NOINLINE-DXIL-NEXT: call void @_GLOBAL__D_a()
65+
// NOINLINE-DXIL-NEXT: ret void
66+
67+
// NOINLINE-SPIRV-NEXT: %0 = call token @llvm.experimental.convergence.entry()
68+
// NOINLINE-SPIRV-NEXT: call spir_func void @_GLOBAL__sub_I_GlobalDestructors.hlsl() [ "convergencectrl"(token %0) ]
69+
// NOINLINE-SPIRV-NEXT: %1 = call i32 @llvm.spv.flattened.thread.id.in.group()
70+
// NOINLINE-SPIRV-NEXT: call spir_func void @_Z4mainj(i32 %1) [ "convergencectrl"(token %0) ]
71+
// NOINLINE-SPIRV-NEXT: call spir_func void @_GLOBAL__D_a() [ "convergencectrl"(token %0) ]
72+
// NOINLINE-SPIRV-NEXT: ret void
73+
6574
// Verify inlining leaves only calls to "llvm." intrinsics
6675
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
6776
// INLINE: ret void
6877

6978
// This is really just a sanity check I needed for myself to verify that
7079
// function scope static variables also get destroyed properly.
7180

72-
// NOINLINE: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
73-
// NOINLINE-NEXT: entry:
74-
// NOINLINE-NEXT: call void @_ZN4TailD1Ev(ptr @_ZZ3WagvE1T)
75-
// NOINLINE-NEXT: call void @_ZN6PupperD1Ev(ptr @GlobalPup)
76-
// NOINLINE-NEXT: ret void
81+
// NOINLINE-DXIL: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
82+
// NOINLINE-DXIL-NEXT: entry:
83+
// NOINLINE-DXIL-NEXT: call void @_ZN4TailD1Ev(ptr @_ZZ3WagvE1T)
84+
// NOINLINE-DXIL-NEXT: call void @_ZN6PupperD1Ev(ptr @GlobalPup)
85+
// NOINLINE-DXIL-NEXT: ret void
86+
87+
// NOINLINE-SPIRV: define internal spir_func void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
88+
// NOINLINE-SPIRV-NEXT: entry:
89+
// NOINLINE-SPIRV-NEXT: %0 = call token @llvm.experimental.convergence.entry()
90+
// NOINLINE-SPIRV-NEXT: call spir_func void @_ZN4TailD1Ev(ptr @_ZZ3WagvE1T) [ "convergencectrl"(token %0) ]
91+
// NOINLINE-SPIRV-NEXT: call spir_func void @_ZN6PupperD1Ev(ptr @GlobalPup) [ "convergencectrl"(token %0) ]
92+
// NOINLINE-SPIRV-NEXT: ret void
7793

7894
// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline

0 commit comments

Comments
 (0)