@@ -404,6 +404,16 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
404404 BasicBlock *BB = BasicBlock::Create (Ctx, " entry" , EntryFn);
405405 IRBuilder<> B (BB);
406406 llvm::SmallVector<Value *> Args;
407+
408+ SmallVector<OperandBundleDef, 1 > OB;
409+ if (CGM.shouldEmitConvergenceTokens ()) {
410+ assert (EntryFn->isConvergent ());
411+ llvm::Value *I = B.CreateIntrinsic (
412+ llvm::Intrinsic::experimental_convergence_entry, {}, {});
413+ llvm::Value *bundleArgs[] = {I};
414+ OB.emplace_back (" convergencectrl" , bundleArgs);
415+ }
416+
407417 // FIXME: support struct parameters where semantics are on members.
408418 // See: https://github.com/llvm/llvm-project/issues/57874
409419 unsigned SRetOffset = 0 ;
@@ -419,7 +429,7 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
419429 Args.push_back (emitInputSemantic (B, *PD, Param.getType ()));
420430 }
421431
422- CallInst *CI = B.CreateCall (FunctionCallee (Fn), Args);
432+ CallInst *CI = B.CreateCall (FunctionCallee (Fn), Args, OB );
423433 CI->setCallingConv (Fn->getCallingConv ());
424434 // FIXME: Handle codegen for return type semantics.
425435 // See: https://github.com/llvm/llvm-project/issues/57875
@@ -474,14 +484,22 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() {
474484 for (auto &F : M.functions ()) {
475485 if (!F.hasFnAttribute (" hlsl.shader" ))
476486 continue ;
477- IRBuilder<> B (&F.getEntryBlock (), F.getEntryBlock ().begin ());
487+ auto *Token = getConvergenceToken (F.getEntryBlock ());
488+ Instruction *IP = &*F.getEntryBlock ().begin ();
489+ SmallVector<OperandBundleDef, 1 > OB;
490+ if (Token) {
491+ llvm::Value *bundleArgs[] = {Token};
492+ OB.emplace_back (" convergencectrl" , bundleArgs);
493+ IP = Token->getNextNode ();
494+ }
495+ IRBuilder<> B (IP);
478496 for (auto *Fn : CtorFns)
479- B.CreateCall (FunctionCallee (Fn));
497+ B.CreateCall (FunctionCallee (Fn), {}, OB );
480498
481499 // Insert global dtors before the terminator of the last instruction
482500 B.SetInsertPoint (F.back ().getTerminator ());
483501 for (auto *Fn : DtorFns)
484- B.CreateCall (FunctionCallee (Fn));
502+ B.CreateCall (FunctionCallee (Fn), {}, OB );
485503 }
486504
487505 // No need to keep global ctors/dtors for non-lib profile after call to
@@ -579,3 +597,18 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() {
579597 Builder.CreateRetVoid ();
580598 return InitResBindingsFunc;
581599}
600+
601+ llvm::Instruction *CGHLSLRuntime::getConvergenceToken (BasicBlock &BB) {
602+ if (!CGM.shouldEmitConvergenceTokens ())
603+ return nullptr ;
604+
605+ auto E = BB.end ();
606+ for (auto I = BB.begin (); I != E; ++I) {
607+ auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
608+ if (II && llvm::isConvergenceControlIntrinsic (II->getIntrinsicID ())) {
609+ return II;
610+ }
611+ }
612+ llvm_unreachable (" Convergence token should have been emitted." );
613+ return nullptr ;
614+ }
0 commit comments