diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 2cce2936fe5ae..06558ce796f2e 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -404,6 +404,16 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn); IRBuilder<> B(BB); llvm::SmallVector Args; + + SmallVector OB; + if (CGM.shouldEmitConvergenceTokens()) { + assert(EntryFn->isConvergent()); + llvm::Value *I = B.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_entry, {}, {}); + llvm::Value *bundleArgs[] = {I}; + OB.emplace_back("convergencectrl", bundleArgs); + } + // FIXME: support struct parameters where semantics are on members. // See: https://github.com/llvm/llvm-project/issues/57874 unsigned SRetOffset = 0; @@ -419,7 +429,7 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, Args.push_back(emitInputSemantic(B, *PD, Param.getType())); } - CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args); + CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB); CI->setCallingConv(Fn->getCallingConv()); // FIXME: Handle codegen for return type semantics. // See: https://github.com/llvm/llvm-project/issues/57875 @@ -474,14 +484,22 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() { for (auto &F : M.functions()) { if (!F.hasFnAttribute("hlsl.shader")) continue; - IRBuilder<> B(&F.getEntryBlock(), F.getEntryBlock().begin()); + auto *Token = getConvergenceToken(F.getEntryBlock()); + Instruction *IP = &*F.getEntryBlock().begin(); + SmallVector OB; + if (Token) { + llvm::Value *bundleArgs[] = {Token}; + OB.emplace_back("convergencectrl", bundleArgs); + IP = Token->getNextNode(); + } + IRBuilder<> B(IP); for (auto *Fn : CtorFns) - B.CreateCall(FunctionCallee(Fn)); + B.CreateCall(FunctionCallee(Fn), {}, OB); // Insert global dtors before the terminator of the last instruction B.SetInsertPoint(F.back().getTerminator()); for (auto *Fn : DtorFns) - B.CreateCall(FunctionCallee(Fn)); + B.CreateCall(FunctionCallee(Fn), {}, OB); } // No need to keep global ctors/dtors for non-lib profile after call to @@ -579,3 +597,18 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() { Builder.CreateRetVoid(); return InitResBindingsFunc; } + +llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) { + if (!CGM.shouldEmitConvergenceTokens()) + return nullptr; + + auto E = BB.end(); + for (auto I = BB.begin(); I != E; ++I) { + auto *II = dyn_cast(&*I); + if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) { + return II; + } + } + llvm_unreachable("Convergence token should have been emitted."); + return nullptr; +} diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index ff7df41b5c62e..cd533cad84e9f 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -143,6 +143,7 @@ class CGHLSLRuntime { bool needsResourceBindingInitFn(); llvm::Function *createResourceBindingInitFn(); + llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB); private: void addBufferResourceAnnotation(llvm::GlobalVariable *GV, diff --git a/clang/test/CodeGenHLSL/convergence/entry.point.hlsl b/clang/test/CodeGenHLSL/convergence/entry.point.hlsl new file mode 100644 index 0000000000000..337a9ad5026c1 --- /dev/null +++ b/clang/test/CodeGenHLSL/convergence/entry.point.hlsl @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: define void @main() +// CHECK-NEXT: entry: +// CHECK-NEXT: [[token:%[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK-NEXT: call spir_func void @_Z4mainv() [ "convergencectrl"(token [[token]]) ] + +[numthreads(1,1,1)] +void main() { +} +