[clang] [llvm] [Clang][OpenMP] Support for dispatch construct (Sema & Codegen) support (PR #117904)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 18 03:06:13 PST 2024
https://github.com/SunilKuravinakop updated https://github.com/llvm/llvm-project/pull/117904
>From 1703aa62cfe35538aedbacb28e907535e838248c Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Fri, 20 Sep 2024 01:41:29 -0500
Subject: [PATCH 01/10] Support for dispatch construct (Sema & Codegen)
support. Support for clauses depend, novariants & nocontext.
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 +
clang/include/clang/Basic/OpenMPKinds.h | 6 +
clang/include/clang/Sema/SemaOpenMP.h | 7 +
clang/lib/Basic/OpenMPKinds.cpp | 5 +
clang/lib/CodeGen/CGStmt.cpp | 2 +-
clang/lib/CodeGen/CGStmtOpenMP.cpp | 4 +
clang/lib/CodeGen/CodeGenFunction.h | 1 +
clang/lib/Sema/SemaOpenMP.cpp | 301 ++++++++++++++-
clang/test/OpenMP/dispatch_codegen.cpp | 359 ++++++++++++++++++
clang/test/OpenMP/dispatch_unsupported.c | 7 -
.../include/llvm/Frontend/OpenMP/OMPContext.h | 6 +
11 files changed, 687 insertions(+), 14 deletions(-)
create mode 100644 clang/test/OpenMP/dispatch_codegen.cpp
delete mode 100644 clang/test/OpenMP/dispatch_unsupported.c
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8495884dcd058f..81b876f9fd85c5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11774,6 +11774,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<
+ "only 'novariants' clause is supported when 'novariants' & 'nocontext' clauses occur on the same dispatch construct">,
+ 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<
diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index 900ad6ca6d66f6..7579fab43dbb19 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -269,6 +269,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
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 3d1cc4fab1c10f..80cee9e7583051 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -1462,6 +1462,13 @@ class SemaOpenMP : public SemaBase {
: OMPDeclareVariantScopes.back().TI;
}
+ StmtResult transformDispatchDirective(OpenMPDirectiveKind Kind,
+ const DeclarationNameInfo &DirName,
+ OpenMPDirectiveKind CancelRegion,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
/// The current `omp begin/end declare variant` scopes.
SmallVector<OMPDeclareVariantScope, 4> OMPDeclareVariantScopes;
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 62a13f01481b28..44ee63df46adb5 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -621,6 +621,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_target);
+}
+
bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_target ||
llvm::is_contained(getLeafConstructs(DKind), OMPD_target);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 698baf853507f4..f3eedb79844378 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -417,7 +417,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));
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 6cb37b20b7aeee..f3f2f54b068263 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4452,6 +4452,10 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
emitMaster(*this, S);
}
+void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) {
+ EmitStmt(S.getAssociatedStmt());
+}
+
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index eaea0d8a08ac06..2e342bc00a94a8 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3830,6 +3830,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);
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 66ff92f554fc42..28a84a52d8d790 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -4205,6 +4205,8 @@ static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
SmallVector<llvm::omp::TraitProperty, 8> Traits;
if (isOpenMPTargetExecutionDirective(DKind))
Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
+ if (isOpenMPDispatchDirective(DKind))
+ Traits.emplace_back(llvm::omp::TraitProperty::construct_dispatch_dispatch);
if (isOpenMPTeamsDirective(DKind))
Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
if (isOpenMPParallelDirective(DKind))
@@ -5965,6 +5967,263 @@ static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
return Checker.teamsLoopCanBeParallelFor();
}
+static Expr *getInitialExprFromCapturedExpr(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 nullptr;
+}
+
+// Next two functions, cloneAssociatedStmt() &
+// replaceWithNewTraitsOrDirectCall(), are for transforming the call traits.
+// e.g.
+// #pragma omp declare variant(foo_variant_dispatch) match(construct={dispatch})
+// #pragma omp declare variant(foo_variant_allCond) match(user={condition(1)})
+// ..
+// #pragma omp dispatch nocontext(cond_true)
+// foo(i, j);
+// is changed to:
+// if (cond_true) {
+// foo(i,j) // with traits: CodeGen call to foo_variant_allCond(i,j)
+// } else {
+// #pragma omp dispatch
+// foo(i,j) // with traits: CodeGen call to foo_variant_dispatch(i,j)
+// }
+//
+// The next 2 functions, are for:
+// if (cond_true) {
+// foo(i,j) // with traits: runtime call to foo_variant_allCond(i,j)
+// }
+//
+static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context, Expr *,
+ SemaOpenMP *, bool);
+
+static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP,
+ SemaOpenMP *SemaPtr, bool NoContext) {
+ if (CapturedStmt *AssocStmt = dyn_cast<CapturedStmt>(StmtP)) {
+ CapturedDecl *CDecl = AssocStmt->getCapturedDecl();
+ Stmt *AssocExprStmt = AssocStmt->getCapturedStmt();
+ Expr *AssocExpr = dyn_cast<Expr>(AssocExprStmt);
+ Expr *NewCallOrPseudoObjOrBinExpr = replaceWithNewTraitsOrDirectCall(
+ Context, AssocExpr, SemaPtr, NoContext);
+
+ // Copy Current Captured Decl to a New Captured Decl for noting the
+ // Annotation
+ CapturedDecl *NewDecl =
+ CapturedDecl::Create(const_cast<ASTContext &>(Context),
+ CDecl->getDeclContext(), CDecl->getNumParams());
+ NewDecl->setBody(static_cast<Stmt *>(NewCallOrPseudoObjOrBinExpr));
+ for (unsigned i = 0; i < CDecl->getNumParams(); ++i) {
+ if (i != CDecl->getContextParamPosition())
+ NewDecl->setParam(i, CDecl->getParam(i));
+ else
+ NewDecl->setContextParam(i, CDecl->getContextParam());
+ }
+
+ // Create a New Captured Stmt containing the New Captured Decl
+ SmallVector<CapturedStmt::Capture, 4> Captures;
+ SmallVector<Expr *, 4> CaptureInits;
+ for (auto capture : AssocStmt->captures())
+ Captures.push_back(capture);
+ for (auto capture_init : AssocStmt->capture_inits())
+ CaptureInits.push_back(capture_init);
+ CapturedStmt *NewStmt = CapturedStmt::Create(
+ Context, AssocStmt->getCapturedStmt(),
+ AssocStmt->getCapturedRegionKind(), Captures, CaptureInits, NewDecl,
+ const_cast<RecordDecl *>(AssocStmt->getCapturedRecordDecl()));
+
+ return NewStmt;
+ }
+ return static_cast<Stmt *>(nullptr);
+}
+
+static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context,
+ Expr *AssocExpr,
+ SemaOpenMP *SemaPtr,
+ bool NoContext) {
+ BinaryOperator *BinaryCopyOpr = nullptr;
+ bool IsBinaryOp = false;
+ Expr *PseudoObjExprOrCall = AssocExpr;
+ if (BinaryOperator *BinOprExpr = dyn_cast<BinaryOperator>(AssocExpr)) {
+ IsBinaryOp = true;
+ BinaryCopyOpr = BinaryOperator::Create(
+ Context, BinOprExpr->getLHS(), BinOprExpr->getRHS(),
+ BinOprExpr->getOpcode(), BinOprExpr->getType(),
+ BinOprExpr->getValueKind(), BinOprExpr->getObjectKind(),
+ BinOprExpr->getOperatorLoc(), FPOptionsOverride());
+ PseudoObjExprOrCall = BinaryCopyOpr->getRHS();
+ }
+
+ Expr *CallWithoutInvariants = PseudoObjExprOrCall;
+ // Change PseudoObjectExpr to a direct call
+ if (PseudoObjectExpr *PseudoObjExpr =
+ dyn_cast<PseudoObjectExpr>(PseudoObjExprOrCall))
+ CallWithoutInvariants = *((PseudoObjExpr->semantics_begin()) - 1);
+
+ Expr *FinalCall = CallWithoutInvariants; // For noinvariants clause
+ if (NoContext) {
+ // Convert StmtResult to a CallExpr before calling ActOnOpenMPCall()
+ CallExpr *CallExprWithinStmt = dyn_cast<CallExpr>(CallWithoutInvariants);
+ int NumArgs = CallExprWithinStmt->getNumArgs();
+ clang::Expr **Args = CallExprWithinStmt->getArgs();
+ // ActOnOpenMPCall() adds traits to a simple function call
+ // e.g. invariant function call traits to "foo(i,j)", if they are present.
+ ExprResult ER = SemaPtr->ActOnOpenMPCall(
+ CallExprWithinStmt, SemaPtr->SemaRef.getCurScope(),
+ CallExprWithinStmt->getBeginLoc(), MultiExprArg(Args, NumArgs),
+ CallExprWithinStmt->getRParenLoc(), static_cast<Expr *>(nullptr));
+ FinalCall = ER.get();
+ }
+
+ if (IsBinaryOp) {
+ BinaryCopyOpr->setRHS(FinalCall);
+ return BinaryCopyOpr;
+ }
+
+ return FinalCall;
+}
+
+static StmtResult combine2Stmts(ASTContext &Context, Stmt *FirstStmt,
+ Stmt *SecondStmt) {
+
+ llvm::SmallVector<Stmt *, 2> NewCombinedStmtVector;
+ NewCombinedStmtVector.push_back(FirstStmt);
+ NewCombinedStmtVector.push_back(SecondStmt);
+ CompoundStmt *CombinedStmt = CompoundStmt::Create(
+ Context, llvm::ArrayRef<Stmt *>(NewCombinedStmtVector),
+ FPOptionsOverride(), SourceLocation(), SourceLocation());
+ StmtResult FinalStmts(CombinedStmt);
+ return FinalStmts;
+}
+
+template <typename SpecificClause>
+static bool hasClausesOfKind(ArrayRef<OMPClause *> Clauses) {
+ auto ClausesOfKind =
+ OMPExecutableDirective::getClausesOfKind<SpecificClause>(Clauses);
+ return ClausesOfKind.begin() != ClausesOfKind.end();
+}
+
+StmtResult SemaOpenMP::transformDispatchDirective(
+ OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+ OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
+
+ StmtResult RetValue;
+ llvm::SmallVector<OMPClause *, 8> DependVector;
+ for (const OMPDependClause *ConstDependClause :
+ OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)) {
+ OMPDependClause *DependClause =
+ const_cast<OMPDependClause *>(ConstDependClause);
+ DependVector.push_back(DependClause);
+ }
+ llvm::ArrayRef<OMPClause *> DependCArray(DependVector);
+
+ // #pragma omp dispatch depend() is changed to #pragma omp taskwait depend()
+ // This is done by calling ActOnOpenMPExecutableDirective() for the
+ // new taskwait directive.
+ StmtResult DispatchDepend2taskwait =
+ ActOnOpenMPExecutableDirective(OMPD_taskwait, DirName, CancelRegion,
+ DependCArray, NULL, StartLoc, EndLoc);
+
+ if (OMPExecutableDirective::getSingleClause<OMPNovariantsClause>(Clauses)) {
+
+ if (OMPExecutableDirective::getSingleClause<OMPNocontextClause>(Clauses)) {
+ Diag(StartLoc, diag::warn_omp_dispatch_clause_novariants_nocontext);
+ }
+
+ const OMPNovariantsClause *NoVariantsC =
+ OMPExecutableDirective::getSingleClause<OMPNovariantsClause>(Clauses);
+ // #pragma omp dispatch novariants(c2) depend(out: x)
+ // foo();
+ // becomes:
+ // #pragma omp taskwait depend(out: x)
+ // if (c2) {
+ // foo();
+ // } else {
+ // #pragma omp dispatch
+ // foo(); <--- foo() is replaced with foo_variant() in CodeGen
+ // }
+ Expr *Cond = getInitialExprFromCapturedExpr(NoVariantsC->getCondition());
+ StmtResult ThenStmt =
+ cloneAssociatedStmt(getASTContext(), AStmt, this, false);
+ SmallVector<OMPClause *, 5> DependClauses;
+ StmtResult ElseStmt = ActOnOpenMPExecutableDirective(
+ Kind, DirName, CancelRegion, DependClauses, AStmt, StartLoc, EndLoc);
+ IfStmt *IfElseStmt =
+ IfStmt::Create(getASTContext(), StartLoc, IfStatementKind::Ordinary,
+ nullptr, // Init
+ nullptr, // Condition Var Declaration
+ Cond,
+ StartLoc, // Source Location Left Paranthesis
+ StartLoc, // Source Location Right Paranthesis
+ ThenStmt.get(), StartLoc, ElseStmt.get());
+ if (hasClausesOfKind<OMPDependClause>(Clauses)) {
+ StmtResult FinalStmts = combine2Stmts(
+ getASTContext(), DispatchDepend2taskwait.get(), IfElseStmt);
+ RetValue = FinalStmts;
+ } else {
+ RetValue = IfElseStmt;
+ }
+ } else if (OMPExecutableDirective::getSingleClause<OMPNocontextClause>(
+ Clauses)) {
+
+ const OMPNocontextClause *NoContextC =
+ OMPExecutableDirective::getSingleClause<OMPNocontextClause>(Clauses);
+ Expr *Cond = getInitialExprFromCapturedExpr(NoContextC->getCondition());
+ // #pragma omp dispatch depend(out: x) nocontext(c2)
+ // foo();
+ // becomes:
+ // #pragma omp taskwait depend(out: x)
+ // if (c2) {
+ // foo();
+ // } else {
+ // #pragma omp dispatch
+ // foo();
+ // }
+
+ StmtResult ThenStmt =
+ cloneAssociatedStmt(getASTContext(), AStmt, this, true);
+
+ SmallVector<OMPClause *, 5> DependClauses;
+ StmtResult ElseStmt = ActOnOpenMPExecutableDirective(
+ Kind, DirName, CancelRegion, DependClauses, AStmt, StartLoc, EndLoc);
+ IfStmt *IfElseStmt =
+ IfStmt::Create(getASTContext(), StartLoc, IfStatementKind::Ordinary,
+ nullptr, // Init
+ nullptr, // Condition Var Declaration
+ Cond,
+ StartLoc, // Source Location Left Paranthesis
+ StartLoc, // Source Location Right Paranthesis
+ ThenStmt.get(), StartLoc, ElseStmt.get());
+ if (hasClausesOfKind<OMPDependClause>(Clauses)) {
+ StmtResult FinalStmts = combine2Stmts(
+ getASTContext(), DispatchDepend2taskwait.get(), IfElseStmt);
+ RetValue = FinalStmts;
+ } else {
+ RetValue = IfElseStmt;
+ }
+ } else if (hasClausesOfKind<OMPDependClause>(Clauses)) {
+ // Only:
+ // #pragma omp dispatch depend(out: x)
+ // foo();
+ // to
+ // #pragma omp taskwait depend(out: x)
+ // foo();
+ StmtResult FinalStmts =
+ combine2Stmts(getASTContext(), DispatchDepend2taskwait.get(), AStmt);
+ RetValue = FinalStmts;
+ }
+ return RetValue;
+}
+
StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
@@ -5979,6 +6238,20 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
BindKind = BC->getBindKind();
+ if ((Kind == OMPD_dispatch) && (Clauses.size() > 0)) {
+
+ bool UnSupportedClause = false;
+ for (OMPClause *C : Clauses) {
+ if (!((C->getClauseKind() == OMPC_novariants) ||
+ (C->getClauseKind() == OMPC_nocontext) ||
+ (C->getClauseKind() == OMPC_depend)))
+ UnSupportedClause = true;
+ }
+ if (!UnSupportedClause)
+ return transformDispatchDirective(Kind, DirName, CancelRegion, Clauses,
+ AStmt, StartLoc, EndLoc);
+ }
+
if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
@@ -7209,8 +7482,10 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
Exprs.erase(Exprs.begin() + BestIdx);
} while (!VMIs.empty());
- if (!NewCall.isUsable())
+ if (!NewCall.isUsable()) {
+ fprintf(stdout, "Returning Call, NewCall is not usable\n");
return Call;
+ }
return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
}
@@ -10520,11 +10795,22 @@ StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
DSAStack->isCancelRegion());
}
+// PseudoObjectExpr is a Trait for dispatch containing the
+// function and its variant. Returning only the function.
+static Expr *RemovePseudoObjectExpr(Expr *PseudoObjExprOrDirectCall) {
+ Expr *DirectCallExpr = PseudoObjExprOrDirectCall;
+ if (PseudoObjectExpr *PseudoObjExpr =
+ dyn_cast<PseudoObjectExpr>(PseudoObjExprOrDirectCall))
+ DirectCallExpr = *((PseudoObjExpr->semantics_begin()) - 1);
+ return DirectCallExpr;
+}
+
static Expr *getDirectCallExpr(Expr *E) {
- E = E->IgnoreParenCasts()->IgnoreImplicit();
- if (auto *CE = dyn_cast<CallExpr>(E))
+ Expr *PseudoObjExpr = E->IgnoreParenCasts()->IgnoreImplicit();
+ Expr *DirectCallExpr = RemovePseudoObjectExpr(PseudoObjExpr);
+ if (auto *CE = dyn_cast<CallExpr>(DirectCallExpr))
if (CE->getDirectCallee())
- return E;
+ return DirectCallExpr;
return nullptr;
}
@@ -10556,15 +10842,18 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
E = E->IgnoreParenCasts()->IgnoreImplicit();
if (auto *BO = dyn_cast<BinaryOperator>(E)) {
- if (BO->getOpcode() == BO_Assign)
+ if (BO->getOpcode() == BO_Assign) {
TargetCall = getDirectCallExpr(BO->getRHS());
+ }
} else {
if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
if (COCE->getOperator() == OO_Equal)
TargetCall = getDirectCallExpr(COCE->getArg(1));
- if (!TargetCall)
+ if (!TargetCall) {
TargetCall = getDirectCallExpr(E);
+ }
}
+
if (!TargetCall) {
Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
return StmtError();
diff --git a/clang/test/OpenMP/dispatch_codegen.cpp b/clang/test/OpenMP/dispatch_codegen.cpp
new file mode 100644
index 00000000000000..3a50ccbb99873a
--- /dev/null
+++ b/clang/test/OpenMP/dispatch_codegen.cpp
@@ -0,0 +1,359 @@
+// expected-no-diagnostics
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+int foo_variant_dispatch(int x, int y) {
+ return x+2;
+}
+
+int foo_variant_allCond(int x, int y) {
+ return x+3;
+}
+
+#pragma omp declare variant(foo_variant_dispatch) match(construct={dispatch})
+#pragma omp declare variant(foo_variant_allCond) match(user={condition(1)})
+int foo(int x, int y) {
+ // Original implementation of foo
+ return x+1;
+}
+
+void checkNoVariants();
+void checkNoContext();
+void checkDepend();
+
+void declareVariant1()
+{
+ int cond_false = 0, cond_true = 1;
+
+ int x = 0;
+ int y = 0;
+ int output = 0;
+
+ foo(x,y);
+
+ #pragma omp dispatch
+ output = foo(x,y);
+
+ checkNoVariants();
+ checkNoContext();
+ checkDepend();
+}
+
+void checkNoVariants()
+{
+ int cond_false = 0, cond_true = 1;
+
+ int x = 0;
+ int y = 0;
+ int output = 0;
+
+ #pragma omp dispatch novariants(cond_false)
+ foo(x,y);
+
+ #pragma omp dispatch novariants(cond_true)
+ output = foo(x,y);
+}
+
+void checkNoContext()
+{
+ int cond_false = 0, cond_true = 1;
+
+ int x = 0;
+ int y = 0;
+ int output = 0;
+
+ #pragma omp dispatch nocontext(cond_false)
+ foo(x,y);
+
+ #pragma omp dispatch nocontext(cond_true)
+ output = foo(x,y);
+
+}
+
+void checkDepend()
+{
+ int cond_false = 0, cond_true = 1;
+
+ int x = 0;
+ int y = 0;
+ int output = 0;
+
+ #pragma omp dispatch depend(out:x)
+ output = foo(x,y);
+
+ #pragma omp dispatch depend(out:x) depend(out:y)
+ output = foo(x,y);
+
+ #pragma omp dispatch depend(out:x) novariants(cond_false)
+ output = foo(x,y);
+
+ #pragma omp dispatch depend(out:x) nocontext(cond_false)
+ foo(x,y);
+}
+
+int bar_variant(int x) {
+ return x+2;
+}
+
+int bar(int x) {
+ return x+1;
+}
+
+void checkNoContext_withoutVariant();
+void checkNoVariants_withoutVariant();
+
+int without_declareVariant()
+{
+ int cond_false = 0, cond_true = 1;
+
+ int x = 0;
+ int output = 0;
+
+ bar(x);
+
+ #pragma omp dispatch
+ bar(x);
+
+ checkNoVariants_withoutVariant();
+ checkNoContext_withoutVariant();
+ return 1;
+}
+
+void checkNoVariants_withoutVariant() {
+ int cond_false = 0, cond_true = 1;
+
+ int x = 0;
+ int output = 0;
+
+ #pragma omp dispatch novariants(cond_true)
+ output = bar(x);
+
+ #pragma omp dispatch novariants(cond_false)
+ bar(x);
+}
+
+void checkNoContext_withoutVariant() {
+ int cond_false = 0, cond_true = 1;
+
+ int x = 0;
+ int output = 0;
+
+ #pragma omp dispatch nocontext(cond_true)
+ output = bar(x);
+
+ #pragma omp dispatch nocontext(cond_false)
+ bar(x);
+}
+
+// CHECK-LABEL: define {{.+}}declareVariant{{.+}}
+// CHECK-LABEL: entry:
+//
+// #pragma omp dispatch
+// CHECK: call {{.+}}foo_variant_allCond{{.+}}
+// CHECK: call {{.+}}captured_stmt{{.+}}
+// CHECK-NEXT: call {{.+}}checkNoVariants{{.+}}
+// CHECK-NEXT: call {{.+}}checkNoContext{{.+}}
+// CHECK-NEXT: call {{.+}}checkDepend{{.+}}
+// CHECK-NEXT: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: {{.+}}checkNoVariants{{.+}}
+// CHECK-LABEL: entry:
+// #pragma omp dispatch novariants(cond_false)
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.1{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.2{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+//
+// #pragma omp dispatch novariants(cond_true)
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.3{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.4{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+//
+// CHECK-LABEL: {{.+}}checkNoContext{{.+}}
+// CHECK-LABEL: entry:
+//
+// #pragma omp dispatch nocontext(cond_false)
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.5{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.6{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+//
+// #pragma omp dispatch nocontext(cond_true)
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.7{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.8{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+//
+// CHECK-LABEL: {{.+}}checkDepend{{.+}}
+// CHECK-LABEL: entry:
+//
+// #pragma omp dispatch depend(out:x)
+// CHECK: call {{.+}}kmpc_omp_taskwait_deps{{.+}}
+// CHECK: call {{.+}}captured_stmt.9{{.+}}
+//
+// #pragma omp dispatch depend(out:x) depend(out:y)
+// CHECK: call {{.+}}kmpc_omp_taskwait_deps{{.+}}
+// CHECK: call {{.+}}captured_stmt.10{{.+}}
+//
+// #pragma omp dispatch depend(out:x) novariants(cond_false)
+// CHECK: call {{.+}}kmpc_omp_taskwait_deps{{.+}}
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.11{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.12{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+//
+// #pragma omp dispatch depend(out:x) nocontext(cond_false)
+// CHECK: call {{.+}}kmpc_omp_taskwait_deps{{.+}}
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.13{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.14{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.1{{.+}}
+// CHECK: call {{.+}}foo{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.2{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.3{{.+}}
+// CHECK: call {{.+}}foo{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.4{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.5{{.+}}
+// CHECK: call {{.+}}foo_variant_allCond{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.6{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.7{{.+}}
+// CHECK: call {{.+}}foo_variant_allCond{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.8{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.9{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.10{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.11{{.+}}
+// CHECK: call {{.+}}foo{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.12{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.13{{.+}}
+// CHECK: call {{.+}}foo_variant_allCond{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}__captured_stmt.14{{.+}}
+// CHECK: call {{.+}}foo_variant_dispatch{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}bar_variant{{.+}}
+// CHECK-LABEL: entry:
+// CHECK: ret{{.+}}
+//
+// CHECK-LABEL: define {{.+}}bar{{.+}}
+// CHECK-LABEL: entry:
+// CHECK: ret{{.+}}
+
+// CHECK-LABEL: define {{.+}}without_declareVariant{{.+}}
+// CHECK-LABEL: entry:
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: call {{.+}}captured_stmt.15{{.+}}
+// CHECK-NEXT: call {{.+}}checkNoVariants_withoutVariant{{.+}}
+// CHECK-NEXT: call {{.+}}checkNoContext_withoutVariant{{.+}}
+// CHECK-NEXT: ret{{.+}}
+//
+// #pragma omp dispatch
+// CHECK-LABEL: define {{.+}}__captured_stmt.15{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+//
+// CHECK-LABEL: define {{.+}}checkNoVariants_withoutVariant{{.+}}
+// CHECK-LABEL: entry:
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.16{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.17{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.18{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.19{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+// CHECK: ret{{.+}}
+//
+// CHECK-LABEL: define {{.+}}checkNoContext_withoutVariant{{.+}}
+// CHECK-LABEL: entry:
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.20{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.21{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+// CHECK-LABEL: if.then{{.+}}
+// CHECK: call {{.+}}captured_stmt.22{{.+}}
+// CHECK-LABEL: if.else{{.+}}
+// CHECK: call {{.+}}captured_stmt.23{{.+}}
+// CHECK-LABEL: if.end{{.+}}
+// CHECK: ret{{.+}}
+//
+// #pragma omp dispatch novariants(cond_true)
+// CHECK-LABEL: define {{.+}}__captured_stmt.16{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+// CHECK-LABEL: define {{.+}}__captured_stmt.17{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+//
+// #pragma omp dispatch novariants(cond_false)
+// CHECK-LABEL: define {{.+}}__captured_stmt.18{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+// CHECK-LABEL: define {{.+}}__captured_stmt.19{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+//
+// #pragma omp dispatch nocontext(cond_true)
+// CHECK-LABEL: define {{.+}}__captured_stmt.20{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+// CHECK-LABEL: define {{.+}}__captured_stmt.21{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+//
+// #pragma omp dispatch nocontext(cond_false)
+// CHECK-LABEL: define {{.+}}__captured_stmt.22{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
+// CHECK-LABEL: define {{.+}}__captured_stmt.23{{.+}}
+// CHECK: call {{.+}}bar{{.+}}
+// CHECK: ret void
diff --git a/clang/test/OpenMP/dispatch_unsupported.c b/clang/test/OpenMP/dispatch_unsupported.c
deleted file mode 100644
index fe7ccfa90a5831..00000000000000
--- a/clang/test/OpenMP/dispatch_unsupported.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm -fopenmp -disable-llvm-passes %s -o /dev/null -verify=expected
-
-// expected-error at +2 {{cannot compile this OpenMP dispatch directive yet}}
-void a(){
- #pragma omp dispatch
- a();
-}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
index b13b74ceab8651..9ca7bf332f9519 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
@@ -141,6 +141,12 @@ struct VariantMatchInfo {
ISATraits.push_back(RawString);
RequiredTraits.set(unsigned(Property));
+#if 0
+ unsigned int i = 0;
+ for (unsigned Bit : RequiredTraits.set_bits()) {
+ i++;
+ }
+#endif
if (Set == TraitSet::construct)
ConstructTraits.push_back(Property);
}
>From 5ae3ffe4217517c7b442ff64094b2c3e01638063 Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Mon, 9 Dec 2024 04:40:16 -0600
Subject: [PATCH 02/10] Taking care of feedback comments from Alexey Bataev. 1)
Changing comments from // to /// 2) Using STLExtras like
llvm::is_contained(). 3) Insteading of combining function comments for 2
functions provided them separately before the function definitions.
---
clang/lib/Basic/OpenMPKinds.cpp | 2 +-
clang/lib/Sema/SemaOpenMP.cpp | 95 ++++++++++++++++-----------------
2 files changed, 47 insertions(+), 50 deletions(-)
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 44ee63df46adb5..45ed0cae2aff26 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -623,7 +623,7 @@ bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
bool clang::isOpenMPDispatchDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_dispatch ||
- llvm::is_contained(getLeafConstructs(DKind), OMPD_target);
+ llvm::is_contained(getLeafConstructs(DKind), OMPD_dispatch);
}
bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 28a84a52d8d790..affadbf873fb4b 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5982,36 +5982,18 @@ static Expr *getInitialExprFromCapturedExpr(Expr *Cond) {
return nullptr;
}
-// Next two functions, cloneAssociatedStmt() &
-// replaceWithNewTraitsOrDirectCall(), are for transforming the call traits.
-// e.g.
-// #pragma omp declare variant(foo_variant_dispatch) match(construct={dispatch})
-// #pragma omp declare variant(foo_variant_allCond) match(user={condition(1)})
-// ..
-// #pragma omp dispatch nocontext(cond_true)
-// foo(i, j);
-// is changed to:
-// if (cond_true) {
-// foo(i,j) // with traits: CodeGen call to foo_variant_allCond(i,j)
-// } else {
-// #pragma omp dispatch
-// foo(i,j) // with traits: CodeGen call to foo_variant_dispatch(i,j)
-// }
-//
-// The next 2 functions, are for:
-// if (cond_true) {
-// foo(i,j) // with traits: runtime call to foo_variant_allCond(i,j)
-// }
-//
static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context, Expr *,
SemaOpenMP *, bool);
+/// cloneAssociatedStmt() function is for cloning the Associated Statement
+/// present with a Directive and then modifying it. By this we avoid modifying
+/// the original Associated Statement.
static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP,
SemaOpenMP *SemaPtr, bool NoContext) {
- if (CapturedStmt *AssocStmt = dyn_cast<CapturedStmt>(StmtP)) {
+ if (auto *AssocStmt = dyn_cast<CapturedStmt>(StmtP)) {
CapturedDecl *CDecl = AssocStmt->getCapturedDecl();
Stmt *AssocExprStmt = AssocStmt->getCapturedStmt();
- Expr *AssocExpr = dyn_cast<Expr>(AssocExprStmt);
+ auto *AssocExpr = dyn_cast<Expr>(AssocExprStmt);
Expr *NewCallOrPseudoObjOrBinExpr = replaceWithNewTraitsOrDirectCall(
Context, AssocExpr, SemaPtr, NoContext);
@@ -6021,21 +6003,21 @@ static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP,
CapturedDecl::Create(const_cast<ASTContext &>(Context),
CDecl->getDeclContext(), CDecl->getNumParams());
NewDecl->setBody(static_cast<Stmt *>(NewCallOrPseudoObjOrBinExpr));
- for (unsigned i = 0; i < CDecl->getNumParams(); ++i) {
- if (i != CDecl->getContextParamPosition())
- NewDecl->setParam(i, CDecl->getParam(i));
+ for (unsigned I : llvm::seq<unsigned>(CDecl->getNumParams())) {
+ if (I != CDecl->getContextParamPosition())
+ NewDecl->setParam(I, CDecl->getParam(I));
else
- NewDecl->setContextParam(i, CDecl->getContextParam());
+ NewDecl->setContextParam(I, CDecl->getContextParam());
}
// Create a New Captured Stmt containing the New Captured Decl
SmallVector<CapturedStmt::Capture, 4> Captures;
SmallVector<Expr *, 4> CaptureInits;
- for (auto capture : AssocStmt->captures())
- Captures.push_back(capture);
- for (auto capture_init : AssocStmt->capture_inits())
- CaptureInits.push_back(capture_init);
- CapturedStmt *NewStmt = CapturedStmt::Create(
+ for (const CapturedStmt::Capture &Capture : AssocStmt->captures())
+ Captures.push_back(Capture);
+ for (Expr *CaptureInit : AssocStmt->capture_inits())
+ CaptureInits.push_back(CaptureInit);
+ auto *NewStmt = CapturedStmt::Create(
Context, AssocStmt->getCapturedStmt(),
AssocStmt->getCapturedRegionKind(), Captures, CaptureInits, NewDecl,
const_cast<RecordDecl *>(AssocStmt->getCapturedRecordDecl()));
@@ -6045,6 +6027,26 @@ static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP,
return static_cast<Stmt *>(nullptr);
}
+/// replaceWithNewTraitsOrDirectCall() is for transforming the call traits.
+/// Call traits associated with a function call are removed and replaced with
+/// a direct call. For clause "nocontext" only, the direct call is then
+/// modified to have call traits for a non-dispatch variant.
+/// For "nocontext" an example is provided below for clear understanding.
+///
+/// #pragma omp declare variant(foo_variant_dispatch)
+/// match(construct={dispatch}) #pragma omp declare variant(foo_variant_allCond)
+/// match(user={condition(1)})
+/// ...
+/// #pragma omp dispatch nocontext(cond_true)
+/// foo(i, j); // with traits: CodeGen call to foo_variant_dispatch(i,j)
+/// dispatch construct is changed to:
+/// if (cond_true) {
+/// foo(i,j) // with traits: CodeGen call to foo_variant_allCond(i,j)
+/// } else {
+/// #pragma omp dispatch
+/// foo(i,j) // with traits: CodeGen call to foo_variant_dispatch(i,j)
+/// }
+///
static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context,
Expr *AssocExpr,
SemaOpenMP *SemaPtr,
@@ -6052,7 +6054,7 @@ static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context,
BinaryOperator *BinaryCopyOpr = nullptr;
bool IsBinaryOp = false;
Expr *PseudoObjExprOrCall = AssocExpr;
- if (BinaryOperator *BinOprExpr = dyn_cast<BinaryOperator>(AssocExpr)) {
+ if (auto *BinOprExpr = dyn_cast<BinaryOperator>(AssocExpr)) {
IsBinaryOp = true;
BinaryCopyOpr = BinaryOperator::Create(
Context, BinOprExpr->getLHS(), BinOprExpr->getRHS(),
@@ -6064,14 +6066,13 @@ static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context,
Expr *CallWithoutInvariants = PseudoObjExprOrCall;
// Change PseudoObjectExpr to a direct call
- if (PseudoObjectExpr *PseudoObjExpr =
- dyn_cast<PseudoObjectExpr>(PseudoObjExprOrCall))
+ if (auto *PseudoObjExpr = dyn_cast<PseudoObjectExpr>(PseudoObjExprOrCall))
CallWithoutInvariants = *((PseudoObjExpr->semantics_begin()) - 1);
Expr *FinalCall = CallWithoutInvariants; // For noinvariants clause
if (NoContext) {
// Convert StmtResult to a CallExpr before calling ActOnOpenMPCall()
- CallExpr *CallExprWithinStmt = dyn_cast<CallExpr>(CallWithoutInvariants);
+ auto *CallExprWithinStmt = cast<CallExpr>(CallWithoutInvariants);
int NumArgs = CallExprWithinStmt->getNumArgs();
clang::Expr **Args = CallExprWithinStmt->getArgs();
// ActOnOpenMPCall() adds traits to a simple function call
@@ -6097,7 +6098,7 @@ static StmtResult combine2Stmts(ASTContext &Context, Stmt *FirstStmt,
llvm::SmallVector<Stmt *, 2> NewCombinedStmtVector;
NewCombinedStmtVector.push_back(FirstStmt);
NewCombinedStmtVector.push_back(SecondStmt);
- CompoundStmt *CombinedStmt = CompoundStmt::Create(
+ auto *CombinedStmt = CompoundStmt::Create(
Context, llvm::ArrayRef<Stmt *>(NewCombinedStmtVector),
FPOptionsOverride(), SourceLocation(), SourceLocation());
StmtResult FinalStmts(CombinedStmt);
@@ -6240,14 +6241,11 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
if ((Kind == OMPD_dispatch) && (Clauses.size() > 0)) {
- bool UnSupportedClause = false;
- for (OMPClause *C : Clauses) {
- if (!((C->getClauseKind() == OMPC_novariants) ||
- (C->getClauseKind() == OMPC_nocontext) ||
- (C->getClauseKind() == OMPC_depend)))
- UnSupportedClause = true;
- }
- if (!UnSupportedClause)
+ if (llvm::all_of(Clauses, [](OMPClause *C) {
+ return llvm::is_contained(
+ {OMPC_novariants, OMPC_nocontext, OMPC_depend},
+ C->getClauseKind());
+ }))
return transformDispatchDirective(Kind, DirName, CancelRegion, Clauses,
AStmt, StartLoc, EndLoc);
}
@@ -7483,7 +7481,6 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
} while (!VMIs.empty());
if (!NewCall.isUsable()) {
- fprintf(stdout, "Returning Call, NewCall is not usable\n");
return Call;
}
return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
@@ -10795,11 +10792,11 @@ StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
DSAStack->isCancelRegion());
}
-// PseudoObjectExpr is a Trait for dispatch containing the
-// function and its variant. Returning only the function.
+/// PseudoObjectExpr is a Trait for dispatch containing the
+/// function and its variant. Returning only the function.
static Expr *RemovePseudoObjectExpr(Expr *PseudoObjExprOrDirectCall) {
Expr *DirectCallExpr = PseudoObjExprOrDirectCall;
- if (PseudoObjectExpr *PseudoObjExpr =
+ if (auto *PseudoObjExpr =
dyn_cast<PseudoObjectExpr>(PseudoObjExprOrDirectCall))
DirectCallExpr = *((PseudoObjExpr->semantics_begin()) - 1);
return DirectCallExpr;
>From daf681cc78cc497064b49116df9871a0a1347cdb Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Tue, 10 Dec 2024 12:23:50 -0600
Subject: [PATCH 03/10] Changed the comments for
replaceWithNewTraitsOrDirectCall().
---
clang/lib/Sema/SemaOpenMP.cpp | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index affadbf873fb4b..835a92776d0c10 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6031,22 +6031,6 @@ static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP,
/// Call traits associated with a function call are removed and replaced with
/// a direct call. For clause "nocontext" only, the direct call is then
/// modified to have call traits for a non-dispatch variant.
-/// For "nocontext" an example is provided below for clear understanding.
-///
-/// #pragma omp declare variant(foo_variant_dispatch)
-/// match(construct={dispatch}) #pragma omp declare variant(foo_variant_allCond)
-/// match(user={condition(1)})
-/// ...
-/// #pragma omp dispatch nocontext(cond_true)
-/// foo(i, j); // with traits: CodeGen call to foo_variant_dispatch(i,j)
-/// dispatch construct is changed to:
-/// if (cond_true) {
-/// foo(i,j) // with traits: CodeGen call to foo_variant_allCond(i,j)
-/// } else {
-/// #pragma omp dispatch
-/// foo(i,j) // with traits: CodeGen call to foo_variant_dispatch(i,j)
-/// }
-///
static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context,
Expr *AssocExpr,
SemaOpenMP *SemaPtr,
@@ -6071,6 +6055,24 @@ static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context,
Expr *FinalCall = CallWithoutInvariants; // For noinvariants clause
if (NoContext) {
+ // example to explain the changes done for "nocontext" clause:
+ //
+ // #pragma omp declare variant(foo_variant_dispatch)
+ // match(construct = {dispatch})
+ // #pragma omp declare variant(foo_variant_allCond)
+ // match(user = {condition(1)})
+ // ...
+ // #pragma omp dispatch nocontext(cond_true)
+ // foo(i, j); // with traits: CodeGen call to
+ // foo_variant_dispatch(i,j)
+ // dispatch construct is changed to:
+ // if (cond_true) {
+ // foo(i,j) // with traits: CodeGen call to foo_variant_allCond(i,j)
+ // } else {
+ // #pragma omp dispatch
+ // foo(i,j) // with traits: CodeGen call to foo_variant_dispatch(i,j)
+ // }
+
// Convert StmtResult to a CallExpr before calling ActOnOpenMPCall()
auto *CallExprWithinStmt = cast<CallExpr>(CallWithoutInvariants);
int NumArgs = CallExprWithinStmt->getNumArgs();
>From bc3c018fc9715f757a1163b82724a56b9c932098 Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Tue, 10 Dec 2024 12:49:39 -0600
Subject: [PATCH 04/10] Removing an unnecessary bracket in if statement in
ActOnOpenMPCall().
---
clang/lib/Sema/SemaOpenMP.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 835a92776d0c10..6bc17cea163343 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -7482,9 +7482,8 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
Exprs.erase(Exprs.begin() + BestIdx);
} while (!VMIs.empty());
- if (!NewCall.isUsable()) {
+ if (!NewCall.isUsable())
return Call;
- }
return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
}
>From b83e0baf49ec540dfaf9f6af1252dd5851472723 Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Tue, 10 Dec 2024 14:05:56 -0600
Subject: [PATCH 05/10] Removing unnecessary brackets around if statement.
Instead of using nullptr for initilizalition StmtResult using an
uninitialized StmtResult. Unnecessary StmtResult & llvm::ArrayRef variables.
---
clang/lib/Sema/SemaOpenMP.cpp | 35 +++++++++++++++--------------------
1 file changed, 15 insertions(+), 20 deletions(-)
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 6bc17cea163343..49d0562ea1a41b 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5990,6 +5990,7 @@ static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context, Expr *,
/// the original Associated Statement.
static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP,
SemaOpenMP *SemaPtr, bool NoContext) {
+ StmtResult ResultAssocStmt;
if (auto *AssocStmt = dyn_cast<CapturedStmt>(StmtP)) {
CapturedDecl *CDecl = AssocStmt->getCapturedDecl();
Stmt *AssocExprStmt = AssocStmt->getCapturedStmt();
@@ -6022,9 +6023,9 @@ static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP,
AssocStmt->getCapturedRegionKind(), Captures, CaptureInits, NewDecl,
const_cast<RecordDecl *>(AssocStmt->getCapturedRecordDecl()));
- return NewStmt;
+ ResultAssocStmt = NewStmt;
}
- return static_cast<Stmt *>(nullptr);
+ return ResultAssocStmt;
}
/// replaceWithNewTraitsOrDirectCall() is for transforming the call traits.
@@ -6103,8 +6104,7 @@ static StmtResult combine2Stmts(ASTContext &Context, Stmt *FirstStmt,
auto *CombinedStmt = CompoundStmt::Create(
Context, llvm::ArrayRef<Stmt *>(NewCombinedStmtVector),
FPOptionsOverride(), SourceLocation(), SourceLocation());
- StmtResult FinalStmts(CombinedStmt);
- return FinalStmts;
+ return CombinedStmt;
}
template <typename SpecificClause>
@@ -6120,21 +6120,19 @@ StmtResult SemaOpenMP::transformDispatchDirective(
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
StmtResult RetValue;
- llvm::SmallVector<OMPClause *, 8> DependVector;
+ llvm::SmallVector<OMPClause *, 8> DependClauseVector;
for (const OMPDependClause *ConstDependClause :
OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)) {
- OMPDependClause *DependClause =
- const_cast<OMPDependClause *>(ConstDependClause);
- DependVector.push_back(DependClause);
+ auto *DependClause = const_cast<OMPDependClause *>(ConstDependClause);
+ DependClauseVector.push_back(DependClause);
}
- llvm::ArrayRef<OMPClause *> DependCArray(DependVector);
// #pragma omp dispatch depend() is changed to #pragma omp taskwait depend()
// This is done by calling ActOnOpenMPExecutableDirective() for the
// new taskwait directive.
- StmtResult DispatchDepend2taskwait =
- ActOnOpenMPExecutableDirective(OMPD_taskwait, DirName, CancelRegion,
- DependCArray, NULL, StartLoc, EndLoc);
+ StmtResult DispatchDepend2taskwait = ActOnOpenMPExecutableDirective(
+ OMPD_taskwait, DirName, CancelRegion, DependClauseVector, NULL, StartLoc,
+ EndLoc);
if (OMPExecutableDirective::getSingleClause<OMPNovariantsClause>(Clauses)) {
@@ -6241,7 +6239,7 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
BindKind = BC->getBindKind();
- if ((Kind == OMPD_dispatch) && (Clauses.size() > 0)) {
+ if ((Kind == OMPD_dispatch) && (!Clauses.empty())) {
if (llvm::all_of(Clauses, [](OMPClause *C) {
return llvm::is_contained(
@@ -10795,7 +10793,7 @@ StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
/// PseudoObjectExpr is a Trait for dispatch containing the
/// function and its variant. Returning only the function.
-static Expr *RemovePseudoObjectExpr(Expr *PseudoObjExprOrDirectCall) {
+static Expr *removePseudoObjectExpr(Expr *PseudoObjExprOrDirectCall) {
Expr *DirectCallExpr = PseudoObjExprOrDirectCall;
if (auto *PseudoObjExpr =
dyn_cast<PseudoObjectExpr>(PseudoObjExprOrDirectCall))
@@ -10805,7 +10803,7 @@ static Expr *RemovePseudoObjectExpr(Expr *PseudoObjExprOrDirectCall) {
static Expr *getDirectCallExpr(Expr *E) {
Expr *PseudoObjExpr = E->IgnoreParenCasts()->IgnoreImplicit();
- Expr *DirectCallExpr = RemovePseudoObjectExpr(PseudoObjExpr);
+ Expr *DirectCallExpr = removePseudoObjectExpr(PseudoObjExpr);
if (auto *CE = dyn_cast<CallExpr>(DirectCallExpr))
if (CE->getDirectCallee())
return DirectCallExpr;
@@ -10840,18 +10838,15 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
E = E->IgnoreParenCasts()->IgnoreImplicit();
if (auto *BO = dyn_cast<BinaryOperator>(E)) {
- if (BO->getOpcode() == BO_Assign) {
+ if (BO->getOpcode() == BO_Assign)
TargetCall = getDirectCallExpr(BO->getRHS());
- }
} else {
if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
if (COCE->getOperator() == OO_Equal)
TargetCall = getDirectCallExpr(COCE->getArg(1));
- if (!TargetCall) {
+ if (!TargetCall)
TargetCall = getDirectCallExpr(E);
- }
}
-
if (!TargetCall) {
Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
return StmtError();
>From 997fe7c0b140da933f59fb1b9a56b1218e911f4a Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Sun, 15 Dec 2024 12:18:42 -0600
Subject: [PATCH 06/10] 1) Claiming support for "dispatch" construct. 2)
Changed comments in transformDispatchDirective() in SemaOpenMP.cpp 3) Adding
checks in clang/test/OpenMP/dispatch_messages.cpp for a) depend
clause b) nocontext, novariants & depend clauses occuring in the same
line of dispatch construct. 4) Removing debugging statements (kept under #if
0 and #endif) in OMPContext.h.
---
clang/docs/OpenMPSupport.rst | 2 +
clang/lib/Sema/SemaOpenMP.cpp | 11 +++--
clang/test/OpenMP/dispatch_messages.cpp | 42 +++++++++++++++++++
.../include/llvm/Frontend/OpenMP/OMPContext.h | 6 ---
4 files changed, 52 insertions(+), 9 deletions(-)
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index 481362dba3f51d..bd591f9981febb 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -314,6 +314,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` | |
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 49d0562ea1a41b..2dbd158e356b4f 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6142,6 +6142,8 @@ StmtResult SemaOpenMP::transformDispatchDirective(
const OMPNovariantsClause *NoVariantsC =
OMPExecutableDirective::getSingleClause<OMPNovariantsClause>(Clauses);
+ // The following example explains the code transformation in the code
+ //
// #pragma omp dispatch novariants(c2) depend(out: x)
// foo();
// becomes:
@@ -6150,7 +6152,7 @@ StmtResult SemaOpenMP::transformDispatchDirective(
// foo();
// } else {
// #pragma omp dispatch
- // foo(); <--- foo() is replaced with foo_variant() in CodeGen
+ // foo();
// }
Expr *Cond = getInitialExprFromCapturedExpr(NoVariantsC->getCondition());
StmtResult ThenStmt =
@@ -6179,12 +6181,15 @@ StmtResult SemaOpenMP::transformDispatchDirective(
const OMPNocontextClause *NoContextC =
OMPExecutableDirective::getSingleClause<OMPNocontextClause>(Clauses);
Expr *Cond = getInitialExprFromCapturedExpr(NoContextC->getCondition());
+ // The following example explains the code transformation in the code
+ //
// #pragma omp dispatch depend(out: x) nocontext(c2)
// foo();
// becomes:
// #pragma omp taskwait depend(out: x)
// if (c2) {
- // foo();
+ // foo(); <=== transformation explained clearly in
+ // replaceWithNewTraitsOrDirectCall()
// } else {
// #pragma omp dispatch
// foo();
@@ -6215,7 +6220,7 @@ StmtResult SemaOpenMP::transformDispatchDirective(
// Only:
// #pragma omp dispatch depend(out: x)
// foo();
- // to
+ // becomes:
// #pragma omp taskwait depend(out: x)
// foo();
StmtResult FinalStmts =
diff --git a/clang/test/OpenMP/dispatch_messages.cpp b/clang/test/OpenMP/dispatch_messages.cpp
index 27592e18adfa70..a75bd17a1b98bc 100644
--- a/clang/test/OpenMP/dispatch_messages.cpp
+++ b/clang/test/OpenMP/dispatch_messages.cpp
@@ -64,6 +64,48 @@ void testit_one(int dnum) {
// expected-error at +1 {{use of undeclared identifier 'x'}}
#pragma omp dispatch nocontext(x)
disp_call();
+
+ bool c1 = false;
+ bool c2 = true;
+ int a = 3, b=4;
+ int output;
+
+ // expected-error at +1 {{expected '(' after 'depend'}}
+ #pragma omp dispatch depend
+ disp_call();
+
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset', 'depobj' or 'inoutset' in OpenMP clause 'depend'}}
+ // expected-warning at +1 {{missing ':' after dependency type}}
+ #pragma omp dispatch depend(
+ disp_call();
+
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset', 'depobj' or 'inoutset' in OpenMP clause 'depend'}}
+ // expected-warning at +1 {{missing ':' after dependency type}}
+ #pragma omp dispatch depend(a
+ disp_call();
+
+ // expected-error at +2 {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset', 'depobj' or 'inoutset' in OpenMP clause 'depend'}}
+ // expected-warning at +1 {{missing ':' after dependency type}}
+ #pragma omp dispatch depend(a)
+ disp_call();
+
+ // expected-error at +1 {{use of undeclared identifier 'z'}}
+ #pragma omp dispatch depend(in:z)
+ disp_call();
+
+ #pragma omp dispatch depend(in:b)
+ output = disp_call();
+
+ #pragma omp dispatch depend(in:b) depend(in:a)
+ output = disp_call();
+
+ // expected-warning at +1 {{only 'novariants' clause is supported when 'novariants' & 'nocontext' clauses occur on the same dispatch construct}}
+ #pragma omp dispatch nocontext(c1) novariants(c2) depend(inout:a)
+ disp_call();
}
void testit_two() {
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
index 9ca7bf332f9519..b13b74ceab8651 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
@@ -141,12 +141,6 @@ struct VariantMatchInfo {
ISATraits.push_back(RawString);
RequiredTraits.set(unsigned(Property));
-#if 0
- unsigned int i = 0;
- for (unsigned Bit : RequiredTraits.set_bits()) {
- i++;
- }
-#endif
if (Set == TraitSet::construct)
ConstructTraits.push_back(Property);
}
>From 182d02676c85df1bdd917c04a80f1e40110bb31c Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Sun, 15 Dec 2024 12:57:56 -0600
Subject: [PATCH 07/10] Spacing problems for claiming "dispatch construct".
---
clang/docs/OpenMPSupport.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index bd591f9981febb..885a978f07967f 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -314,7 +314,7 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | dispatch construct and function variant argument adjustment | :part:`worked on` | D99537, D99679 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
-| misc | dispatch construct | :part:`worked on` | |
+| misc | dispatch construct | :part:`worked on` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | assumes directives | :part:`worked on` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
>From dca846e2dc4a4a835b4fae977c46e4483219e9fa Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Mon, 16 Dec 2024 02:36:42 -0600
Subject: [PATCH 08/10] Adding support for dispatch construct in Release Notes.
---
clang/docs/ReleaseNotes.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9882a1c42d50c4..0bfbd2fcfedd9f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1098,6 +1098,7 @@ OpenMP Support
- Added support for 'omp assume' directive.
- Added support for 'omp scope' directive.
- Added support for allocator-modifier in 'allocate' clause.
+- Added support for 'omp dispatch' directive.
Improvements
^^^^^^^^^^^^
>From 26427bfe51035cacdb2ab19b39baa580b3c169ef Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Wed, 18 Dec 2024 01:12:46 -0600
Subject: [PATCH 09/10] re-wording message in
warn_omp_dispatch_clause_novariants_nocontext.
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 81b876f9fd85c5..b7199139e88dd1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11775,7 +11775,7 @@ def err_omp_clause_requires_dispatch_construct : Error<
def err_omp_append_args_with_varargs : Error<
"'append_args' is not allowed with varargs functions">;
def warn_omp_dispatch_clause_novariants_nocontext : Warning<
- "only 'novariants' clause is supported when 'novariants' & 'nocontext' clauses occur on the same dispatch construct">,
+ "'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">;
>From e379325e93cdef5583089f63d1a52fca9cec0e2b Mon Sep 17 00:00:00 2001
From: Sunil Kuravinakop <kuravina at pe28vega.hpc.amslabs.hpecorp.net>
Date: Wed, 18 Dec 2024 05:02:58 -0600
Subject: [PATCH 10/10] Changes in expected-warning message for "#pragma omp
dispatch nocontext(c1) novariants(c2) depend(inout:a)".
---
clang/test/OpenMP/dispatch_messages.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/OpenMP/dispatch_messages.cpp b/clang/test/OpenMP/dispatch_messages.cpp
index a75bd17a1b98bc..d1435b05224fe1 100644
--- a/clang/test/OpenMP/dispatch_messages.cpp
+++ b/clang/test/OpenMP/dispatch_messages.cpp
@@ -103,7 +103,7 @@ void testit_one(int dnum) {
#pragma omp dispatch depend(in:b) depend(in:a)
output = disp_call();
- // expected-warning at +1 {{only 'novariants' clause is supported when 'novariants' & 'nocontext' clauses occur on the same dispatch construct}}
+ // expected-warning at +1 {{'nocontext' clause is ignored, only 'novariants' clause is applied}}
#pragma omp dispatch nocontext(c1) novariants(c2) depend(inout:a)
disp_call();
}
More information about the llvm-commits
mailing list