summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGStmt.cpp
diff options
context:
space:
mode:
authorSameer Sahasrabuddhe <sameer.sahasrabuddhe@amd.com>2025-04-15 18:00:01 +0530
committerSameer Sahasrabuddhe <sameer.sahasrabuddhe@amd.com>2025-04-18 12:26:21 +0530
commit5681859e308283628da481c0ddc09a39345b3d46 (patch)
treeba0c37590c1ac3026adaf1ef43484d12097892b4 /clang/lib/CodeGen/CGStmt.cpp
parent4ddf344b77cc01282571c643d621af34e6a7d8ad (diff)
[clang] Redefine `noconvergent` and generate convergence control tokensusers/ssahasra/clang-generate-tokens
This introduces the `-fconvergence-control` flag that emits convergence control intrinsics which are then used as the `convergencectrl` operand bundle on convergent calls. This also redefines the `noconvergent` attribute in Clang. The existing simple interpretation is that if a statement is marked `noconvergent`, then every asm call is treated as a non-convergent operation in the emitted LLVM IR. The new semantics introduces a more powerful notion that a `noconvergent` statement may contain convergent operations, but the resulting convergence constraints are limited to the scope of that statement. As a whole the statement itself does not place any convergence constraints on the control flow reaching it. When emitting convergence tokens, this attribute results in a call to the `anchor` intrinsic that determines convergence within the statement.
Diffstat (limited to 'clang/lib/CodeGen/CGStmt.cpp')
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp44
1 files changed, 31 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 3562b4ea22a2..1a9a574572f6 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -829,14 +829,24 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
} break;
}
}
+ bool LegacyNoConvergent = noconvergent && !CGM.shouldEmitConvergenceTokens();
SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge);
SaveAndRestore save_noinline(InNoInlineAttributedStmt, noinline);
SaveAndRestore save_alwaysinline(InAlwaysInlineAttributedStmt, alwaysinline);
- SaveAndRestore save_noconvergent(InNoConvergentAttributedStmt, noconvergent);
+ SaveAndRestore save_noconvergent(InNoConvergentAttributedStmt,
+ LegacyNoConvergent);
SaveAndRestore save_musttail(MustTailCall, musttail);
SaveAndRestore save_flattenOrBranch(HLSLControlFlowAttr, flattenOrBranch);
CGAtomicOptionsRAII AORAII(CGM, AA);
+ if (noconvergent && CGM.shouldEmitConvergenceTokens()) {
+ EmitBlock(createBasicBlock("noconvergent.anchor"));
+ ConvergenceTokenStack.push_back(
+ emitConvergenceAnchorToken(Builder.GetInsertBlock()));
+ }
EmitStmt(S.getSubStmt(), S.getAttrs());
+ if (noconvergent && CGM.shouldEmitConvergenceTokens()) {
+ ConvergenceTokenStack.pop_back();
+ }
}
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
@@ -3317,16 +3327,6 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
return F;
}
-// Returns the first convergence entry/loop/anchor instruction found in |BB|.
-// std::nullptr otherwise.
-static llvm::ConvergenceControlInst *getConvergenceToken(llvm::BasicBlock *BB) {
- for (auto &I : *BB) {
- if (auto *CI = dyn_cast<llvm::ConvergenceControlInst>(&I))
- return CI;
- }
- return nullptr;
-}
-
llvm::CallBase *
CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input) {
llvm::ConvergenceControlInst *ParentToken = ConvergenceTokenStack.back();
@@ -3349,14 +3349,32 @@ CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
}
llvm::ConvergenceControlInst *
+CodeGenFunction::emitConvergenceAnchorToken(llvm::BasicBlock *BB) {
+ return llvm::ConvergenceControlInst::CreateAnchor(*BB);
+}
+
+llvm::ConvergenceControlInst *
CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) {
llvm::BasicBlock *BB = &F->getEntryBlock();
- llvm::ConvergenceControlInst *Token = getConvergenceToken(BB);
+ llvm::ConvergenceControlInst *Token = llvm::getConvergenceControlDef(*BB);
if (Token)
return Token;
- // Adding a convergence token requires the function to be marked as
+ // Adding a convergence entry token requires the function to be marked as
// convergent.
F->setConvergent();
return llvm::ConvergenceControlInst::CreateEntry(*BB);
}
+
+llvm::ConvergenceControlInst *
+CodeGenFunction::getOrEmitConvergenceAnchorToken(llvm::Function *F) {
+ llvm::BasicBlock *BB = &F->getEntryBlock();
+ llvm::ConvergenceControlInst *Token = llvm::getConvergenceControlDef(*BB);
+ if (Token)
+ return Token;
+
+ // Adding a convergence anchor token requires the function to be marked as
+ // not convergent.
+ F->setNotConvergent();
+ return llvm::ConvergenceControlInst::CreateAnchor(*BB);
+}