[llvm-branch-commits] [clang] [llvm] [clang] Redefine `noconvergent` and generate convergence control tokens (PR #136282)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Apr 18 01:28:43 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Sameer Sahasrabuddhe (ssahasra)
<details>
<summary>Changes</summary>
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.
---
Patch is 64.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136282.diff
27 Files Affected:
- (modified) clang/docs/ThreadConvergence.rst (+27)
- (modified) clang/include/clang/Analysis/Analyses/ConvergenceCheck.h (+2-1)
- (modified) clang/include/clang/Basic/AttrDocs.td (+9-6)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2)
- (modified) clang/include/clang/Basic/LangOptions.def (+2)
- (modified) clang/include/clang/Driver/Options.td (+5)
- (modified) clang/lib/Analysis/ConvergenceCheck.cpp (+33-10)
- (modified) clang/lib/CodeGen/CGCall.cpp (+7-1)
- (modified) clang/lib/CodeGen/CGStmt.cpp (+31-13)
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+15-8)
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+11-2)
- (modified) clang/lib/CodeGen/CodeGenModule.h (+1-1)
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+3)
- (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+5-3)
- (added) clang/test/CodeGenHIP/convergence-tokens.hip (+687)
- (added) clang/test/CodeGenHIP/noconvergent-statement.hip (+109)
- (added) clang/test/SemaHIP/noconvergent-errors/backwards_jump.hip (+23)
- (added) clang/test/SemaHIP/noconvergent-errors/jump-into-nest.hip (+32)
- (added) clang/test/SemaHIP/noconvergent-errors/no-errors.hip (+83)
- (added) clang/test/SemaHIP/noconvergent-errors/simple_jump.hip (+23)
- (modified) llvm/include/llvm/IR/InstrTypes.h (+2-6)
- (modified) llvm/include/llvm/IR/IntrinsicInst.h (+12)
- (added) llvm/include/llvm/Transforms/Utils/FixConvergenceControl.h (+21)
- (modified) llvm/lib/IR/Instructions.cpp (+7)
- (modified) llvm/lib/IR/IntrinsicInst.cpp (+21)
- (modified) llvm/lib/Transforms/Utils/CMakeLists.txt (+1)
- (added) llvm/lib/Transforms/Utils/FixConvergenceControl.cpp (+191)
``````````diff
diff --git a/clang/docs/ThreadConvergence.rst b/clang/docs/ThreadConvergence.rst
index d872ab9cb77f5..ce2ca2cbeacde 100644
--- a/clang/docs/ThreadConvergence.rst
+++ b/clang/docs/ThreadConvergence.rst
@@ -564,6 +564,33 @@ backwards ``goto`` instead of a ``while`` statement.
``outside_loop``. This includes threads that jumped from ``G2`` as well as
threads that reached ``outside_loop`` after executing ``C``.
+.. _noconvergent-statement:
+
+The ``noconvergent`` Statement
+==============================
+
+When a statement is marked as ``noconvergent`` the convergence of threads at the
+start of this statement is not constrained by any convergent operations inside
+the statement.
+
+- When two threads execute a statement marked ``noconvergent``, it is
+ implementation-defined whether they are converged at that execution. [Note:
+ The resulting evaluations must still satisfy the strict partial order imposed
+ by convergence-before.]
+- When two threads are converged at the start of this statement (as determined
+ by the implementation), whether they are converged at each convergent
+ operation inside this statement is determined by the usual rules.
+
+For every label statement ``L`` occurring inside a ``noconvergent``
+statement, every ``goto`` or ``switch`` statement that transfers control to
+``L`` must also occur inside that statement.
+
+.. note::
+
+ Convergence control tokens are necessary for correctly implementing the
+ "noconvergent" statement attribute. When tokens are not in use, the legacy
+ behaviour is retained, where the only effect of this attribute is that
+ ``asm`` calls within the statement are not treated as convergent operations.
Implementation-defined Convergence
==================================
diff --git a/clang/include/clang/Analysis/Analyses/ConvergenceCheck.h b/clang/include/clang/Analysis/Analyses/ConvergenceCheck.h
index bf0d164c6a5bc..74208889a84df 100644
--- a/clang/include/clang/Analysis/Analyses/ConvergenceCheck.h
+++ b/clang/include/clang/Analysis/Analyses/ConvergenceCheck.h
@@ -18,7 +18,8 @@ class AnalysisDeclContext;
class Sema;
class Stmt;
-void analyzeForConvergence(Sema &S, AnalysisDeclContext &AC);
+void analyzeForConvergence(Sema &S, AnalysisDeclContext &AC,
+ bool GenerateWarnings, bool GenerateTokens);
} // end namespace clang
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 5f37922d352b7..7ef8d3d86fe50 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1700,13 +1700,12 @@ def NoConvergentDocs : Documentation {
This attribute prevents a function from being treated as convergent; when a
function is marked ``noconvergent``, calls to that function are not
automatically assumed to be convergent, unless such calls are explicitly marked
-as ``convergent``. If a statement is marked as ``noconvergent``, any calls to
-inline ``asm`` in that statement are no longer treated as convergent.
+as ``convergent``.
-In languages following SPMD/SIMT programming model, e.g., CUDA/HIP, function
-declarations and inline asm calls are treated as convergent by default for
-correctness. This ``noconvergent`` attribute is helpful for developers to
-prevent them from being treated as convergent when it's safe.
+If a statement is marked as ``noconvergent``, the semantics depends on whether
+convergence control tokens are used in the generated LLVM IR. When convergence
+control tokens are not in use, any calls to inline ``asm`` in that statement are
+treated as not convergent.
.. code-block:: c
@@ -1719,6 +1718,10 @@ prevent them from being treated as convergent when it's safe.
[[clang::noconvergent]] { asm volatile ("nop"); } // the asm call is non-convergent
}
+When tokens are in use, placing the ``noconvergent`` attribute on a statement
+indicates that thread convergence at the entry to that statement is
+:ref:`implementation-defined<noconvergent-statement>`.
+
}];
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dabb6d31b519a..3be697c6337bc 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6514,6 +6514,8 @@ def note_goto_affects_convergence : Note<
"jump from this goto statement affects convergence">;
def note_switch_case_affects_convergence : Note<
"jump to this case statement affects convergence of loop">;
+def err_jump_into_noconvergent : Error<
+ "cannot jump into a noconvergent statement from outside">;
def err_goto_into_protected_scope : Error<
"cannot jump from this goto statement to its label">;
def ext_goto_into_protected_scope : ExtWarn<
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 930c1c06d1a76..c8254af61387b 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -306,6 +306,8 @@ LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP")
LANGOPT(OffloadUniformBlock, 1, 0, "Assume that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)")
LANGOPT(HIPStdPar, 1, 0, "Enable Standard Parallel Algorithm Acceleration for HIP (experimental)")
LANGOPT(HIPStdParInterposeAlloc, 1, 0, "Replace allocations / deallocations with HIP RT calls when Standard Parallel Algorithm Acceleration for HIP is enabled (Experimental)")
+LANGOPT(ConvergenceControl, 1, 0,
+ "Generate explicit convergence control (experimental)")
LANGOPT(OpenACC , 1, 0, "OpenACC Enabled")
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 830d3459a1320..369929c30a623 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1397,6 +1397,11 @@ def fhip_emit_relocatable : Flag<["-"], "fhip-emit-relocatable">,
HelpText<"Compile HIP source to relocatable">;
def fno_hip_emit_relocatable : Flag<["-"], "fno-hip-emit-relocatable">,
HelpText<"Do not override toolchain to compile HIP source to relocatable">;
+defm convergence_control : BoolFOption<"convergence-control",
+ LangOpts<"ConvergenceControl">, DefaultFalse,
+ PosFlag<SetTrue, [], [ClangOption, CC1Option], "Generate">,
+ NegFlag<SetFalse, [], [ClangOption], "Don't generate">,
+ BothFlags<[], [ClangOption], " explicit convergence control tokens (experimental)">>;
}
// Clang specific/exclusive options for OpenACC.
diff --git a/clang/lib/Analysis/ConvergenceCheck.cpp b/clang/lib/Analysis/ConvergenceCheck.cpp
index 75139388ea19e..93744f8b8e495 100644
--- a/clang/lib/Analysis/ConvergenceCheck.cpp
+++ b/clang/lib/Analysis/ConvergenceCheck.cpp
@@ -16,6 +16,11 @@
using namespace clang;
using namespace llvm;
+static void errorJumpIntoNoConvergent(Sema &S, Stmt *From, Stmt *Parent) {
+ S.Diag(Parent->getBeginLoc(), diag::err_jump_into_noconvergent);
+ S.Diag(From->getBeginLoc(), diag::note_goto_affects_convergence);
+}
+
static void warnGotoCycle(Sema &S, Stmt *From, Stmt *Parent) {
S.Diag(Parent->getBeginLoc(),
diag::warn_cycle_created_by_goto_affects_convergence);
@@ -27,7 +32,8 @@ static void warnJumpIntoLoop(Sema &S, Stmt *From, Stmt *Loop) {
S.Diag(From->getBeginLoc(), diag::note_goto_affects_convergence);
}
-static void checkConvergenceOnGoto(Sema &S, GotoStmt *From, ParentMap &PM) {
+static void checkConvergenceOnGoto(Sema &S, GotoStmt *From, ParentMap &PM,
+ bool GenerateWarnings, bool GenerateTokens) {
Stmt *To = From->getLabel()->getStmt();
unsigned ToDepth = PM.getParentDepth(To) + 1;
@@ -42,7 +48,7 @@ static void checkConvergenceOnGoto(Sema &S, GotoStmt *From, ParentMap &PM) {
}
// Special case: the goto statement is a descendant of the label statement.
- if (ExpandedFrom == ExpandedTo) {
+ if (GenerateWarnings && ExpandedFrom == ExpandedTo) {
assert(ExpandedTo == To);
warnGotoCycle(S, From, To);
return;
@@ -60,10 +66,18 @@ static void checkConvergenceOnGoto(Sema &S, GotoStmt *From, ParentMap &PM) {
SmallVector<Stmt *> Loops;
for (Stmt *I = To; I != ParentFrom; I = PM.getParent(I)) {
+ if (GenerateTokens)
+ if (const auto *AS = dyn_cast<AttributedStmt>(I))
+ if (hasSpecificAttr<NoConvergentAttr>(AS->getAttrs()))
+ errorJumpIntoNoConvergent(S, From, I);
// Can't jump into a ranged-for, so we don't need to look for it here.
- if (isa<ForStmt, WhileStmt, DoStmt>(I))
+ if (GenerateWarnings && isa<ForStmt, WhileStmt, DoStmt>(I))
Loops.push_back(I);
}
+
+ if (!GenerateWarnings)
+ return;
+
for (Stmt *I : reverse(Loops))
warnJumpIntoLoop(S, From, I);
@@ -88,21 +102,29 @@ static void warnSwitchIntoLoop(Sema &S, Stmt *Case, Stmt *Loop) {
}
static void checkConvergenceForSwitch(Sema &S, SwitchStmt *Switch,
- ParentMap &PM) {
+ ParentMap &PM, bool GenerateWarnings,
+ bool GenerateTokens) {
for (SwitchCase *Case = Switch->getSwitchCaseList(); Case;
Case = Case->getNextSwitchCase()) {
SmallVector<Stmt *> Loops;
for (Stmt *I = Case; I != Switch; I = PM.getParent(I)) {
+ if (GenerateTokens)
+ if (const auto *AS = dyn_cast<AttributedStmt>(I))
+ if (hasSpecificAttr<NoConvergentAttr>(AS->getAttrs()))
+ errorJumpIntoNoConvergent(S, Switch, I);
// Can't jump into a ranged-for, so we don't need to look for it here.
- if (isa<ForStmt, WhileStmt, DoStmt>(I))
+ if (GenerateWarnings && isa<ForStmt, WhileStmt, DoStmt>(I))
Loops.push_back(I);
}
- for (Stmt *I : reverse(Loops))
- warnSwitchIntoLoop(S, Case, I);
+ if (GenerateWarnings) {
+ for (Stmt *I : reverse(Loops))
+ warnSwitchIntoLoop(S, Case, I);
+ }
}
}
-void clang::analyzeForConvergence(Sema &S, AnalysisDeclContext &AC) {
+void clang::analyzeForConvergence(Sema &S, AnalysisDeclContext &AC,
+ bool GenerateWarnings, bool GenerateTokens) {
// Iterating over the CFG helps trim unreachable blocks, and locates Goto
// statements faster than iterating over the whole body.
CFG *cfg = AC.getCFG();
@@ -111,9 +133,10 @@ void clang::analyzeForConvergence(Sema &S, AnalysisDeclContext &AC) {
for (CFGBlock *BI : *cfg) {
Stmt *Term = BI->getTerminatorStmt();
if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(Term)) {
- checkConvergenceOnGoto(S, Goto, PM);
+ checkConvergenceOnGoto(S, Goto, PM, GenerateWarnings, GenerateTokens);
} else if (SwitchStmt *Switch = dyn_cast_or_null<SwitchStmt>(Term)) {
- checkConvergenceForSwitch(S, Switch, PM);
+ checkConvergenceForSwitch(S, Switch, PM, GenerateWarnings,
+ GenerateTokens);
}
}
}
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 8cb27420dd911..20f251a5ba5b2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5773,7 +5773,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Attrs =
Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline);
- // Remove call-site convergent attribute if requested.
+ // Remove call-site convergent attribute if this call occurs inside a
+ // noconvergent statement. This is the legacy behaviour when convergence
+ // control tokens are not in use. It only affects inline asm calls, since all
+ // other function calls inherit the convergent attribute from the callee. When
+ // convergence control tokens are in use, any inline asm calls should be
+ // explicitly marked noconvergent, else they simply inherit whatever token is
+ // currently in scope.
if (InNoConvergentAttributedStmt)
Attrs =
Attrs.removeFnAttribute(getLLVMContext(), llvm::Attribute::Convergent);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 3562b4ea22a24..1a9a574572f67 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();
@@ -3348,15 +3348,33 @@ CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB) {
return llvm::ConvergenceControlInst::CreateLoop(*BB, ParentToken);
}
+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);
+}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 4d29ceace646f..d9226bdd775a3 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -47,6 +47,7 @@
#include "llvm/Support/CRC.h"
#include "llvm/Support/xxhash.h"
#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
+#include "llvm/Transforms/Utils/FixConvergenceControl.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <optional>
@@ -371,12 +372,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
assert(DeferredDeactivationCleanupStack.empty() &&
"mismatched activate/deactivate of cleanups!");
- if (CGM.shouldEmitConvergenceTokens()) {
- ConvergenceTokenStack.pop_back();
- assert(ConvergenceTokenStack.empty() &&
- "mismatched push/pop in convergence stack!");
- }
-
bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0
&& NumSimpleReturnExprs == NumReturnExprs
&& ReturnBlock.getBlock()->use_empty();
@@ -1362,8 +1357,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (const auto *VecWidth = CurFuncDecl->getAttr<MinVectorWidthAttr>())
LargestVectorWidth = VecWidth->getVectorWidth();
- if (CGM.shouldEmitConvergenceTokens())
- ConvergenceTokenStack.push_back(getOrEmitConvergenceEntryToken(CurFn));
+ if (CGM.shouldEmitConvergenceTokens()) {
+ llvm::ConvergenceControlInst *Token =
+ (FD && FD->hasAttr<NoConvergentAttr>())
+ ? getOrEmitConvergenceAnchorToken(CurFn)
+ : getOrEmitConvergenceEntryToken(CurFn);
+ ConvergenceTokenStack.push_back(Token);
+ }
}
void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
@@ -1647,6 +1647,13 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
}
}
+ if (CGM.shouldEmitConvergenceTokens()) {
+ ConvergenceTokenStack.pop_back();
+ assert(ConvergenceTokenStack.empty() &&
+ "mismatched push/pop in convergence stack!");
+ fixConvergenceControl(CurFn);
+ }
+
// Emit the standard function epilogue.
FinishFunction(BodyRange.getEnd());
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 9254c7077237f..0d20218f6cbf1 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5339,15 +5339,24 @@ class CodeGenFunction : public CodeGenTypeCache {
// as it's parent convergence instr.
llvm::ConvergenceControlInst *emitConvergenceLoopToken(llvm::BasicBlock *BB);
+ // Emits a convergence_anchor instruction for the given |BB|.
+ llvm::ConvergenceControlInst *
+ emitConvergenceAnchorToken(llvm::BasicBlock *BB);
+
// Adds a convergence_ctrl token with |ParentToken| as parent convergence
// instr to the call |Input|.
llvm::CallBase *addConvergenceControlToken(llvm::CallBase *Input);
- // Find the convergence_entry instruction |F|, or emits ones if none exists.
- // Returns the convergence instruction.
+ // Find the convergence control token in the entry block of |F|, or if none
+ // exists, create an entry token.
llvm::ConvergenceControlInst *
getOrEmitConvergenceEntryToken(llvm::Function *F);
+ // Find the convergence control token in the entry block of |F|, or if none
+ // exists, create an anchor token.
+ llvm::ConvergenceControlInst *
+ getOrEmitConvergenceAnchorToken(llvm::Function *F);
+
private:
llvm::MDNode *getRangeForLoadFromType(QualType Ty);
void EmitReturnOfRValue(RValue RV, QualType Ty);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 9a0bc675e0baa..1651c87049df8 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1751,7 +1751,7 @@ class CodeGenModule : public CodeGenTypeCache {
bool shouldEmitConvergenceTokens() const {
// TODO: this should probably become unconditional once the controlled
// convergence becomes the norm.
- return getTriple().isSPIRVLogical();
+ return getTriple().isSPIRVLogical() || getLangOpts().ConvergenceControl;
}
void addUndefinedGlobalForTailCall(
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b2dd4b3b54869..c9e37548fa835 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7098,6 +7098,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fhip_new_launch_api,
options::OPT_fno_hip_new_launch_api, true))
CmdArgs.push_back("-fhip-new-launch-api");
+ if (Args.hasFlag(options::OPT_fconvergence_control,
+ options::OPT_fno_convergence_control, false))
+ CmdArgs.push_back("-fconvergence-control");
Args.addOptInFlag(CmdArgs, options::OPT_fgpu_allow_device_init,
options::OPT_fno_gpu_allow_device_init);
Args.AddLastArg(CmdArgs, options::OPT_hipstdpar);
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clan...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/136282
More information about the llvm-branch-commits
mailing list