From 1703aa62cfe35538aedbacb28e907535e838248c Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Fri, 20 Sep 2024 01:41:29 -0500 Subject: [PATCH 01/32] 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 8495884dcd058..81b876f9fd85c 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; 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 900ad6ca6d66f..7579fab43dbb1 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 3d1cc4fab1c10..80cee9e758305 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 Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// The current `omp begin/end declare variant` scopes. SmallVector OMPDeclareVariantScopes; diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 62a13f01481b2..44ee63df46adb 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 698baf853507f..f3eedb7984437 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -417,7 +417,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { EmitOMPInteropDirective(cast(*S)); break; case Stmt::OMPDispatchDirectiveClass: - CGM.ErrorUnsupported(S, "OpenMP dispatch directive"); + EmitOMPDispatchDirective(cast(*S)); break; case Stmt::OMPScopeDirectiveClass: EmitOMPScopeDirective(cast(*S)); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 6cb37b20b7aee..f3f2f54b06826 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 eaea0d8a08ac0..2e342bc00a94a 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 66ff92f554fc4..28a84a52d8d79 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4205,6 +4205,8 @@ static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, SmallVector 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(SubExpr)) { + if (auto *CapturedExprDecl = + dyn_cast(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(StmtP)) { + CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); + Stmt *AssocExprStmt = AssocStmt->getCapturedStmt(); + Expr *AssocExpr = dyn_cast(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(Context), + CDecl->getDeclContext(), CDecl->getNumParams()); + NewDecl->setBody(static_cast(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 Captures; + SmallVector 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(AssocStmt->getCapturedRecordDecl())); + + return NewStmt; + } + return static_cast(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(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(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(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(nullptr)); + FinalCall = ER.get(); + } + + if (IsBinaryOp) { + BinaryCopyOpr->setRHS(FinalCall); + return BinaryCopyOpr; + } + + return FinalCall; +} + +static StmtResult combine2Stmts(ASTContext &Context, Stmt *FirstStmt, + Stmt *SecondStmt) { + + llvm::SmallVector NewCombinedStmtVector; + NewCombinedStmtVector.push_back(FirstStmt); + NewCombinedStmtVector.push_back(SecondStmt); + CompoundStmt *CombinedStmt = CompoundStmt::Create( + Context, llvm::ArrayRef(NewCombinedStmtVector), + FPOptionsOverride(), SourceLocation(), SourceLocation()); + StmtResult FinalStmts(CombinedStmt); + return FinalStmts; +} + +template +static bool hasClausesOfKind(ArrayRef Clauses) { + auto ClausesOfKind = + OMPExecutableDirective::getClausesOfKind(Clauses); + return ClausesOfKind.begin() != ClausesOfKind.end(); +} + +StmtResult SemaOpenMP::transformDispatchDirective( + OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, + OpenMPDirectiveKind CancelRegion, ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { + + StmtResult RetValue; + llvm::SmallVector DependVector; + for (const OMPDependClause *ConstDependClause : + OMPExecutableDirective::getClausesOfKind(Clauses)) { + OMPDependClause *DependClause = + const_cast(ConstDependClause); + DependVector.push_back(DependClause); + } + llvm::ArrayRef 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(Clauses)) { + + if (OMPExecutableDirective::getSingleClause(Clauses)) { + Diag(StartLoc, diag::warn_omp_dispatch_clause_novariants_nocontext); + } + + const OMPNovariantsClause *NoVariantsC = + OMPExecutableDirective::getSingleClause(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 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(Clauses)) { + StmtResult FinalStmts = combine2Stmts( + getASTContext(), DispatchDepend2taskwait.get(), IfElseStmt); + RetValue = FinalStmts; + } else { + RetValue = IfElseStmt; + } + } else if (OMPExecutableDirective::getSingleClause( + Clauses)) { + + const OMPNocontextClause *NoContextC = + OMPExecutableDirective::getSingleClause(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 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(Clauses)) { + StmtResult FinalStmts = combine2Stmts( + getASTContext(), DispatchDepend2taskwait.get(), IfElseStmt); + RetValue = FinalStmts; + } else { + RetValue = IfElseStmt; + } + } else if (hasClausesOfKind(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 Clauses, @@ -5979,6 +6238,20 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( OMPExecutableDirective::getSingleClause(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(PseudoObjExprOrDirectCall)) + DirectCallExpr = *((PseudoObjExpr->semantics_begin()) - 1); + return DirectCallExpr; +} + static Expr *getDirectCallExpr(Expr *E) { - E = E->IgnoreParenCasts()->IgnoreImplicit(); - if (auto *CE = dyn_cast(E)) + Expr *PseudoObjExpr = E->IgnoreParenCasts()->IgnoreImplicit(); + Expr *DirectCallExpr = RemovePseudoObjectExpr(PseudoObjExpr); + if (auto *CE = dyn_cast(DirectCallExpr)) if (CE->getDirectCallee()) - return E; + return DirectCallExpr; return nullptr; } @@ -10556,15 +10842,18 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef Clauses, E = E->IgnoreParenCasts()->IgnoreImplicit(); if (auto *BO = dyn_cast(E)) { - if (BO->getOpcode() == BO_Assign) + if (BO->getOpcode() == BO_Assign) { TargetCall = getDirectCallExpr(BO->getRHS()); + } } else { if (auto *COCE = dyn_cast(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 0000000000000..3a50ccbb99873 --- /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 fe7ccfa90a583..0000000000000 --- 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@+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 b13b74ceab865..9ca7bf332f951 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 Date: Mon, 9 Dec 2024 04:40:16 -0600 Subject: [PATCH 02/32] 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 44ee63df46adb..45ed0cae2aff2 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 28a84a52d8d79..affadbf873fb4 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(StmtP)) { + if (auto *AssocStmt = dyn_cast(StmtP)) { CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); Stmt *AssocExprStmt = AssocStmt->getCapturedStmt(); - Expr *AssocExpr = dyn_cast(AssocExprStmt); + auto *AssocExpr = dyn_cast(AssocExprStmt); Expr *NewCallOrPseudoObjOrBinExpr = replaceWithNewTraitsOrDirectCall( Context, AssocExpr, SemaPtr, NoContext); @@ -6021,21 +6003,21 @@ static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP, CapturedDecl::Create(const_cast(Context), CDecl->getDeclContext(), CDecl->getNumParams()); NewDecl->setBody(static_cast(NewCallOrPseudoObjOrBinExpr)); - for (unsigned i = 0; i < CDecl->getNumParams(); ++i) { - if (i != CDecl->getContextParamPosition()) - NewDecl->setParam(i, CDecl->getParam(i)); + for (unsigned I : llvm::seq(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 Captures; SmallVector 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(AssocStmt->getCapturedRecordDecl())); @@ -6045,6 +6027,26 @@ static StmtResult cloneAssociatedStmt(const ASTContext &Context, Stmt *StmtP, return static_cast(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(AssocExpr)) { + if (auto *BinOprExpr = dyn_cast(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(PseudoObjExprOrCall)) + if (auto *PseudoObjExpr = dyn_cast(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(CallWithoutInvariants); + auto *CallExprWithinStmt = cast(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 NewCombinedStmtVector; NewCombinedStmtVector.push_back(FirstStmt); NewCombinedStmtVector.push_back(SecondStmt); - CompoundStmt *CombinedStmt = CompoundStmt::Create( + auto *CombinedStmt = CompoundStmt::Create( Context, llvm::ArrayRef(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(PseudoObjExprOrDirectCall)) DirectCallExpr = *((PseudoObjExpr->semantics_begin()) - 1); return DirectCallExpr; From daf681cc78cc497064b49116df9871a0a1347cdb Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 10 Dec 2024 12:23:50 -0600 Subject: [PATCH 03/32] 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 affadbf873fb4..835a92776d0c1 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(CallWithoutInvariants); int NumArgs = CallExprWithinStmt->getNumArgs(); From bc3c018fc9715f757a1163b82724a56b9c932098 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 10 Dec 2024 12:49:39 -0600 Subject: [PATCH 04/32] 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 835a92776d0c1..6bc17cea16334 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 Date: Tue, 10 Dec 2024 14:05:56 -0600 Subject: [PATCH 05/32] 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 6bc17cea16334..49d0562ea1a41 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(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(AssocStmt->getCapturedRecordDecl())); - return NewStmt; + ResultAssocStmt = NewStmt; } - return static_cast(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(NewCombinedStmtVector), FPOptionsOverride(), SourceLocation(), SourceLocation()); - StmtResult FinalStmts(CombinedStmt); - return FinalStmts; + return CombinedStmt; } template @@ -6120,21 +6120,19 @@ StmtResult SemaOpenMP::transformDispatchDirective( Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { StmtResult RetValue; - llvm::SmallVector DependVector; + llvm::SmallVector DependClauseVector; for (const OMPDependClause *ConstDependClause : OMPExecutableDirective::getClausesOfKind(Clauses)) { - OMPDependClause *DependClause = - const_cast(ConstDependClause); - DependVector.push_back(DependClause); + auto *DependClause = const_cast(ConstDependClause); + DependClauseVector.push_back(DependClause); } - llvm::ArrayRef 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(Clauses)) { @@ -6241,7 +6239,7 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( OMPExecutableDirective::getSingleClause(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(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(DirectCallExpr)) if (CE->getDirectCallee()) return DirectCallExpr; @@ -10840,18 +10838,15 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef Clauses, E = E->IgnoreParenCasts()->IgnoreImplicit(); if (auto *BO = dyn_cast(E)) { - if (BO->getOpcode() == BO_Assign) { + if (BO->getOpcode() == BO_Assign) TargetCall = getDirectCallExpr(BO->getRHS()); - } } else { if (auto *COCE = dyn_cast(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 Date: Sun, 15 Dec 2024 12:18:42 -0600 Subject: [PATCH 06/32] 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 481362dba3f51..bd591f9981feb 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 49d0562ea1a41..2dbd158e356b4 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(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(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 27592e18adfa7..a75bd17a1b98b 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@+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@+1 {{expected '(' after 'depend'}} + #pragma omp dispatch depend + disp_call(); + + // expected-error@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset', 'depobj' or 'inoutset' in OpenMP clause 'depend'}} + // expected-warning@+1 {{missing ':' after dependency type}} + #pragma omp dispatch depend( + disp_call(); + + // expected-error@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset', 'depobj' or 'inoutset' in OpenMP clause 'depend'}} + // expected-warning@+1 {{missing ':' after dependency type}} + #pragma omp dispatch depend(a + disp_call(); + + // expected-error@+2 {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset', 'depobj' or 'inoutset' in OpenMP clause 'depend'}} + // expected-warning@+1 {{missing ':' after dependency type}} + #pragma omp dispatch depend(a) + disp_call(); + + // expected-error@+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@+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 9ca7bf332f951..b13b74ceab865 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 Date: Sun, 15 Dec 2024 12:57:56 -0600 Subject: [PATCH 07/32] 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 bd591f9981feb..885a978f07967 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 Date: Mon, 16 Dec 2024 02:36:42 -0600 Subject: [PATCH 08/32] 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 9882a1c42d50c..0bfbd2fcfedd9 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 Date: Wed, 18 Dec 2024 01:12:46 -0600 Subject: [PATCH 09/32] 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 81b876f9fd85c..b7199139e88dd 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; 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 Date: Wed, 18 Dec 2024 05:02:58 -0600 Subject: [PATCH 10/32] 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 a75bd17a1b98b..d1435b05224fe 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@+1 {{only 'novariants' clause is supported when 'novariants' & 'nocontext' clauses occur on the same dispatch construct}} + // expected-warning@+1 {{'nocontext' clause is ignored, only 'novariants' clause is applied}} #pragma omp dispatch nocontext(c1) novariants(c2) depend(inout:a) disp_call(); } From bab22e671e9b87acfa31ba7c98fe5a847f56e65f Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Thu, 2 Jan 2025 03:29:14 -0600 Subject: [PATCH 11/32] Removing the word CodeGen from comments, which can lead to confusion. --- clang/lib/Sema/SemaOpenMP.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 2dbd158e356b4..054b413fb5e5f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6064,14 +6064,13 @@ static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context, // match(user = {condition(1)}) // ... // #pragma omp dispatch nocontext(cond_true) - // foo(i, j); // with traits: CodeGen call to - // foo_variant_dispatch(i,j) + // foo(i,j); // with traits: 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) + // foo(i,j) // with traits: call to foo_variant_allCond(i,j) // } else { // #pragma omp dispatch - // foo(i,j) // with traits: CodeGen call to foo_variant_dispatch(i,j) + // foo(i,j) // with traits: call to foo_variant_dispatch(i,j) // } // Convert StmtResult to a CallExpr before calling ActOnOpenMPCall() From 00ac6cfbbd36f1d801510ae8ad62ab35ef8d5748 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Sat, 1 Feb 2025 03:26:44 -0600 Subject: [PATCH 12/32] Moving the helper functions to CodeGen by using AnnotateAttr in Sema. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 103 ++++++++++- clang/lib/CodeGen/CodeGenFunction.h | 2 + clang/lib/Sema/SemaOpenMP.cpp | 275 ++++------------------------ 3 files changed, 139 insertions(+), 241 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f3f2f54b06826..3cc7d73373f26 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4452,8 +4452,100 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { emitMaster(*this, S); } +static Expr *getInitialExprFromCapturedExpr(Expr *Cond) { + + Expr *SubExpr = Cond->IgnoreParenImpCasts(); + + if (auto *DeclRef = dyn_cast(SubExpr)) { + if (auto *CapturedExprDecl = + dyn_cast(DeclRef->getDecl())) { + + // Retrieve the initial expression from the captured expression + return CapturedExprDecl->getInit(); + } + } + return nullptr; +} + +static Expr *replaceWithNewTraitsOrDirectCall(Stmt *AssocExpr, + CallExpr *ReplacementFunction) { + Expr *FinalCall = ReplacementFunction; + + if (BinaryOperator *BinaryCopyOpr = dyn_cast(AssocExpr)) { + BinaryCopyOpr->setRHS(FinalCall); + return BinaryCopyOpr; + } + + return FinalCall; +} + +static void transformCallInStmt(Stmt *StmtP) { + if (auto *AssocStmt = dyn_cast(StmtP)) { + CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); + + // Access AnnotateAttr + CallExpr *NewCallExpr = nullptr; + for (const auto *attr : CDecl->attrs()) { + if (const auto *annotateAttr = llvm::dyn_cast(attr); + annotateAttr && + annotateAttr->getAnnotation() == "NoContextInvariant") { + NewCallExpr = llvm::dyn_cast(*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) { - EmitStmt(S.getAssociatedStmt()); + if (S.hasClausesOfKind()) { + EmitOMPDispatchToTaskwaitDirective(S); + } + ArrayRef Clauses = S.clauses(); + if (S.hasClausesOfKind()) { + const OMPNovariantsClause *NoVariantsC = + OMPExecutableDirective::getSingleClause(Clauses); + Expr *Condition = + getInitialExprFromCapturedExpr(NoVariantsC->getCondition()); + Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); + EmitIfElse(this, Condition, AssociatedStmt); + } else if (S.hasClausesOfKind()) { + const OMPNocontextClause *NoContextC = + OMPExecutableDirective::getSingleClause(Clauses); + Expr *Condition = + getInitialExprFromCapturedExpr(NoContextC->getCondition()); + Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); + EmitIfElse(this, Condition, AssociatedStmt); + } else { + EmitStmt(S.getAssociatedStmt()); + } } static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S) { @@ -5477,6 +5569,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(); + CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data); +} + void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { OMPTaskDataTy Data; // Build list of dependences diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2e342bc00a94a..c78fa5d88f72b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3636,6 +3636,8 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef Attrs = {}); + void EmitOMPDispatchToTaskwaitDirective(const OMPDispatchDirective &S); + /// Controls insertion of cancellation exit blocks in worksharing constructs. class OMPCancelStackRAII { CodeGenFunction &CGF; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 054b413fb5e5f..bc61d7e7386af 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5967,86 +5967,16 @@ static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) { return Checker.teamsLoopCanBeParallelFor(); } -static Expr *getInitialExprFromCapturedExpr(Expr *Cond) { - - Expr *SubExpr = Cond->IgnoreParenImpCasts(); - - if (auto *DeclRef = dyn_cast(SubExpr)) { - if (auto *CapturedExprDecl = - dyn_cast(DeclRef->getDecl())) { - - // Retrieve the initial expression from the captured expression - return CapturedExprDecl->getInit(); - } - } - return nullptr; -} - -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) { - StmtResult ResultAssocStmt; - if (auto *AssocStmt = dyn_cast(StmtP)) { - CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); - Stmt *AssocExprStmt = AssocStmt->getCapturedStmt(); - auto *AssocExpr = dyn_cast(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(Context), - CDecl->getDeclContext(), CDecl->getNumParams()); - NewDecl->setBody(static_cast(NewCallOrPseudoObjOrBinExpr)); - for (unsigned I : llvm::seq(CDecl->getNumParams())) { - 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 Captures; - SmallVector CaptureInits; - 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(AssocStmt->getCapturedRecordDecl())); - - ResultAssocStmt = NewStmt; - } - return ResultAssocStmt; -} - -/// replaceWithNewTraitsOrDirectCall() is for transforming the call traits. +/// getNewTraitsOrDirectCall() 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. -static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context, - Expr *AssocExpr, - SemaOpenMP *SemaPtr, - bool NoContext) { - BinaryOperator *BinaryCopyOpr = nullptr; - bool IsBinaryOp = false; +/// modified to have call traits for a non-dispatch (directive) variant. +static Expr *getNewTraitsOrDirectCall(const ASTContext &Context, + Expr *AssocExpr, SemaOpenMP *SemaPtr, + bool NoContext) { Expr *PseudoObjExprOrCall = AssocExpr; if (auto *BinOprExpr = dyn_cast(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(); + PseudoObjExprOrCall = BinOprExpr->getRHS(); } Expr *CallWithoutInvariants = PseudoObjExprOrCall; @@ -6056,24 +5986,6 @@ 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: call to foo_variant_dispatch(i,j) - // dispatch construct is changed to: - // if (cond_true) { - // foo(i,j) // with traits: call to foo_variant_allCond(i,j) - // } else { - // #pragma omp dispatch - // foo(i,j) // with traits: call to foo_variant_dispatch(i,j) - // } - - // Convert StmtResult to a CallExpr before calling ActOnOpenMPCall() auto *CallExprWithinStmt = cast(CallWithoutInvariants); int NumArgs = CallExprWithinStmt->getNumArgs(); clang::Expr **Args = CallExprWithinStmt->getArgs(); @@ -6084,149 +5996,34 @@ static Expr *replaceWithNewTraitsOrDirectCall(const ASTContext &Context, CallExprWithinStmt->getBeginLoc(), MultiExprArg(Args, NumArgs), CallExprWithinStmt->getRParenLoc(), static_cast(nullptr)); FinalCall = ER.get(); + if (auto *PseudoObjExpr = dyn_cast(ER.get())) + FinalCall = *((PseudoObjExpr->semantics_begin())); } - - if (IsBinaryOp) { - BinaryCopyOpr->setRHS(FinalCall); - return BinaryCopyOpr; - } - return FinalCall; } -static StmtResult combine2Stmts(ASTContext &Context, Stmt *FirstStmt, - Stmt *SecondStmt) { - - llvm::SmallVector NewCombinedStmtVector; - NewCombinedStmtVector.push_back(FirstStmt); - NewCombinedStmtVector.push_back(SecondStmt); - auto *CombinedStmt = CompoundStmt::Create( - Context, llvm::ArrayRef(NewCombinedStmtVector), - FPOptionsOverride(), SourceLocation(), SourceLocation()); - return CombinedStmt; -} - -template -static bool hasClausesOfKind(ArrayRef Clauses) { - auto ClausesOfKind = - OMPExecutableDirective::getClausesOfKind(Clauses); - return ClausesOfKind.begin() != ClausesOfKind.end(); -} - -StmtResult SemaOpenMP::transformDispatchDirective( - OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, - OpenMPDirectiveKind CancelRegion, ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - - StmtResult RetValue; - llvm::SmallVector DependClauseVector; - for (const OMPDependClause *ConstDependClause : - OMPExecutableDirective::getClausesOfKind(Clauses)) { - auto *DependClause = const_cast(ConstDependClause); - DependClauseVector.push_back(DependClause); - } - - // #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, DependClauseVector, NULL, StartLoc, - EndLoc); - - if (OMPExecutableDirective::getSingleClause(Clauses)) { - - if (OMPExecutableDirective::getSingleClause(Clauses)) { - Diag(StartLoc, diag::warn_omp_dispatch_clause_novariants_nocontext); - } - - const OMPNovariantsClause *NoVariantsC = - OMPExecutableDirective::getSingleClause(Clauses); - // The following example explains the code transformation in the code - // - // #pragma omp dispatch novariants(c2) depend(out: x) - // foo(); - // becomes: - // #pragma omp taskwait depend(out: x) - // if (c2) { - // foo(); - // } else { - // #pragma omp dispatch - // foo(); - // } - Expr *Cond = getInitialExprFromCapturedExpr(NoVariantsC->getCondition()); - StmtResult ThenStmt = - cloneAssociatedStmt(getASTContext(), AStmt, this, false); - SmallVector 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(Clauses)) { - StmtResult FinalStmts = combine2Stmts( - getASTContext(), DispatchDepend2taskwait.get(), IfElseStmt); - RetValue = FinalStmts; - } else { - RetValue = IfElseStmt; - } - } else if (OMPExecutableDirective::getSingleClause( - Clauses)) { - - const OMPNocontextClause *NoContextC = - OMPExecutableDirective::getSingleClause(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(); <=== transformation explained clearly in - // replaceWithNewTraitsOrDirectCall() - // } else { - // #pragma omp dispatch - // foo(); - // } - - StmtResult ThenStmt = - cloneAssociatedStmt(getASTContext(), AStmt, this, true); - - SmallVector 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(Clauses)) { - StmtResult FinalStmts = combine2Stmts( - getASTContext(), DispatchDepend2taskwait.get(), IfElseStmt); - RetValue = FinalStmts; - } else { - RetValue = IfElseStmt; - } - } else if (hasClausesOfKind(Clauses)) { - // Only: - // #pragma omp dispatch depend(out: x) - // foo(); - // becomes: - // #pragma omp taskwait depend(out: x) - // foo(); - StmtResult FinalStmts = - combine2Stmts(getASTContext(), DispatchDepend2taskwait.get(), AStmt); - RetValue = FinalStmts; +/// annotateAStmt() function is used by ActOnOpenMPExecutableDirective() +/// for the dispatch directive (nocontext or invariant clauses) dispatch +/// directive. An annotation "NoContextInvariant" is added to the Captured Decl +/// in the Associated Stmt. This annotation contains either a call to the +/// function, not to any of its variants (for invariant clause) or a variant +/// function (for nocontext clause). +static void annotateAStmt(const ASTContext &Context, Stmt *StmtP, + SemaOpenMP *SemaPtr, bool NoContext) { + StmtResult ResultAssocStmt; + if (auto *AssocStmt = dyn_cast(StmtP)) { + CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); + Stmt *AssocExprStmt = AssocStmt->getCapturedStmt(); + auto *AssocExpr = dyn_cast(AssocExprStmt); + Expr *NewCallExpr = + getNewTraitsOrDirectCall(Context, AssocExpr, SemaPtr, NoContext); + // Annotate "NoContextInvariant" to CDecl of the AssocStmt + llvm::SmallVector Args; + Args.push_back(NewCallExpr); + CDecl->addAttr(AnnotateAttr::CreateImplicit( + const_cast(Context), "NoContextInvariant", Args.data(), + Args.size())); } - return RetValue; } StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( @@ -6244,14 +6041,12 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( BindKind = BC->getBindKind(); if ((Kind == OMPD_dispatch) && (!Clauses.empty())) { - - 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); + if (OMPExecutableDirective::getSingleClause(Clauses)) { + annotateAStmt(getASTContext(), AStmt, this, false); + } else if (OMPExecutableDirective::getSingleClause( + Clauses)) { + annotateAStmt(getASTContext(), AStmt, this, true); + } } if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) { From ff2f370b3bfcba325c3e0cfa6a78a9151b013eba Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 4 Feb 2025 00:48:04 -0600 Subject: [PATCH 13/32] Changing the commit message from: 'nocontext' clause is ignored, only 'novariants' clause is applied to first occuring clause among 'nocontext' or 'novariants' is applied This is being done because of usage of llvm::any_of & llvm::is_contained instead of if statements. --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 28 ++++---- clang/lib/Sema/SemaOpenMP.cpp | 19 ++++-- clang/test/OpenMP/dispatch_ast_print.cpp | 1 - clang/test/OpenMP/dispatch_codegen.cpp | 64 +++++++++---------- clang/test/OpenMP/dispatch_messages.cpp | 2 +- 6 files changed, 63 insertions(+), 53 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b7199139e88dd..6d2f94dccd425 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< - "'nocontext' clause is ignored, only 'novariants' clause is applied">, + "first occuring clause among 'nocontext' or 'novariants' is applied">, InGroup; def err_openmp_vla_in_task_untied : Error< "variable length arrays are not supported in OpenMP tasking regions with 'untied' clause">; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 3cc7d73373f26..0724b7cf0f62a 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4529,18 +4529,22 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { EmitOMPDispatchToTaskwaitDirective(S); } ArrayRef Clauses = S.clauses(); - if (S.hasClausesOfKind()) { - const OMPNovariantsClause *NoVariantsC = - OMPExecutableDirective::getSingleClause(Clauses); - Expr *Condition = - getInitialExprFromCapturedExpr(NoVariantsC->getCondition()); - Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); - EmitIfElse(this, Condition, AssociatedStmt); - } else if (S.hasClausesOfKind()) { - const OMPNocontextClause *NoContextC = - OMPExecutableDirective::getSingleClause(Clauses); - Expr *Condition = - getInitialExprFromCapturedExpr(NoContextC->getCondition()); + bool IsClauseNoContext = false; + if (llvm::any_of(Clauses, [&IsClauseNoContext](OMPClause *C) { + IsClauseNoContext = (C->getClauseKind() == OMPC_nocontext); + return llvm::is_contained({OMPC_novariants, OMPC_nocontext}, + C->getClauseKind()); + })) { + Expr *Condition = nullptr; + if (IsClauseNoContext) { + const OMPNocontextClause *NoContextC = + OMPExecutableDirective::getSingleClause(Clauses); + Condition = getInitialExprFromCapturedExpr(NoContextC->getCondition()); + } else { + const OMPNovariantsClause *NoVariantsC = + OMPExecutableDirective::getSingleClause(Clauses); + Condition = getInitialExprFromCapturedExpr(NoVariantsC->getCondition()); + } Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); EmitIfElse(this, Condition, AssociatedStmt); } else { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index bc61d7e7386af..69b6c0fd111bf 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6041,14 +6041,21 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( BindKind = BC->getBindKind(); if ((Kind == OMPD_dispatch) && (!Clauses.empty())) { - if (OMPExecutableDirective::getSingleClause(Clauses)) { - annotateAStmt(getASTContext(), AStmt, this, false); - } else if (OMPExecutableDirective::getSingleClause( - Clauses)) { - annotateAStmt(getASTContext(), AStmt, this, true); + bool IsClauseNoContext = false; + if (llvm::any_of(Clauses, [&IsClauseNoContext](OMPClause *C) { + IsClauseNoContext = (C->getClauseKind() == OMPC_nocontext); + return llvm::is_contained({OMPC_novariants, OMPC_nocontext}, + C->getClauseKind()); + })) { + if (OMPExecutableDirective::getSingleClause( + Clauses) && + OMPExecutableDirective::getSingleClause( + Clauses)) { + Diag(StartLoc, diag::warn_omp_dispatch_clause_novariants_nocontext); + } + annotateAStmt(getASTContext(), AStmt, this, IsClauseNoContext); } } - if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) { const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective(); diff --git a/clang/test/OpenMP/dispatch_ast_print.cpp b/clang/test/OpenMP/dispatch_ast_print.cpp index 6065f4f6e68ca..54ba5c19df51c 100644 --- a/clang/test/OpenMP/dispatch_ast_print.cpp +++ b/clang/test/OpenMP/dispatch_ast_print.cpp @@ -4,7 +4,6 @@ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp \ // RUN: -fsyntax-only -verify %s -// expected-no-diagnostics // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp \ // RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT diff --git a/clang/test/OpenMP/dispatch_codegen.cpp b/clang/test/OpenMP/dispatch_codegen.cpp index 3a50ccbb99873..c3be66c6bbc7d 100644 --- a/clang/test/OpenMP/dispatch_codegen.cpp +++ b/clang/test/OpenMP/dispatch_codegen.cpp @@ -163,16 +163,16 @@ void checkNoContext_withoutVariant() { // 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.1{{.+}} +// CHECK-LABEL: if.then{{.+}} // 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.3{{.+}} +// CHECK-LABEL: if.then{{.+}} // CHECK: call {{.+}}captured_stmt.4{{.+}} // CHECK-LABEL: if.end{{.+}} // @@ -180,16 +180,16 @@ void checkNoContext_withoutVariant() { // 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.5{{.+}} +// CHECK-LABEL: if.then{{.+}} // 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.7{{.+}} +// CHECK-LABEL: if.then{{.+}} // CHECK: call {{.+}}captured_stmt.8{{.+}} // CHECK-LABEL: if.end{{.+}} // @@ -206,51 +206,51 @@ void checkNoContext_withoutVariant() { // // #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.11{{.+}} +// CHECK-LABEL: if.then{{.+}} // 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.13{{.+}} +// CHECK-LABEL: if.then{{.+}} // CHECK: call {{.+}}captured_stmt.14{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.1{{.+}} -// CHECK: call {{.+}}foo{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.2{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.3{{.+}} -// CHECK: call {{.+}}foo{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.4{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.5{{.+}} -// CHECK: call {{.+}}foo_variant_allCond{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.6{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo_variant_allCond{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.7{{.+}} -// CHECK: call {{.+}}foo_variant_allCond{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.8{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo_variant_allCond{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.9{{.+}} @@ -262,19 +262,19 @@ void checkNoContext_withoutVariant() { // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.11{{.+}} -// CHECK: call {{.+}}foo{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.12{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.13{{.+}} -// CHECK: call {{.+}}foo_variant_allCond{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.14{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo_variant_allCond{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}bar_variant{{.+}} @@ -300,28 +300,28 @@ void checkNoContext_withoutVariant() { // // 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.16{{.+}} +// CHECK-LABEL: if.then{{.+}} // 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.18{{.+}} +// CHECK-LABEL: if.then{{.+}} // 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.20{{.+}} +// CHECK-LABEL: if.then{{.+}} // 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.22{{.+}} +// CHECK-LABEL: if.then{{.+}} // CHECK: call {{.+}}captured_stmt.23{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret{{.+}} diff --git a/clang/test/OpenMP/dispatch_messages.cpp b/clang/test/OpenMP/dispatch_messages.cpp index d1435b05224fe..41944c8516baf 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@+1 {{'nocontext' clause is ignored, only 'novariants' clause is applied}} + // expected-warning@+1 {{first occuring clause among 'nocontext' or 'novariants' is applied}} #pragma omp dispatch nocontext(c1) novariants(c2) depend(inout:a) disp_call(); } From de5b7cc5654229e1e2521b1a171472dbdfb08e53 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 4 Feb 2025 13:11:25 -0600 Subject: [PATCH 14/32] All clang/test/OpenMP/dispatch_*.cpp tests pass with the changes in this commit. --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/include/clang/Sema/SemaOpenMP.h | 9 +-- clang/lib/CodeGen/CGStmtOpenMP.cpp | 43 +++++++------- clang/lib/Sema/SemaOpenMP.cpp | 42 ++++++++------ clang/test/OpenMP/dispatch_ast_print.cpp | 1 + clang/test/OpenMP/dispatch_codegen.cpp | 56 ++++++++----------- clang/test/OpenMP/dispatch_messages.cpp | 2 +- 7 files changed, 75 insertions(+), 80 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6d2f94dccd425..b7199139e88dd 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< - "first occuring clause among 'nocontext' or 'novariants' is applied">, + "'nocontext' clause is ignored, only 'novariants' clause is applied">, InGroup; def err_openmp_vla_in_task_untied : Error< "variable length arrays are not supported in OpenMP tasking regions with 'untied' clause">; diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index 80cee9e758305..6eae0021a3211 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -1462,12 +1462,9 @@ class SemaOpenMP : public SemaBase { : OMPDeclareVariantScopes.back().TI; } - StmtResult transformDispatchDirective(OpenMPDirectiveKind Kind, - const DeclarationNameInfo &DirName, - OpenMPDirectiveKind CancelRegion, - ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); + void annotateAStmt(const ASTContext &Context, Stmt *StmtP, + SemaOpenMP *SemaPtr, ArrayRef &Clauses, + SourceLocation StartLoc); /// The current `omp begin/end declare variant` scopes. SmallVector OMPDeclareVariantScopes; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 0724b7cf0f62a..9ac5f5841bbfe 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4525,31 +4525,30 @@ static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition, } void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { - if (S.hasClausesOfKind()) { - EmitOMPDispatchToTaskwaitDirective(S); - } ArrayRef Clauses = S.clauses(); - bool IsClauseNoContext = false; - if (llvm::any_of(Clauses, [&IsClauseNoContext](OMPClause *C) { - IsClauseNoContext = (C->getClauseKind() == OMPC_nocontext); - return llvm::is_contained({OMPC_novariants, OMPC_nocontext}, - C->getClauseKind()); - })) { - Expr *Condition = nullptr; - if (IsClauseNoContext) { - const OMPNocontextClause *NoContextC = - OMPExecutableDirective::getSingleClause(Clauses); - Condition = getInitialExprFromCapturedExpr(NoContextC->getCondition()); - } else { - const OMPNovariantsClause *NoVariantsC = - OMPExecutableDirective::getSingleClause(Clauses); - Condition = getInitialExprFromCapturedExpr(NoVariantsC->getCondition()); + if (!Clauses.empty()) { + if (S.hasClausesOfKind()) + EmitOMPDispatchToTaskwaitDirective(S); + + if (S.hasClausesOfKind() || + S.hasClausesOfKind()) { + Expr *Condition = nullptr; + if (const OMPNovariantsClause *NoVariantsC = + OMPExecutableDirective::getSingleClause( + Clauses)) { + Condition = getInitialExprFromCapturedExpr(NoVariantsC->getCondition()); + } else { + const OMPNocontextClause *NoContextC = + OMPExecutableDirective::getSingleClause( + Clauses); + Condition = getInitialExprFromCapturedExpr(NoContextC->getCondition()); + } + /* OMPC_novariants or OMPC_nocontext present */ + Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); + EmitIfElse(this, Condition, AssociatedStmt); } - Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); - EmitIfElse(this, Condition, AssociatedStmt); - } else { + } else EmitStmt(S.getAssociatedStmt()); - } } static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 69b6c0fd111bf..5fb4a0cdf6aab 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6003,18 +6003,29 @@ static Expr *getNewTraitsOrDirectCall(const ASTContext &Context, } /// annotateAStmt() function is used by ActOnOpenMPExecutableDirective() -/// for the dispatch directive (nocontext or invariant clauses) dispatch -/// directive. An annotation "NoContextInvariant" is added to the Captured Decl +/// for the dispatch directive (nocontext or invariant clauses). +/// An annotation "NoContextInvariant" is added to the Captured Decl /// in the Associated Stmt. This annotation contains either a call to the /// function, not to any of its variants (for invariant clause) or a variant /// function (for nocontext clause). -static void annotateAStmt(const ASTContext &Context, Stmt *StmtP, - SemaOpenMP *SemaPtr, bool NoContext) { - StmtResult ResultAssocStmt; +void SemaOpenMP::annotateAStmt(const ASTContext &Context, Stmt *StmtP, + SemaOpenMP *SemaPtr, + ArrayRef &Clauses, + SourceLocation StartLoc) { if (auto *AssocStmt = dyn_cast(StmtP)) { CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); Stmt *AssocExprStmt = AssocStmt->getCapturedStmt(); auto *AssocExpr = dyn_cast(AssocExprStmt); + bool NoContext = false; + + if (OMPExecutableDirective::getSingleClause(Clauses)) { + + if (OMPExecutableDirective::getSingleClause(Clauses)) + Diag(StartLoc, diag::warn_omp_dispatch_clause_novariants_nocontext); + } else if (OMPExecutableDirective::getSingleClause( + Clauses)) + NoContext = true; + Expr *NewCallExpr = getNewTraitsOrDirectCall(Context, AssocExpr, SemaPtr, NoContext); // Annotate "NoContextInvariant" to CDecl of the AssocStmt @@ -6041,19 +6052,16 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( BindKind = BC->getBindKind(); if ((Kind == OMPD_dispatch) && (!Clauses.empty())) { - bool IsClauseNoContext = false; - if (llvm::any_of(Clauses, [&IsClauseNoContext](OMPClause *C) { - IsClauseNoContext = (C->getClauseKind() == OMPC_nocontext); - return llvm::is_contained({OMPC_novariants, OMPC_nocontext}, - C->getClauseKind()); + + if (llvm::all_of(Clauses, [](OMPClause *C) { + return llvm::is_contained( + {OMPC_novariants, OMPC_nocontext, OMPC_depend}, + C->getClauseKind()); })) { - if (OMPExecutableDirective::getSingleClause( - Clauses) && - OMPExecutableDirective::getSingleClause( - Clauses)) { - Diag(StartLoc, diag::warn_omp_dispatch_clause_novariants_nocontext); - } - annotateAStmt(getASTContext(), AStmt, this, IsClauseNoContext); + if (OMPExecutableDirective::getSingleClause( + Clauses) || + OMPExecutableDirective::getSingleClause(Clauses)) + annotateAStmt(getASTContext(), AStmt, this, Clauses, StartLoc); } } if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) { diff --git a/clang/test/OpenMP/dispatch_ast_print.cpp b/clang/test/OpenMP/dispatch_ast_print.cpp index 54ba5c19df51c..6065f4f6e68ca 100644 --- a/clang/test/OpenMP/dispatch_ast_print.cpp +++ b/clang/test/OpenMP/dispatch_ast_print.cpp @@ -4,6 +4,7 @@ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp \ // RUN: -fsyntax-only -verify %s +// expected-no-diagnostics // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp \ // RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT diff --git a/clang/test/OpenMP/dispatch_codegen.cpp b/clang/test/OpenMP/dispatch_codegen.cpp index c3be66c6bbc7d..1661086d74132 100644 --- a/clang/test/OpenMP/dispatch_codegen.cpp +++ b/clang/test/OpenMP/dispatch_codegen.cpp @@ -198,26 +198,24 @@ void checkNoContext_withoutVariant() { // // #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.else{{.+}} -// CHECK: call {{.+}}captured_stmt.11{{.+}} +// CHECK: call {{.+}}captured_stmt.9{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.12{{.+}} +// CHECK: call {{.+}}captured_stmt.10{{.+}} // CHECK-LABEL: if.end{{.+}} // // #pragma omp dispatch depend(out:x) nocontext(cond_false) // CHECK: call {{.+}}kmpc_omp_taskwait_deps{{.+}} // CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.13{{.+}} +// CHECK: call {{.+}}captured_stmt.11{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.14{{.+}} +// CHECK: call {{.+}}captured_stmt.12{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret void // @@ -258,7 +256,7 @@ void checkNoContext_withoutVariant() { // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.10{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.11{{.+}} @@ -266,14 +264,6 @@ void checkNoContext_withoutVariant() { // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.12{{.+}} -// CHECK: call {{.+}}foo{{.+}} -// CHECK: ret void -// -// CHECK-LABEL: define {{.+}}__captured_stmt.13{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} -// CHECK: ret void -// -// CHECK-LABEL: define {{.+}}__captured_stmt.14{{.+}} // CHECK: call {{.+}}foo_variant_allCond{{.+}} // CHECK: ret void // @@ -288,72 +278,72 @@ void checkNoContext_withoutVariant() { // CHECK-LABEL: define {{.+}}without_declareVariant{{.+}} // CHECK-LABEL: entry: // CHECK: call {{.+}}bar{{.+}} -// CHECK: call {{.+}}captured_stmt.15{{.+}} +// CHECK: call {{.+}}captured_stmt.13{{.+}} // CHECK-NEXT: call {{.+}}checkNoVariants_withoutVariant{{.+}} // CHECK-NEXT: call {{.+}}checkNoContext_withoutVariant{{.+}} // CHECK-NEXT: ret{{.+}} // // #pragma omp dispatch -// CHECK-LABEL: define {{.+}}__captured_stmt.15{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.13{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}checkNoVariants_withoutVariant{{.+}} // CHECK-LABEL: entry: // CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.16{{.+}} +// CHECK: call {{.+}}captured_stmt.14{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.17{{.+}} +// CHECK: call {{.+}}captured_stmt.15{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.18{{.+}} +// CHECK: call {{.+}}captured_stmt.16{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.19{{.+}} +// CHECK: call {{.+}}captured_stmt.17{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret{{.+}} // // CHECK-LABEL: define {{.+}}checkNoContext_withoutVariant{{.+}} // CHECK-LABEL: entry: // CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.20{{.+}} +// CHECK: call {{.+}}captured_stmt.18{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.21{{.+}} +// CHECK: call {{.+}}captured_stmt.19{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.22{{.+}} +// CHECK: call {{.+}}captured_stmt.20{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.23{{.+}} +// CHECK: call {{.+}}captured_stmt.21{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret{{.+}} // // #pragma omp dispatch novariants(cond_true) -// CHECK-LABEL: define {{.+}}__captured_stmt.16{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.14{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.17{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.15{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // #pragma omp dispatch novariants(cond_false) -// CHECK-LABEL: define {{.+}}__captured_stmt.18{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.16{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.19{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.17{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // #pragma omp dispatch nocontext(cond_true) -// CHECK-LABEL: define {{.+}}__captured_stmt.20{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.18{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.21{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.19{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // #pragma omp dispatch nocontext(cond_false) -// CHECK-LABEL: define {{.+}}__captured_stmt.22{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.20{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.23{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.21{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void diff --git a/clang/test/OpenMP/dispatch_messages.cpp b/clang/test/OpenMP/dispatch_messages.cpp index 41944c8516baf..d1435b05224fe 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@+1 {{first occuring clause among 'nocontext' or 'novariants' is applied}} + // expected-warning@+1 {{'nocontext' clause is ignored, only 'novariants' clause is applied}} #pragma omp dispatch nocontext(c1) novariants(c2) depend(inout:a) disp_call(); } From 817f6df3f506f988295905e8d818b53deb8382be Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Sat, 22 Feb 2025 10:23:05 -0600 Subject: [PATCH 15/32] Handling: 1) Templates 2) Constant values in the conditions for novariants & nocontext. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 2 +- clang/lib/Sema/SemaOpenMP.cpp | 5 +++- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 26 +++++++++++++++++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index c5e0106a6db51..51563b825d741 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4456,7 +4456,7 @@ static Expr *getInitialExprFromCapturedExpr(Expr *Cond) { return CapturedExprDecl->getInit(); } } - return nullptr; + return Cond; } static Expr *replaceWithNewTraitsOrDirectCall(Stmt *AssocExpr, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index a566bb32f63be..19c68b6a4a0de 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -7267,12 +7267,15 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope, Sema::TentativeAnalysisScope Trap(SemaRef); if (auto *SpecializedMethod = dyn_cast(BestDecl)) { - auto *MemberCall = dyn_cast(CE); + if (!SpecializedMethod->isStatic()) { + if (auto *MemberCall = dyn_cast(CE)) { BestExpr = MemberExpr::CreateImplicit( Context, MemberCall->getImplicitObjectArgument(), /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy, MemberCall->getValueKind(), MemberCall->getObjectKind()); } + } + } NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc, ExecConfig); if (NewCall.isUsable()) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 4855e8a23689c..05f8d79646260 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -422,8 +422,8 @@ static void instantiateOMPDeclareVariantAttr( auto *FD = cast(New); auto *ThisContext = dyn_cast_or_null(FD->getDeclContext()); - auto &&SubstExpr = [FD, ThisContext, &S, &TemplateArgs](Expr *E) { - if (auto *DRE = dyn_cast(E->IgnoreParenImpCasts())) + auto &&SubstExpr = [FD, ThisContext, &S, &TemplateArgs, New](Expr *E) { + if (auto *DRE = dyn_cast(E->IgnoreParenImpCasts())) { if (auto *PVD = dyn_cast(DRE->getDecl())) { Sema::ContextRAII SavedContext(S, FD); LocalInstantiationScope Local(S); @@ -431,7 +431,29 @@ static void instantiateOMPDeclareVariantAttr( Local.InstantiatedLocal( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); return S.SubstExpr(E, TemplateArgs); + } else if (auto *CMD = dyn_cast(DRE->getDecl())) { + const TemplateArgumentList *TAL = TemplateArgumentList::CreateCopy( + S.Context, TemplateArgs.getInnermost()); + auto *TPL = CMD->getTemplateParameterList(0); + TemplateDeclInstantiator Instantiator(S, CMD->getDeclContext(), + TemplateArgs); + CXXMethodDecl *MD = cast(Instantiator.VisitCXXMethodDecl(CMD, TPL)); + QualType FnPtrType; + if (MD && !MD->isStatic()) { + const Type *ClassType = + S.Context.getTypeDeclType(MD->getParent()).getTypePtr(); + FnPtrType = S.Context.getMemberPointerType(MD->getType(), ClassType); + } else { + FnPtrType = MD->getType(); + } + E = DeclRefExpr::Create(S.Context, NestedNameSpecifierLoc(), + SourceLocation(), MD, + /* RefersToEnclosingVariableOrCapture */ false, + /* NameLoc */ MD->getLocation(), FnPtrType, + ExprValueKind::VK_PRValue); + return ExprResult(E); } + } Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), FD->isCXXInstanceMember()); return S.SubstExpr(E, TemplateArgs); From 984446d25d762c96aba992075cc33523fd9636a8 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 18 Mar 2025 02:14:58 -0500 Subject: [PATCH 16/32] Undoing changes to handle templates. --- clang/lib/Sema/SemaOpenMP.cpp | 5 +---- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 21 ------------------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 19c68b6a4a0de..a566bb32f63be 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -7267,15 +7267,12 @@ ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope, Sema::TentativeAnalysisScope Trap(SemaRef); if (auto *SpecializedMethod = dyn_cast(BestDecl)) { - if (!SpecializedMethod->isStatic()) { - if (auto *MemberCall = dyn_cast(CE)) { + auto *MemberCall = dyn_cast(CE); BestExpr = MemberExpr::CreateImplicit( Context, MemberCall->getImplicitObjectArgument(), /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy, MemberCall->getValueKind(), MemberCall->getObjectKind()); } - } - } NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc, ExecConfig); if (NewCall.isUsable()) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 05f8d79646260..2b4c5952877b0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -431,27 +431,6 @@ static void instantiateOMPDeclareVariantAttr( Local.InstantiatedLocal( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); return S.SubstExpr(E, TemplateArgs); - } else if (auto *CMD = dyn_cast(DRE->getDecl())) { - const TemplateArgumentList *TAL = TemplateArgumentList::CreateCopy( - S.Context, TemplateArgs.getInnermost()); - auto *TPL = CMD->getTemplateParameterList(0); - TemplateDeclInstantiator Instantiator(S, CMD->getDeclContext(), - TemplateArgs); - CXXMethodDecl *MD = cast(Instantiator.VisitCXXMethodDecl(CMD, TPL)); - QualType FnPtrType; - if (MD && !MD->isStatic()) { - const Type *ClassType = - S.Context.getTypeDeclType(MD->getParent()).getTypePtr(); - FnPtrType = S.Context.getMemberPointerType(MD->getType(), ClassType); - } else { - FnPtrType = MD->getType(); - } - E = DeclRefExpr::Create(S.Context, NestedNameSpecifierLoc(), - SourceLocation(), MD, - /* RefersToEnclosingVariableOrCapture */ false, - /* NameLoc */ MD->getLocation(), FnPtrType, - ExprValueKind::VK_PRValue); - return ExprResult(E); } } Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), From c1a83cc694f459e2e99ff88e381b662829b79a90 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 25 Mar 2025 00:24:42 -0500 Subject: [PATCH 17/32] Separating virtual regions of taskwait directive and dispatch directive in Sema. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 12 ------------ clang/lib/Sema/SemaOpenMP.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 5aa72a46669fa..c5921e637f852 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4603,9 +4603,6 @@ static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition, void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { ArrayRef Clauses = S.clauses(); if (!Clauses.empty()) { - if (S.hasClausesOfKind()) - EmitOMPDispatchToTaskwaitDirective(S); - if (S.hasClausesOfKind() || S.hasClausesOfKind()) { Expr *Condition = nullptr; @@ -5647,15 +5644,6 @@ 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(); - CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data); -} - void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { OMPTaskDataTy Data; // Build list of dependences diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index fabd5f5921dc4..d32831852f610 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6062,6 +6062,7 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( OpenMPBindClauseKind BindKind = OMPC_BIND_unknown; llvm::SmallVector ClausesWithImplicit; + StmtResult DispatchDepend2taskwait; if (const OMPBindClause *BC = OMPExecutableDirective::getSingleClause(Clauses)) BindKind = BC->getBindKind(); @@ -6073,6 +6074,23 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( {OMPC_novariants, OMPC_nocontext, OMPC_depend}, C->getClauseKind()); })) { + + /* Handle OMPC_depend clauses */ + if (llvm::any_of(Clauses, [](const OMPClause *C) { + return isa(C); + })) { + + llvm::SmallVector DependClauseVector; + llvm::for_each( + OMPExecutableDirective::getClausesOfKind(Clauses), + [&](const OMPDependClause *Clause) { + DependClauseVector.push_back( + const_cast(Clause)); + }); + DispatchDepend2taskwait = ActOnOpenMPExecutableDirective( + OMPD_taskwait, DirName, CancelRegion, DependClauseVector, NULL, + StartLoc, EndLoc); + } if (OMPExecutableDirective::getSingleClause( Clauses) || OMPExecutableDirective::getSingleClause(Clauses)) @@ -6566,6 +6584,14 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( case OMPD_dispatch: Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + if (DispatchDepend2taskwait.get()) { + llvm::SmallVector CombStmtVector = { + DispatchDepend2taskwait.get(), Res.get()}; + auto *CompoundStmt = CompoundStmt::Create( + getASTContext(), CombStmtVector, FPOptionsOverride(), + SourceLocation(), SourceLocation()); + Res = CompoundStmt; + } break; case OMPD_loop: Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc, From bb176c89b7f814bb45ce6f8dcc5345e2e2fb0e84 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Sat, 29 Mar 2025 01:27:59 -0500 Subject: [PATCH 18/32] Moving handling of dispatch depend into CodeGen. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 12 ++++++++++++ clang/lib/Sema/SemaOpenMP.cpp | 25 ------------------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index c5921e637f852..5200b12576aa6 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4603,6 +4603,9 @@ static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition, void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { ArrayRef Clauses = S.clauses(); if (!Clauses.empty()) { + if (S.hasClausesOfKind()) + EmitOMPDispatchToTaskwaitDirective(S); + if (S.hasClausesOfKind() || S.hasClausesOfKind()) { Expr *Condition = nullptr; @@ -5644,6 +5647,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(); + CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data); +} + void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { OMPTaskDataTy Data; // Build list of dependences diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index a98b31009e903..77aff5550a1dc 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6062,7 +6062,6 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( OpenMPBindClauseKind BindKind = OMPC_BIND_unknown; llvm::SmallVector ClausesWithImplicit; - StmtResult DispatchDepend2taskwait; if (const OMPBindClause *BC = OMPExecutableDirective::getSingleClause(Clauses)) BindKind = BC->getBindKind(); @@ -6075,22 +6074,6 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( C->getClauseKind()); })) { - /* Handle OMPC_depend clauses */ - if (llvm::any_of(Clauses, [](const OMPClause *C) { - return isa(C); - })) { - - llvm::SmallVector DependClauseVector; - llvm::for_each( - OMPExecutableDirective::getClausesOfKind(Clauses), - [&](const OMPDependClause *Clause) { - DependClauseVector.push_back( - const_cast(Clause)); - }); - DispatchDepend2taskwait = ActOnOpenMPExecutableDirective( - OMPD_taskwait, DirName, CancelRegion, DependClauseVector, NULL, - StartLoc, EndLoc); - } if (OMPExecutableDirective::getSingleClause( Clauses) || OMPExecutableDirective::getSingleClause(Clauses)) @@ -6584,14 +6567,6 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( case OMPD_dispatch: Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); - if (DispatchDepend2taskwait.get()) { - llvm::SmallVector CombStmtVector = { - DispatchDepend2taskwait.get(), Res.get()}; - auto *CompoundStmt = CompoundStmt::Create( - getASTContext(), CombStmtVector, FPOptionsOverride(), - SourceLocation(), SourceLocation()); - Res = CompoundStmt; - } break; case OMPD_loop: Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc, From d217bc55cc417af46a443116bdf300315b038b9a Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Sat, 29 Mar 2025 01:40:29 -0500 Subject: [PATCH 19/32] Changes to be committed: modified: clang/lib/CodeGen/CGStmtOpenMP.cpp --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 5200b12576aa6..5aa72a46669fa 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -5649,11 +5649,11 @@ void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { void CodeGenFunction::EmitOMPDispatchToTaskwaitDirective( const OMPDispatchDirective &S) { - OMPTaskDataTy Data; - // Build list of dependences - buildDependences(S, Data); - Data.HasNowaitClause = S.hasClausesOfKind(); - CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data); + OMPTaskDataTy Data; + // Build list of dependences + buildDependences(S, Data); + Data.HasNowaitClause = S.hasClausesOfKind(); + CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data); } void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { From 8fba558379b00c4185b33b99284d848446155398 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Thu, 3 Apr 2025 12:59:38 -0500 Subject: [PATCH 20/32] -ast-dump is working with addition of extra virtual region. CodeGen is still in progress. --- clang/lib/Basic/OpenMPKinds.cpp | 5 ++++- clang/lib/CodeGen/CGStmtOpenMP.cpp | 14 ++++++++++---- clang/lib/Sema/SemaOpenMP.cpp | 24 +++++++++++++++++++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index b817a1cf3e92c..7f98d51622e26 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -801,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: @@ -824,7 +828,6 @@ void clang::getOpenMPCaptureRegions( else return true; break; - case OMPD_dispatch: case OMPD_distribute: case OMPD_for: case OMPD_ordered: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 5aa72a46669fa..75b39689cf0d3 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4602,9 +4602,16 @@ static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition, void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { ArrayRef Clauses = S.clauses(); + CapturedStmt *InnerCapturedStmt = nullptr; if (!Clauses.empty()) { - if (S.hasClausesOfKind()) - EmitOMPDispatchToTaskwaitDirective(S); + if (S.hasClausesOfKind()) { + Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); + if (auto *AssocStmt = dyn_cast(AssociatedStmt)) + if (InnerCapturedStmt = + dyn_cast(AssocStmt->getCapturedStmt())) { + EmitOMPDispatchToTaskwaitDirective(S); + } + } if (S.hasClausesOfKind() || S.hasClausesOfKind()) { @@ -4620,8 +4627,7 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { Condition = getInitialExprFromCapturedExpr(NoContextC->getCondition()); } /* OMPC_novariants or OMPC_nocontext present */ - Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); - EmitIfElse(this, Condition, AssociatedStmt); + EmitIfElse(this, Condition, InnerCapturedStmt); } } else EmitStmt(S.getAssociatedStmt()); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 77aff5550a1dc..2156c53c6c83b 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4282,6 +4282,18 @@ getTargetRegionParams(Sema &SemaRef) { return Params; } +static SmallVector +getDispatchRegionParams(Sema &SemaRef) { + ASTContext &Context = SemaRef.getASTContext(); + SmallVector Params; + + // QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); + // Params.push_back(std::make_pair(StringRef(), VoidPtrTy)); + + Params.push_back(std::make_pair(StringRef(), QualType())); + return Params; +} + static SmallVector getUnknownRegionParams(Sema &SemaRef) { SmallVector Params{ @@ -4367,6 +4379,10 @@ static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, getTargetRegionParams(SemaRef), Level); break; + case OMPD_dispatch: + SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, + getDispatchRegionParams(SemaRef), Level); + break; case OMPD_unknown: SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, getUnknownRegionParams(SemaRef)); @@ -6028,8 +6044,13 @@ void SemaOpenMP::annotateAStmt(const ASTContext &Context, Stmt *StmtP, ArrayRef &Clauses, SourceLocation StartLoc) { if (auto *AssocStmt = dyn_cast(StmtP)) { - CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); + if (auto *InnerAssocStmt = + dyn_cast(AssocStmt->getCapturedStmt())) { + // Additional CapturedStmt for Virtual taskwait region + AssocStmt = InnerAssocStmt; + } Stmt *AssocExprStmt = AssocStmt->getCapturedStmt(); + CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); auto *AssocExpr = dyn_cast(AssocExprStmt); bool NoContext = false; @@ -10651,6 +10672,7 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef Clauses, return StmtError(); Stmt *S = cast(AStmt)->getCapturedStmt(); + if (isa(S) S = cast(S)->getCapturedStmt(); // 5.1 OpenMP // expression-stmt : an expression statement with one of the following forms: From 5ec20c325aef2d94ed4906b9c335cb29cf0fbb04 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Thu, 3 Apr 2025 13:01:24 -0500 Subject: [PATCH 21/32] modified: clang/lib/Sema/SemaOpenMP.cpp --- clang/lib/Sema/SemaOpenMP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 2156c53c6c83b..858aa0e8cf07c 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -10672,7 +10672,7 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef Clauses, return StmtError(); Stmt *S = cast(AStmt)->getCapturedStmt(); - if (isa(S) S = cast(S)->getCapturedStmt(); + if (isa(S)) S = cast(S)->getCapturedStmt(); // 5.1 OpenMP // expression-stmt : an expression statement with one of the following forms: From cd8fae5d129384f6f393b3620faa165360c4f282 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Thu, 3 Apr 2025 13:27:58 -0500 Subject: [PATCH 22/32] Formatting problems. modified: clang/lib/Sema/SemaOpenMP.cpp --- clang/lib/Sema/SemaOpenMP.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 858aa0e8cf07c..166a8bd598a13 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -10672,7 +10672,8 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef Clauses, return StmtError(); Stmt *S = cast(AStmt)->getCapturedStmt(); - if (isa(S)) S = cast(S)->getCapturedStmt(); + if (isa(S)) + S = cast(S)->getCapturedStmt(); // 5.1 OpenMP // expression-stmt : an expression statement with one of the following forms: From f47769abf65c3495546a9b5165c27dfaeb28ede9 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Fri, 4 Apr 2025 06:05:57 -0500 Subject: [PATCH 23/32] CodeGen works with this change. modified: clang/lib/CodeGen/CGStmtOpenMP.cpp --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 75b39689cf0d3..69e9ebce2dff9 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4602,15 +4602,9 @@ static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition, void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { ArrayRef Clauses = S.clauses(); - CapturedStmt *InnerCapturedStmt = nullptr; if (!Clauses.empty()) { if (S.hasClausesOfKind()) { - Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); - if (auto *AssocStmt = dyn_cast(AssociatedStmt)) - if (InnerCapturedStmt = - dyn_cast(AssocStmt->getCapturedStmt())) { - EmitOMPDispatchToTaskwaitDirective(S); - } + EmitOMPDispatchToTaskwaitDirective(S); } if (S.hasClausesOfKind() || @@ -4626,8 +4620,17 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { Clauses); Condition = getInitialExprFromCapturedExpr(NoContextC->getCondition()); } + CodeGenFunction::CGCapturedStmtInfo CapStmtInfo; + if (!CapturedStmtInfo) + CapturedStmtInfo = &CapStmtInfo; + Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); + if (auto *AssocStmt = dyn_cast(AssociatedStmt)) + if (auto *InnerCapturedStmt = + dyn_cast(AssocStmt->getCapturedStmt())) { + AssociatedStmt = InnerCapturedStmt; + } /* OMPC_novariants or OMPC_nocontext present */ - EmitIfElse(this, Condition, InnerCapturedStmt); + EmitIfElse(this, Condition, AssociatedStmt); } } else EmitStmt(S.getAssociatedStmt()); From 503222e1b48c786c8761f7b7863ff2898c97da6d Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Fri, 4 Apr 2025 13:13:21 -0500 Subject: [PATCH 24/32] All tests pass with this change. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 69e9ebce2dff9..53a63179ca496 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4602,10 +4602,20 @@ static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition, void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { ArrayRef Clauses = S.clauses(); + + Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); + if (auto *AssocStmt = dyn_cast(AssociatedStmt)) + if (auto *InnerCapturedStmt = + dyn_cast(AssocStmt->getCapturedStmt())) { + AssociatedStmt = InnerCapturedStmt; + } + CodeGenFunction::CGCapturedStmtInfo CapStmtInfo; + if (!CapturedStmtInfo) + CapturedStmtInfo = &CapStmtInfo; + if (!Clauses.empty()) { - if (S.hasClausesOfKind()) { + if (S.hasClausesOfKind()) EmitOMPDispatchToTaskwaitDirective(S); - } if (S.hasClausesOfKind() || S.hasClausesOfKind()) { @@ -4620,20 +4630,11 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { Clauses); Condition = getInitialExprFromCapturedExpr(NoContextC->getCondition()); } - CodeGenFunction::CGCapturedStmtInfo CapStmtInfo; - if (!CapturedStmtInfo) - CapturedStmtInfo = &CapStmtInfo; - Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); - if (auto *AssocStmt = dyn_cast(AssociatedStmt)) - if (auto *InnerCapturedStmt = - dyn_cast(AssocStmt->getCapturedStmt())) { - AssociatedStmt = InnerCapturedStmt; - } /* OMPC_novariants or OMPC_nocontext present */ EmitIfElse(this, Condition, AssociatedStmt); } } else - EmitStmt(S.getAssociatedStmt()); + EmitStmt(AssociatedStmt); } static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S) { From de8b736c0c4bff6c2f3467bf53b3a71412f52c83 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Wed, 9 Apr 2025 01:43:30 -0500 Subject: [PATCH 25/32] 1) Changing the name of the function from getInitialExprFromCapturedExpr() to getCapturedExprFromImplicitCastExpr() 2) Removing extra additions from clang/docs/ReleaseNotes.rst. --- clang/docs/ReleaseNotes.rst | 3 --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index df5889ad4bd80..1714897e9da6b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -537,9 +537,6 @@ Python Binding Changes 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. - Added support 'no_openmp_constructs' assumption clause. - Added support for 'self_maps' in map and requirement clause. diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 53a63179ca496..c0a626aab1783 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4528,7 +4528,7 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { emitMaster(*this, S); } -static Expr *getInitialExprFromCapturedExpr(Expr *Cond) { +static Expr *getCapturedExprFromImplicitCastExpr(Expr *Cond) { Expr *SubExpr = Cond->IgnoreParenImpCasts(); @@ -4623,12 +4623,14 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { if (const OMPNovariantsClause *NoVariantsC = OMPExecutableDirective::getSingleClause( Clauses)) { - Condition = getInitialExprFromCapturedExpr(NoVariantsC->getCondition()); + Condition = + getCapturedExprFromImplicitCastExpr(NoVariantsC->getCondition()); } else { const OMPNocontextClause *NoContextC = OMPExecutableDirective::getSingleClause( Clauses); - Condition = getInitialExprFromCapturedExpr(NoContextC->getCondition()); + Condition = + getCapturedExprFromImplicitCastExpr(NoContextC->getCondition()); } /* OMPC_novariants or OMPC_nocontext present */ EmitIfElse(this, Condition, AssociatedStmt); From b60c252590f2ee92f26c22c3a1673549733f8a90 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Wed, 9 Apr 2025 10:18:07 -0500 Subject: [PATCH 26/32] Added OMPLexicalScope before emitting if-else statement. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 618fc6fb1b6b1..d6f2db3c2ba83 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4577,7 +4577,7 @@ static void transformCallInStmt(Stmt *StmtP) { } } -static void EmitIfElse(CodeGenFunction *CGF, Expr *Condition, +static void emitIfElse(CodeGenFunction *CGF, Expr *Condition, Stmt *AssociatedStmt) { llvm::Value *CondValue = CGF->EvaluateExprAsBool(Condition); llvm::BasicBlock *ThenBlock = CGF->createBasicBlock("if.then"); @@ -4633,8 +4633,9 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { Condition = getCapturedExprFromImplicitCastExpr(NoContextC->getCondition()); } + OMPLexicalScope Scope(CGF, S, OMPD_unknown); /* OMPC_novariants or OMPC_nocontext present */ - EmitIfElse(this, Condition, AssociatedStmt); + emitIfElse(this, Condition, AssociatedStmt); } } else EmitStmt(AssociatedStmt); From d23c5238aa33d6264646c5d895a52c38e393b75c Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Wed, 9 Apr 2025 11:34:48 -0500 Subject: [PATCH 27/32] Changing LexicalScope to OMPD_dispatch. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index d6f2db3c2ba83..1875366ab6092 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4633,7 +4633,7 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { Condition = getCapturedExprFromImplicitCastExpr(NoContextC->getCondition()); } - OMPLexicalScope Scope(CGF, S, OMPD_unknown); + OMPLexicalScope Scope(*this, S, OMPD_dispatch); /* OMPC_novariants or OMPC_nocontext present */ emitIfElse(this, Condition, AssociatedStmt); } From f186576d65d0b5691aa1ca534976e63286795b5e Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Thu, 10 Apr 2025 12:00:27 -0500 Subject: [PATCH 28/32] Removed unused statements. --- clang/lib/Sema/SemaOpenMP.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 166a8bd598a13..0861449c921cc 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4287,9 +4287,6 @@ getDispatchRegionParams(Sema &SemaRef) { ASTContext &Context = SemaRef.getASTContext(); SmallVector Params; - // QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict(); - // Params.push_back(std::make_pair(StringRef(), VoidPtrTy)); - Params.push_back(std::make_pair(StringRef(), QualType())); return Params; } From fd150c26326fbff426111260eb895a36b838b9a8 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Wed, 16 Apr 2025 06:22:54 -0500 Subject: [PATCH 29/32] Replacing getCapturedExprFromImplicitCastExpr() with CGF->EmitBranchOnBoolExpr(). --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 1875366ab6092..31eff4c16e7e4 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4529,21 +4529,6 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { emitMaster(*this, S); } -static Expr *getCapturedExprFromImplicitCastExpr(Expr *Cond) { - - Expr *SubExpr = Cond->IgnoreParenImpCasts(); - - if (auto *DeclRef = dyn_cast(SubExpr)) { - if (auto *CapturedExprDecl = - dyn_cast(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; @@ -4579,12 +4564,11 @@ static void transformCallInStmt(Stmt *StmtP) { 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); + CGF->EmitBranchOnBoolExpr(Condition, ThenBlock, ElseBlock, 0); // Emit the else block. Stmt *ElseStmt = AssociatedStmt; @@ -4624,17 +4608,14 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { if (const OMPNovariantsClause *NoVariantsC = OMPExecutableDirective::getSingleClause( Clauses)) { - Condition = - getCapturedExprFromImplicitCastExpr(NoVariantsC->getCondition()); + Condition = NoVariantsC->getCondition(); } else { const OMPNocontextClause *NoContextC = OMPExecutableDirective::getSingleClause( Clauses); - Condition = - getCapturedExprFromImplicitCastExpr(NoContextC->getCondition()); + Condition = NoContextC->getCondition(); } OMPLexicalScope Scope(*this, S, OMPD_dispatch); - /* OMPC_novariants or OMPC_nocontext present */ emitIfElse(this, Condition, AssociatedStmt); } } else From 07d88276b0dc92846b710889678949ed6397b9e2 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 22 Apr 2025 16:33:28 -0500 Subject: [PATCH 30/32] Adding support for clauses novariants and nocontext occuring on the same dispatch directive. --- .../clang/Basic/DiagnosticSemaKinds.td | 3 - clang/lib/CodeGen/CGStmtOpenMP.cpp | 160 ++++++++++++++---- clang/lib/Sema/SemaOpenMP.cpp | 48 ++++-- clang/test/OpenMP/dispatch_codegen.cpp | 105 +++++++----- clang/test/OpenMP/dispatch_messages.cpp | 1 - 5 files changed, 219 insertions(+), 98 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 03d9f38c0f6cc..d17519d4c4155 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11899,9 +11899,6 @@ 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< - "'nocontext' clause is ignored, only 'novariants' clause is applied">, - InGroup; 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/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 31eff4c16e7e4..e7a2421bc3b4b 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4529,59 +4529,144 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { emitMaster(*this, S); } -static Expr *replaceWithNewTraitsOrDirectCall(Stmt *AssocExpr, - CallExpr *ReplacementFunction) { - Expr *FinalCall = ReplacementFunction; - - if (BinaryOperator *BinaryCopyOpr = dyn_cast(AssocExpr)) { - BinaryCopyOpr->setRHS(FinalCall); - return BinaryCopyOpr; +static Expr *replaceWithNewTraitsOrDirectCall(CapturedDecl *CDecl, + Expr *NewExpr) { + Expr *CurrentCallExpr = nullptr; + Stmt *CallExprStmt = CDecl->getBody(); + + if (BinaryOperator *BinaryCopyOpr = dyn_cast(CallExprStmt)) { + CurrentCallExpr = BinaryCopyOpr->getRHS(); + BinaryCopyOpr->setRHS(NewExpr); + } else { + CurrentCallExpr = dyn_cast(CallExprStmt); + CDecl->setBody(NewExpr); } - return FinalCall; + return CurrentCallExpr; } -static void transformCallInStmt(Stmt *StmtP) { - if (auto *AssocStmt = dyn_cast(StmtP)) { - CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); +static Expr *transformCallInStmt(Stmt *StmtP, bool NoContext = false) { + Expr *CurrentExpr = nullptr; + if (auto *CptStmt = dyn_cast(StmtP)) { + CapturedDecl *CDecl = CptStmt->getCapturedDecl(); - // Access AnnotateAttr CallExpr *NewCallExpr = nullptr; for (const auto *attr : CDecl->attrs()) { - if (const auto *annotateAttr = llvm::dyn_cast(attr); - annotateAttr && - annotateAttr->getAnnotation() == "NoContextInvariant") { - NewCallExpr = llvm::dyn_cast(*annotateAttr->args_begin()); + if (NoContext) { + if (const auto *annotateAttr = + llvm::dyn_cast(attr); + annotateAttr && annotateAttr->getAnnotation() == "NoContextAttr") { + NewCallExpr = llvm::dyn_cast(*annotateAttr->args_begin()); + } + } else { + if (const auto *annotateAttr = + llvm::dyn_cast(attr); + annotateAttr && annotateAttr->getAnnotation() == "NoVariantsAttr") { + NewCallExpr = llvm::dyn_cast(*annotateAttr->args_begin()); + } } } - Stmt *CallExprStmt = CDecl->getBody(); - Stmt *NewCallExprStmt = - replaceWithNewTraitsOrDirectCall(CallExprStmt, NewCallExpr); - CDecl->setBody(NewCallExprStmt); + CurrentExpr = replaceWithNewTraitsOrDirectCall(CDecl, NewCallExpr); } + return CurrentExpr; } -static void emitIfElse(CodeGenFunction *CGF, Expr *Condition, - Stmt *AssociatedStmt) { +// emitIfElse is used for the following conditions: +// +// NoVariants = 0 && NoContext = 1 +// if (Condition_NoContext) { +// foo_variant2(); // Present in AnnotationAttr +// } else { +// foo_variant(); +// } +// +// NoVariants = 1 && NoContext = 0 +// if (Condition_NoVariants) { +// foo(); +// } else { +// foo_variant(); +// } +// +// NoVariants = 1 && NoContext = 1 +// if (Condition_NoVariants) { // ==> label if.then.NoVariants +// foo(); +// } else { // ==> label else.NoVariants +// if (Condition_NoContext) { // ==> label if.then.NoContext +// foo_variant2(); // Present in AnnotationAttr +// } else { // ==> label else +// foo_variant(); +// } +// } +// +static void emitIfElse(CodeGenFunction *CGF, Stmt *AssociatedStmt, + Expr *Condition_NoVariants, Expr *Condition_NoContext) { llvm::BasicBlock *ThenBlock = CGF->createBasicBlock("if.then"); llvm::BasicBlock *ElseBlock = CGF->createBasicBlock("if.else"); llvm::BasicBlock *MergeBlock = CGF->createBasicBlock("if.end"); + llvm::BasicBlock *ThenNoVariantsBlock = nullptr; + llvm::BasicBlock *ElseNoVariantsBlock = nullptr; + llvm::BasicBlock *ThenNoContextBlock = nullptr; + Expr *ElseCall = nullptr; - CGF->EmitBranchOnBoolExpr(Condition, ThenBlock, ElseBlock, 0); + if (Condition_NoVariants && Condition_NoContext) { + ThenNoVariantsBlock = CGF->createBasicBlock("if.then.NoVariants"); + ElseNoVariantsBlock = CGF->createBasicBlock("else.NoVariants"); + ThenNoContextBlock = CGF->createBasicBlock("if.then.NoContext"); + + CGF->EmitBranchOnBoolExpr(Condition_NoVariants, ThenNoVariantsBlock, + ElseNoVariantsBlock, 0); + + } else if (Condition_NoVariants) + CGF->EmitBranchOnBoolExpr(Condition_NoVariants, ThenBlock, ElseBlock, 0); + else + CGF->EmitBranchOnBoolExpr(Condition_NoContext, ThenBlock, ElseBlock, 0); + + if (Condition_NoVariants && Condition_NoContext) { + // Emit the NoVariants (if then, for the NoVariants) block. + CGF->EmitBlock(ThenNoVariantsBlock); + Stmt *ThenStmt = AssociatedStmt; + ElseCall = transformCallInStmt(ThenStmt, false); + CGF->EmitStmt(ThenStmt); + CGF->Builder.CreateBr(MergeBlock); + + CGF->EmitBlock(ElseNoVariantsBlock); + CGF->EmitBranchOnBoolExpr(Condition_NoVariants, ThenNoContextBlock, + ElseBlock, 0); + // Emit the NoContext (else if, for the NoContext) block. + CGF->EmitBlock(ThenNoContextBlock); + Stmt *ThenNoContextStmt = AssociatedStmt; + transformCallInStmt(ThenNoContextStmt, true); + CGF->EmitStmt(ThenNoContextStmt); + CGF->Builder.CreateBr(MergeBlock); + + } else if (Condition_NoVariants) { + // Emit the NoVariants (then) block. + CGF->EmitBlock(ThenBlock); + Stmt *ThenStmt = AssociatedStmt; + ElseCall = transformCallInStmt(ThenStmt, false); + CGF->EmitStmt(ThenStmt); + CGF->Builder.CreateBr(MergeBlock); + + } else if (Condition_NoContext) { + // Emit the NoContext (then) block. + CGF->EmitBlock(ThenBlock); + Stmt *ThenStmt = AssociatedStmt; + ElseCall = transformCallInStmt(ThenStmt, true); + CGF->EmitStmt(ThenStmt); + CGF->Builder.CreateBr(MergeBlock); + } // Emit the else block. - Stmt *ElseStmt = AssociatedStmt; CGF->EmitBlock(ElseBlock); + Stmt *ElseStmt = AssociatedStmt; + if (auto *CaptStmt = dyn_cast(ElseStmt)) { + CapturedDecl *CDecl = CaptStmt->getCapturedDecl(); + replaceWithNewTraitsOrDirectCall(CDecl, ElseCall); + } 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); } @@ -4598,25 +4683,32 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { if (!CapturedStmtInfo) CapturedStmtInfo = &CapStmtInfo; + Expr *NoVariantsCondition = nullptr; + Expr *NoContextCondition = nullptr; if (!Clauses.empty()) { if (S.hasClausesOfKind()) EmitOMPDispatchToTaskwaitDirective(S); if (S.hasClausesOfKind() || S.hasClausesOfKind()) { - Expr *Condition = nullptr; if (const OMPNovariantsClause *NoVariantsC = OMPExecutableDirective::getSingleClause( Clauses)) { - Condition = NoVariantsC->getCondition(); + NoVariantsCondition = NoVariantsC->getCondition(); + if (const OMPNocontextClause *NoContextC = + OMPExecutableDirective::getSingleClause( + Clauses)) { + NoContextCondition = NoContextC->getCondition(); + } } else { const OMPNocontextClause *NoContextC = OMPExecutableDirective::getSingleClause( Clauses); - Condition = NoContextC->getCondition(); + NoContextCondition = NoContextC->getCondition(); } + OMPLexicalScope Scope(*this, S, OMPD_dispatch); - emitIfElse(this, Condition, AssociatedStmt); + emitIfElse(this, AssociatedStmt, NoVariantsCondition, NoContextCondition); } } else EmitStmt(AssociatedStmt); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 0861449c921cc..1d895171eb4bd 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6030,6 +6030,28 @@ static Expr *getNewTraitsOrDirectCall(const ASTContext &Context, return FinalCall; } +// Add Attribute NoContextAttr or NoVariantsAttr +// to the CapturedDecl. +static void addAttr(const ASTContext &Context, Expr *AssocExpr, + SemaOpenMP *SemaPtr, bool NoContext, CapturedDecl *CDecl) { + llvm::SmallVector Args; + Expr *NewCallExpr = nullptr; + + if (NoContext) { + NewCallExpr = getNewTraitsOrDirectCall(Context, AssocExpr, SemaPtr, true); + Args.push_back(NewCallExpr); + CDecl->addAttr(AnnotateAttr::CreateImplicit( + const_cast(Context), "NoContextAttr", Args.data(), + Args.size())); + } else { + NewCallExpr = getNewTraitsOrDirectCall(Context, AssocExpr, SemaPtr, false); + Args.push_back(NewCallExpr); + CDecl->addAttr(AnnotateAttr::CreateImplicit( + const_cast(Context), "NoVariantsAttr", Args.data(), + Args.size())); + } +} + /// annotateAStmt() function is used by ActOnOpenMPExecutableDirective() /// for the dispatch directive (nocontext or invariant clauses). /// An annotation "NoContextInvariant" is added to the Captured Decl @@ -6049,24 +6071,20 @@ void SemaOpenMP::annotateAStmt(const ASTContext &Context, Stmt *StmtP, Stmt *AssocExprStmt = AssocStmt->getCapturedStmt(); CapturedDecl *CDecl = AssocStmt->getCapturedDecl(); auto *AssocExpr = dyn_cast(AssocExprStmt); - bool NoContext = false; if (OMPExecutableDirective::getSingleClause(Clauses)) { - - if (OMPExecutableDirective::getSingleClause(Clauses)) - Diag(StartLoc, diag::warn_omp_dispatch_clause_novariants_nocontext); + addAttr(const_cast(Context), AssocExpr, SemaPtr, false, + CDecl); + if (OMPExecutableDirective::getSingleClause( + Clauses)) { + addAttr(const_cast(Context), AssocExpr, SemaPtr, true, + CDecl); + } } else if (OMPExecutableDirective::getSingleClause( - Clauses)) - NoContext = true; - - Expr *NewCallExpr = - getNewTraitsOrDirectCall(Context, AssocExpr, SemaPtr, NoContext); - // Annotate "NoContextInvariant" to CDecl of the AssocStmt - llvm::SmallVector Args; - Args.push_back(NewCallExpr); - CDecl->addAttr(AnnotateAttr::CreateImplicit( - const_cast(Context), "NoContextInvariant", Args.data(), - Args.size())); + Clauses)) { + addAttr(const_cast(Context), AssocExpr, SemaPtr, true, + CDecl); + } } } diff --git a/clang/test/OpenMP/dispatch_codegen.cpp b/clang/test/OpenMP/dispatch_codegen.cpp index 1661086d74132..8da387640d988 100644 --- a/clang/test/OpenMP/dispatch_codegen.cpp +++ b/clang/test/OpenMP/dispatch_codegen.cpp @@ -89,6 +89,9 @@ void checkDepend() #pragma omp dispatch depend(out:x) nocontext(cond_false) foo(x,y); + + #pragma omp dispatch depend(out:x) novariants(cond_false) nocontext(cond_true) + output = foo(x,y); } int bar_variant(int x) { @@ -163,16 +166,16 @@ void checkNoContext_withoutVariant() { // CHECK-LABEL: {{.+}}checkNoVariants{{.+}} // CHECK-LABEL: entry: // #pragma omp dispatch novariants(cond_false) -// CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.1{{.+}} // 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.else{{.+}} -// CHECK: call {{.+}}captured_stmt.3{{.+}} // CHECK-LABEL: if.then{{.+}} +// CHECK: call {{.+}}captured_stmt.3{{.+}} +// CHECK-LABEL: if.else{{.+}} // CHECK: call {{.+}}captured_stmt.4{{.+}} // CHECK-LABEL: if.end{{.+}} // @@ -180,16 +183,16 @@ void checkNoContext_withoutVariant() { // CHECK-LABEL: entry: // // #pragma omp dispatch nocontext(cond_false) -// CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.5{{.+}} // 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.else{{.+}} -// CHECK: call {{.+}}captured_stmt.7{{.+}} // CHECK-LABEL: if.then{{.+}} +// CHECK: call {{.+}}captured_stmt.7{{.+}} +// CHECK-LABEL: if.else{{.+}} // CHECK: call {{.+}}captured_stmt.8{{.+}} // CHECK-LABEL: if.end{{.+}} // @@ -204,69 +207,81 @@ void checkNoContext_withoutVariant() { // // #pragma omp dispatch depend(out:x) novariants(cond_false) // CHECK: call {{.+}}kmpc_omp_taskwait_deps{{.+}} -// CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.9{{.+}} // CHECK-LABEL: if.then{{.+}} +// CHECK: call {{.+}}captured_stmt.9{{.+}} +// CHECK-LABEL: if.else{{.+}} // CHECK: call {{.+}}captured_stmt.10{{.+}} // CHECK-LABEL: if.end{{.+}} // // #pragma omp dispatch depend(out:x) nocontext(cond_false) // CHECK: call {{.+}}kmpc_omp_taskwait_deps{{.+}} -// CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.11{{.+}} // CHECK-LABEL: if.then{{.+}} +// CHECK: call {{.+}}captured_stmt.11{{.+}} +// CHECK-LABEL: if.else{{.+}} // CHECK: call {{.+}}captured_stmt.12{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.1{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.2{{.+}} -// CHECK: call {{.+}}foo{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.3{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.4{{.+}} -// CHECK: call {{.+}}foo{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.5{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo_variant_allCond{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.6{{.+}} -// CHECK: call {{.+}}foo_variant_allCond{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.7{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo_variant_allCond{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.8{{.+}} -// CHECK: call {{.+}}foo_variant_allCond{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.9{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.10{{.+}} -// CHECK: call {{.+}}foo{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}__captured_stmt.11{{.+}} -// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: call {{.+}}foo_variant_allCond{{.+}} // 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{{.+}} +// CHECK: ret void +// +// CHECK-LABEL: define {{.+}}__captured_stmt.14{{.+}} // CHECK: call {{.+}}foo_variant_allCond{{.+}} // CHECK: ret void // +// CHECK-LABEL: define {{.+}}__captured_stmt.15{{.+}} +// CHECK: call {{.+}}foo_variant_dispatch{{.+}} +// CHECK: ret void +// // CHECK-LABEL: define {{.+}}bar_variant{{.+}} // CHECK-LABEL: entry: // CHECK: ret{{.+}} @@ -278,72 +293,72 @@ void checkNoContext_withoutVariant() { // CHECK-LABEL: define {{.+}}without_declareVariant{{.+}} // CHECK-LABEL: entry: // CHECK: call {{.+}}bar{{.+}} -// CHECK: call {{.+}}captured_stmt.13{{.+}} +// CHECK: call {{.+}}captured_stmt.16{{.+}} // CHECK-NEXT: call {{.+}}checkNoVariants_withoutVariant{{.+}} // CHECK-NEXT: call {{.+}}checkNoContext_withoutVariant{{.+}} // CHECK-NEXT: ret{{.+}} // // #pragma omp dispatch -// CHECK-LABEL: define {{.+}}__captured_stmt.13{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.16{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // CHECK-LABEL: define {{.+}}checkNoVariants_withoutVariant{{.+}} // CHECK-LABEL: entry: -// CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.14{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.15{{.+}} -// CHECK-LABEL: if.end{{.+}} +// CHECK: call {{.+}}captured_stmt.17{{.+}} // CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.16{{.+}} +// CHECK: call {{.+}}captured_stmt.18{{.+}} +// CHECK-LABEL: if.end{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.17{{.+}} +// CHECK: call {{.+}}captured_stmt.19{{.+}} +// CHECK-LABEL: if.else{{.+}} +// CHECK: call {{.+}}captured_stmt.20{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret{{.+}} // // CHECK-LABEL: define {{.+}}checkNoContext_withoutVariant{{.+}} // CHECK-LABEL: entry: -// CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.18{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.19{{.+}} -// CHECK-LABEL: if.end{{.+}} +// CHECK: call {{.+}}captured_stmt.21{{.+}} // CHECK-LABEL: if.else{{.+}} -// CHECK: call {{.+}}captured_stmt.20{{.+}} +// CHECK: call {{.+}}captured_stmt.22{{.+}} +// CHECK-LABEL: if.end{{.+}} // CHECK-LABEL: if.then{{.+}} -// CHECK: call {{.+}}captured_stmt.21{{.+}} +// CHECK: call {{.+}}captured_stmt.23{{.+}} +// CHECK-LABEL: if.else{{.+}} +// CHECK: call {{.+}}captured_stmt.24{{.+}} // CHECK-LABEL: if.end{{.+}} // CHECK: ret{{.+}} // // #pragma omp dispatch novariants(cond_true) -// CHECK-LABEL: define {{.+}}__captured_stmt.14{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.17{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.15{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.18{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // #pragma omp dispatch novariants(cond_false) -// CHECK-LABEL: define {{.+}}__captured_stmt.16{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.19{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.17{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.20{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // #pragma omp dispatch nocontext(cond_true) -// CHECK-LABEL: define {{.+}}__captured_stmt.18{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.21{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.19{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.22{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void // // #pragma omp dispatch nocontext(cond_false) -// CHECK-LABEL: define {{.+}}__captured_stmt.20{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.23{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void -// CHECK-LABEL: define {{.+}}__captured_stmt.21{{.+}} +// CHECK-LABEL: define {{.+}}__captured_stmt.24{{.+}} // CHECK: call {{.+}}bar{{.+}} // CHECK: ret void diff --git a/clang/test/OpenMP/dispatch_messages.cpp b/clang/test/OpenMP/dispatch_messages.cpp index d1435b05224fe..5d1fc77f6bdce 100644 --- a/clang/test/OpenMP/dispatch_messages.cpp +++ b/clang/test/OpenMP/dispatch_messages.cpp @@ -103,7 +103,6 @@ void testit_one(int dnum) { #pragma omp dispatch depend(in:b) depend(in:a) output = disp_call(); - // expected-warning@+1 {{'nocontext' clause is ignored, only 'novariants' clause is applied}} #pragma omp dispatch nocontext(c1) novariants(c2) depend(inout:a) disp_call(); } From 4206c6ea6562163411fdec9cb408d4cbce5b742f Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Thu, 24 Apr 2025 03:43:47 -0500 Subject: [PATCH 31/32] Rolling back changes to make template related changes in this patch. Changes to be committed: modified: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 426cb18a9aca6..e0f7ccc4674d8 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -423,8 +423,8 @@ static void instantiateOMPDeclareVariantAttr( auto *FD = cast(New); auto *ThisContext = dyn_cast_or_null(FD->getDeclContext()); - auto &&SubstExpr = [FD, ThisContext, &S, &TemplateArgs, New](Expr *E) { - if (auto *DRE = dyn_cast(E->IgnoreParenImpCasts())) { + auto &&SubstExpr = [FD, ThisContext, &S, &TemplateArgs](Expr *E) { + if (auto *DRE = dyn_cast(E->IgnoreParenImpCasts())) if (auto *PVD = dyn_cast(DRE->getDecl())) { Sema::ContextRAII SavedContext(S, FD); LocalInstantiationScope Local(S); @@ -433,7 +433,6 @@ static void instantiateOMPDeclareVariantAttr( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); return S.SubstExpr(E, TemplateArgs); } - } Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), FD->isCXXInstanceMember()); return S.SubstExpr(E, TemplateArgs); From 6a3566473653ab7c64782856fb64fc8aa544c136 Mon Sep 17 00:00:00 2001 From: Sunil Kuravinakop Date: Tue, 6 May 2025 01:38:47 -0500 Subject: [PATCH 32/32] Minor changes based on review feedback. --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 30 ++++++++++++++---------------- clang/lib/Sema/SemaOpenMP.cpp | 7 +++---- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index e7a2421bc3b4b..d35547049d408 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4617,10 +4617,11 @@ static void emitIfElse(CodeGenFunction *CGF, Stmt *AssociatedStmt, CGF->EmitBranchOnBoolExpr(Condition_NoVariants, ThenNoVariantsBlock, ElseNoVariantsBlock, 0); - } else if (Condition_NoVariants) + } else if (Condition_NoVariants) { CGF->EmitBranchOnBoolExpr(Condition_NoVariants, ThenBlock, ElseBlock, 0); - else + } else { CGF->EmitBranchOnBoolExpr(Condition_NoContext, ThenBlock, ElseBlock, 0); + } if (Condition_NoVariants && Condition_NoContext) { // Emit the NoVariants (if then, for the NoVariants) block. @@ -4640,19 +4641,15 @@ static void emitIfElse(CodeGenFunction *CGF, Stmt *AssociatedStmt, CGF->EmitStmt(ThenNoContextStmt); CGF->Builder.CreateBr(MergeBlock); - } else if (Condition_NoVariants) { - // Emit the NoVariants (then) block. - CGF->EmitBlock(ThenBlock); - Stmt *ThenStmt = AssociatedStmt; - ElseCall = transformCallInStmt(ThenStmt, false); - CGF->EmitStmt(ThenStmt); - CGF->Builder.CreateBr(MergeBlock); + } else { + bool CNoVariantsOrCNoContext = false; + if (Condition_NoContext) { + CNoVariantsOrCNoContext = true; + } - } else if (Condition_NoContext) { - // Emit the NoContext (then) block. CGF->EmitBlock(ThenBlock); Stmt *ThenStmt = AssociatedStmt; - ElseCall = transformCallInStmt(ThenStmt, true); + ElseCall = transformCallInStmt(ThenStmt, CNoVariantsOrCNoContext); CGF->EmitStmt(ThenStmt); CGF->Builder.CreateBr(MergeBlock); } @@ -4674,11 +4671,11 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { ArrayRef Clauses = S.clauses(); Stmt *AssociatedStmt = const_cast(S.getAssociatedStmt()); - if (auto *AssocStmt = dyn_cast(AssociatedStmt)) + if (auto *AssocStmt = dyn_cast(AssociatedStmt)) { if (auto *InnerCapturedStmt = - dyn_cast(AssocStmt->getCapturedStmt())) { + dyn_cast(AssocStmt->getCapturedStmt())) AssociatedStmt = InnerCapturedStmt; - } + } CodeGenFunction::CGCapturedStmtInfo CapStmtInfo; if (!CapturedStmtInfo) CapturedStmtInfo = &CapStmtInfo; @@ -4710,8 +4707,9 @@ void CodeGenFunction::EmitOMPDispatchDirective(const OMPDispatchDirective &S) { OMPLexicalScope Scope(*this, S, OMPD_dispatch); emitIfElse(this, AssociatedStmt, NoVariantsCondition, NoContextCondition); } - } else + } else { EmitStmt(AssociatedStmt); + } } static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 1d895171eb4bd..f1354b5f8535f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4284,10 +4284,9 @@ getTargetRegionParams(Sema &SemaRef) { static SmallVector getDispatchRegionParams(Sema &SemaRef) { - ASTContext &Context = SemaRef.getASTContext(); SmallVector Params; - Params.push_back(std::make_pair(StringRef(), QualType())); + Params.emplace_back(StringRef(), QualType()); return Params; } @@ -10687,8 +10686,8 @@ SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef Clauses, return StmtError(); Stmt *S = cast(AStmt)->getCapturedStmt(); - if (isa(S)) - S = cast(S)->getCapturedStmt(); + if (auto *CS = dyn_cast(S)) + S = CS->getCapturedStmt(); // 5.1 OpenMP // expression-stmt : an expression statement with one of the following forms: