Skip to content
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1703aa6
Support for dispatch construct (Sema & Codegen) support. Support for …
Sep 20, 2024
5ae3ffe
Taking care of feedback comments from Alexey Bataev.
Dec 9, 2024
daf681c
Changed the comments for replaceWithNewTraitsOrDirectCall().
Dec 10, 2024
bc3c018
Removing an unnecessary bracket in if statement in ActOnOpenMPCall().
Dec 10, 2024
b83e0ba
Removing unnecessary brackets around if statement.
Dec 10, 2024
997fe7c
1) Claiming support for "dispatch" construct.
Dec 15, 2024
182d026
Spacing problems for claiming "dispatch construct".
Dec 15, 2024
dca846e
Adding support for dispatch construct in Release Notes.
Dec 16, 2024
26427bf
re-wording message in warn_omp_dispatch_clause_novariants_nocontext.
Dec 18, 2024
e379325
Changes in expected-warning message for "#pragma omp dispatch
Dec 18, 2024
bab22e6
Removing the word CodeGen from comments, which can lead to confusion.
Jan 2, 2025
00ac6cf
Moving the helper functions to CodeGen by using AnnotateAttr in Sema.
Feb 1, 2025
ff2f370
Changing the commit message from:
Feb 4, 2025
de5b7cc
All clang/test/OpenMP/dispatch_*.cpp tests pass with the changes in t…
Feb 4, 2025
5d5b152
Merge branch 'main' into dispatch_depend
Feb 5, 2025
817f6df
Handling:
Feb 22, 2025
984446d
Undoing changes to handle templates.
Mar 18, 2025
4cb7bdd
Merge branch 'main' into dispatch_depend
Mar 18, 2025
bd2e38a
Merge branch 'main' into dispatch_depend
Mar 18, 2025
c1a83cc
Separating virtual regions of taskwait directive and dispatch directive
Mar 25, 2025
07354f0
Merge branch 'main' into dispatch_depend
Mar 25, 2025
f204bc4
Merge branch 'main' into dispatch_depend
Mar 25, 2025
ce9bff0
Merge branch 'main' into dispatch_depend
Mar 25, 2025
bb176c8
Moving handling of dispatch depend into CodeGen.
Mar 29, 2025
d217bc5
Changes to be committed:
Mar 29, 2025
8fba558
-ast-dump is working with addition of extra virtual region. CodeGen is
Apr 3, 2025
5ec20c3
modified: clang/lib/Sema/SemaOpenMP.cpp
Apr 3, 2025
cd8fae5
Formatting problems.
Apr 3, 2025
f47769a
CodeGen works with this change.
Apr 4, 2025
503222e
All tests pass with this change.
Apr 4, 2025
de8b736
1) Changing the name of the function from
Apr 9, 2025
f1e91f0
Merge branch 'main' into dispatch_depend
Apr 9, 2025
b2571fa
Merge branch 'main' into dispatch_depend
Apr 9, 2025
b60c252
Added OMPLexicalScope before emitting if-else statement.
Apr 9, 2025
d23c523
Changing LexicalScope to OMPD_dispatch.
Apr 9, 2025
f186576
Removed unused statements.
Apr 10, 2025
fd150c2
Replacing getCapturedExprFromImplicitCastExpr() with
Apr 16, 2025
07d8827
Adding support for clauses novariants and nocontext occuring on the same
Apr 22, 2025
4206c6e
Rolling back changes to make template related changes in this patch.
Apr 24, 2025
6a35664
Minor changes based on review feedback.
May 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/OpenMPSupport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | dispatch construct and function variant argument adjustment | :part:`worked on` | D99537, D99679 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | dispatch construct | :part:`worked on` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | assumes directives | :part:`worked on` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | assume directive | :good:`done` | |
Expand Down
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ Python Binding Changes

OpenMP Support
--------------
- Added support for 'omp dispatch' directive.
- Added support 'no_openmp_constructs' assumption clause.
- Added support for 'self_maps' in map and requirement clause.
- Added support for 'omp stripe' directive.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -11899,6 +11899,9 @@ def err_omp_clause_requires_dispatch_construct : Error<
"'%0' clause requires 'dispatch' context selector">;
def err_omp_append_args_with_varargs : Error<
"'append_args' is not allowed with varargs functions">;
def warn_omp_dispatch_clause_novariants_nocontext : Warning<
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is a warning, not an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message is to indicate the user that if novariants and nocontext are specified then novariants is taken into account. This warning is to inform the user and not an error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it is not an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not need to stop execution if novariants and nocontext occur together. In a dispatch directive like #pragma omp dispatch nocontext(c1) novariants(c2) then I do not find a way to generate

if(condition)
    foo();
else
   foo_variant

For the "condition" in if statement I do not know a way to use c1 & c2 together. Hence I preferred to indicate this to user and use novariants(c2). I do not want to stop the compilation with an error message because the spec does not indicate what to do in this case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be just c1 || c2? What's the problem in emitting the combined expression?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this in the standard:
If do-not-use-variant evaluates to true, no function variant is selected for the target-call of the
13 dispatch region associated with the novariants clause even if one would be selected
14 normally.

Doe it mean that novariant has higher priority than nocontext?

Copy link
Contributor Author

@SunilKuravinakop SunilKuravinakop Apr 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This relates only to the novariants clause only. However, I can extrapolate the spec to mean whatever I have implemented. It will be good to provide a warning.
If you feel that warning is not needed then I can remove it but, the user should not be left wondering why nocontext was not considered.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dreachem thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The effect of the nocontext clause is to not add the dispatch construct to the construct trait set. It will only matter once we support dispatch in a construct trait selector (support for this is not required in 5.2, but is required in 6.0).

Assuming we support dispatch in a construct trait selector, then this is what the various combinations would mean:

novariants(0), nocontext(0): Allow selective variant substitution according to context match
novariants(0), nocontext(1): Allow selective variant substitution according to context match (NO MATCH
                             for selectors that require **dispatch** trait)
novariants(1), nocontext(0): Always call the base function (shuts off any variant substitution for the call)
novariants(1), nocontext(1): Always call the base function (shuts off any variant substitution for the call)

In summary, novariants takes precedence and nocontext can be ignored ONLY if the do-not-use-variant argument evaluates to true.

Copy link
Contributor Author

@SunilKuravinakop SunilKuravinakop Apr 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alexey,
I have added support for clauses novariants and nocontext occuring on the same dispatch directive and removed the warning message.
Can you please review the code?
--Sunil

"'nocontext' clause is ignored, only 'novariants' clause is applied">,
InGroup<SourceUsesOpenMP>;
def err_openmp_vla_in_task_untied : Error<
"variable length arrays are not supported in OpenMP tasking regions with 'untied' clause">;
def warn_omp_unterminated_declare_target : Warning<
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/OpenMPKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind);
/// parallel', otherwise - false.
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind);

/// Checks if the specified directive is a dispatch-kind directive.
/// \param DKind Specified directive.
/// \return true - the directive is a dispatch-like directive like 'omp
/// dispatch', otherwise - false.
bool isOpenMPDispatchDirective(OpenMPDirectiveKind DKind);

/// Checks if the specified directive is a target code offload directive.
/// \param DKind Specified directive.
/// \return true - the directive is a target code offload directive like
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Sema/SemaOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,10 @@ class SemaOpenMP : public SemaBase {
: OMPDeclareVariantScopes.back().TI;
}

void annotateAStmt(const ASTContext &Context, Stmt *StmtP,
SemaOpenMP *SemaPtr, ArrayRef<OMPClause *> &Clauses,
SourceLocation StartLoc);

/// The current `omp begin/end declare variant` scopes.
SmallVector<OMPDeclareVariantScope, 4> OMPDeclareVariantScopes;

Expand Down
10 changes: 9 additions & 1 deletion clang/lib/Basic/OpenMPKinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,11 @@ bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
llvm::is_contained(getLeafConstructs(DKind), OMPD_parallel);
}

bool clang::isOpenMPDispatchDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_dispatch ||
llvm::is_contained(getLeafConstructs(DKind), OMPD_dispatch);
}

bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_target ||
llvm::is_contained(getLeafConstructs(DKind), OMPD_target);
Expand Down Expand Up @@ -796,6 +801,10 @@ void clang::getOpenMPCaptureRegions(
CaptureRegions.push_back(OMPD_task);
CaptureRegions.push_back(OMPD_target);
break;
case OMPD_dispatch:
CaptureRegions.push_back(OMPD_task);
CaptureRegions.push_back(OMPD_dispatch);
break;
case OMPD_task:
case OMPD_target_enter_data:
case OMPD_target_exit_data:
Expand All @@ -819,7 +828,6 @@ void clang::getOpenMPCaptureRegions(
else
return true;
break;
case OMPD_dispatch:
case OMPD_distribute:
case OMPD_for:
case OMPD_ordered:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
EmitOMPInteropDirective(cast<OMPInteropDirective>(*S));
break;
case Stmt::OMPDispatchDirectiveClass:
CGM.ErrorUnsupported(S, "OpenMP dispatch directive");
EmitOMPDispatchDirective(cast<OMPDispatchDirective>(*S));
break;
case Stmt::OMPScopeDirectiveClass:
EmitOMPScopeDirective(cast<OMPScopeDirective>(*S));
Expand Down
120 changes: 120 additions & 0 deletions clang/lib/CodeGen/CGStmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4529,6 +4529,117 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
emitMaster(*this, S);
}

static Expr *getCapturedExprFromImplicitCastExpr(Expr *Cond) {

Expr *SubExpr = Cond->IgnoreParenImpCasts();

if (auto *DeclRef = dyn_cast<DeclRefExpr>(SubExpr)) {
if (auto *CapturedExprDecl =
dyn_cast<OMPCapturedExprDecl>(DeclRef->getDecl())) {

// Retrieve the initial expression from the captured expression
return CapturedExprDecl->getInit();
}
}
return Cond;
}

static Expr *replaceWithNewTraitsOrDirectCall(Stmt *AssocExpr,
CallExpr *ReplacementFunction) {
Expr *FinalCall = ReplacementFunction;

if (BinaryOperator *BinaryCopyOpr = dyn_cast<BinaryOperator>(AssocExpr)) {
BinaryCopyOpr->setRHS(FinalCall);
return BinaryCopyOpr;
}

return FinalCall;
}

static void transformCallInStmt(Stmt *StmtP) {
if (auto *AssocStmt = dyn_cast<CapturedStmt>(StmtP)) {
CapturedDecl *CDecl = AssocStmt->getCapturedDecl();

// Access AnnotateAttr
CallExpr *NewCallExpr = nullptr;
for (const auto *attr : CDecl->attrs()) {
if (const auto *annotateAttr = llvm::dyn_cast<clang::AnnotateAttr>(attr);
annotateAttr &&
annotateAttr->getAnnotation() == "NoContextInvariant") {
NewCallExpr = llvm::dyn_cast<CallExpr>(*annotateAttr->args_begin());
}
}

Stmt *CallExprStmt = CDecl->getBody();
Stmt *NewCallExprStmt =
replaceWithNewTraitsOrDirectCall(CallExprStmt, NewCallExpr);
CDecl->setBody(NewCallExprStmt);
}
}

static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition,
Stmt *AssociatedStmt) {
llvm::Value *CondValue = CGF->EvaluateExprAsBool(Condition);
llvm::BasicBlock *ThenBlock = CGF->createBasicBlock("if.then");
llvm::BasicBlock *ElseBlock = CGF->createBasicBlock("if.else");
llvm::BasicBlock *MergeBlock = CGF->createBasicBlock("if.end");

CGF->Builder.CreateCondBr(CondValue, ThenBlock, ElseBlock);

// Emit the else block.
Stmt *ElseStmt = AssociatedStmt;
CGF->EmitBlock(ElseBlock);
CGF->EmitStmt(ElseStmt);
CGF->Builder.CreateBr(MergeBlock);

// Emit the then block.
Stmt *ThenStmt = AssociatedStmt;
transformCallInStmt(ThenStmt);
CGF->EmitBlock(ThenBlock);
CGF->EmitStmt(ThenStmt);
CGF->Builder.CreateBr(MergeBlock);
CGF->EmitBlock(MergeBlock);
}

void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) {
ArrayRef<OMPClause *> Clauses = S.clauses();

Stmt *AssociatedStmt = const_cast<Stmt *>(S.getAssociatedStmt());
if (auto *AssocStmt = dyn_cast<CapturedStmt>(AssociatedStmt))
if (auto *InnerCapturedStmt =
dyn_cast<CapturedStmt>(AssocStmt->getCapturedStmt())) {
AssociatedStmt = InnerCapturedStmt;
}
CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
if (!CapturedStmtInfo)
CapturedStmtInfo = &CapStmtInfo;

if (!Clauses.empty()) {
if (S.hasClausesOfKind<OMPDependClause>())
EmitOMPDispatchToTaskwaitDirective(S);

if (S.hasClausesOfKind<OMPNovariantsClause>() ||
S.hasClausesOfKind<OMPNocontextClause>()) {
Expr *Condition = nullptr;
if (const OMPNovariantsClause *NoVariantsC =
OMPExecutableDirective::getSingleClause<OMPNovariantsClause>(
Clauses)) {
Condition =
getCapturedExprFromImplicitCastExpr(NoVariantsC->getCondition());
} else {
const OMPNocontextClause *NoContextC =
OMPExecutableDirective::getSingleClause<OMPNocontextClause>(
Clauses);
Condition =
getCapturedExprFromImplicitCastExpr(NoContextC->getCondition());
}
/* OMPC_novariants or OMPC_nocontext present */
EmitIfElse(this, Condition, AssociatedStmt);
}
} else
EmitStmt(AssociatedStmt);
}

static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
Expand Down Expand Up @@ -5549,6 +5660,15 @@ void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier);
}

void CodeGenFunction::EmitOMPDispatchToTaskwaitDirective(
const OMPDispatchDirective &S) {
OMPTaskDataTy Data;
// Build list of dependences
buildDependences(S, Data);
Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
}

void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
OMPTaskDataTy Data;
// Build list of dependences
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3663,6 +3663,8 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = {});

void EmitOMPDispatchToTaskwaitDirective(const OMPDispatchDirective &S);

/// Controls insertion of cancellation exit blocks in worksharing constructs.
class OMPCancelStackRAII {
CodeGenFunction &CGF;
Expand Down Expand Up @@ -3855,6 +3857,7 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitOMPSectionDirective(const OMPSectionDirective &S);
void EmitOMPSingleDirective(const OMPSingleDirective &S);
void EmitOMPMasterDirective(const OMPMasterDirective &S);
void EmitOMPDispatchDirective(const OMPDispatchDirective &S);
void EmitOMPMaskedDirective(const OMPMaskedDirective &S);
void EmitOMPCriticalDirective(const OMPCriticalDirective &S);
void EmitOMPParallelForDirective(const OMPParallelForDirective &S);
Expand Down
Loading