Author: Mike Rice Date: 2021-03-30T14:12:53-07:00 New Revision: b7899ba0e8b7a7b8fbab06a8b3f2d70f16d7a250
URL: https://github.com/llvm/llvm-project/commit/b7899ba0e8b7a7b8fbab06a8b3f2d70f16d7a250 DIFF: https://github.com/llvm/llvm-project/commit/b7899ba0e8b7a7b8fbab06a8b3f2d70f16d7a250.diff LOG: [OPENMP51]Initial support for the dispatch directive. Added basic parsing/sema/serialization support for dispatch directive. Differential Revision: https://reviews.llvm.org/D99537 Added: clang/test/OpenMP/dispatch_ast_print.cpp clang/test/OpenMP/dispatch_messages.cpp Modified: clang/include/clang-c/Index.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/AST/StmtOpenMP.h clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/StmtNodes.td clang/include/clang/Sema/Sema.h clang/include/clang/Serialization/ASTBitCodes.h clang/lib/AST/StmtOpenMP.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/StmtProfile.cpp clang/lib/Basic/OpenMPKinds.cpp clang/lib/CodeGen/CGStmt.cpp clang/lib/Parse/ParseOpenMP.cpp clang/lib/Sema/SemaExceptionSpec.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/tools/libclang/CIndex.cpp clang/tools/libclang/CXCursor.cpp llvm/include/llvm/Frontend/OpenMP/OMP.td llvm/include/llvm/Frontend/OpenMP/OMPKinds.def Removed: ################################################################################ diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index bcc063051b8c3..696e271a72313 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2580,7 +2580,11 @@ enum CXCursorKind { */ CXCursor_OMPInteropDirective = 290, - CXCursor_LastStmt = CXCursor_OMPInteropDirective, + /** OpenMP dispatch directive. + */ + CXCursor_OMPDispatchDirective = 291, + + CXCursor_LastStmt = CXCursor_OMPDispatchDirective, /** * Cursor that represents the translation unit itself. diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 256f73338bd27..23864819bc07e 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2971,6 +2971,9 @@ DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeSimdDirective, DEF_TRAVERSE_STMT(OMPInteropDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPDispatchDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index 6ddc29446a8c8..a59b36c302a3d 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -5139,6 +5139,72 @@ class OMPInteropDirective final : public OMPExecutableDirective { } }; +/// This represents '#pragma omp dispatch' directive. +/// +/// \code +/// #pragma omp dispatch device(dnum) +/// \endcode +/// This example shows a directive '#pragma omp dispatch' with a +/// device clause with variable 'dnum'. +/// +class OMPDispatchDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + + /// The location of the target-call. + SourceLocation TargetCallLoc; + + /// Set the location of the target-call. + void setTargetCallLoc(SourceLocation Loc) { TargetCallLoc = Loc; } + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPDispatchDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(OMPDispatchDirectiveClass, + llvm::omp::OMPD_dispatch, StartLoc, EndLoc) {} + + /// Build an empty directive. + /// + explicit OMPDispatchDirective() + : OMPExecutableDirective(OMPDispatchDirectiveClass, + llvm::omp::OMPD_dispatch, SourceLocation(), + SourceLocation()) {} + +public: + /// Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param TargetCallLoc Location of the target-call. + /// + static OMPDispatchDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + SourceLocation TargetCallLoc); + + /// Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPDispatchDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + /// Return location of target-call. + SourceLocation getTargetCallLoc() const { return TargetCallLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPDispatchDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ad592d5520300..099e73ed013a0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10616,6 +10616,9 @@ def err_omp_interop_bad_depend_clause : Error< "'depend' clause requires the 'targetsync' interop type">; def err_omp_interop_var_multiple_actions : Error< "interop variable %0 used in multiple action clauses">; +def err_omp_dispatch_statement_call + : Error<"statement after '#pragma omp dispatch' must be a direct call" + " to a target function or an assignment to one">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 4aac8a32ef976..d2e8fa69a5840 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -276,3 +276,4 @@ def OMPTargetTeamsDistributeParallelForDirective : StmtNode<OMPLoopDirective>; def OMPTargetTeamsDistributeParallelForSimdDirective : StmtNode<OMPLoopDirective>; def OMPTargetTeamsDistributeSimdDirective : StmtNode<OMPLoopDirective>; def OMPInteropDirective : StmtNode<OMPExecutableDirective>; +def OMPDispatchDirective : StmtNode<OMPExecutableDirective>; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8e1bc3f2dbdab..b5c8d3d292fcf 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10804,6 +10804,11 @@ class Sema final { StmtResult ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp dispatch' after parsing of the + // /associated statement. + StmtResult ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); /// Checks correctness of linear modifiers. bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 64f15e75bc2c8..17690b901eacf 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1941,6 +1941,7 @@ enum StmtCode { STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE, STMT_OMP_INTEROP_DIRECTIVE, + STMT_OMP_DISPATCH_DIRECTIVE, EXPR_OMP_ARRAY_SECTION, EXPR_OMP_ARRAY_SHAPING, EXPR_OMP_ITERATOR, diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index fa77b862f3d0e..7dc43ea924508 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -1959,3 +1959,21 @@ OMPInteropDirective *OMPInteropDirective::CreateEmpty(const ASTContext &C, EmptyShell) { return createEmptyDirective<OMPInteropDirective>(C, NumClauses); } + +OMPDispatchDirective *OMPDispatchDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + SourceLocation TargetCallLoc) { + auto *Dir = createDirective<OMPDispatchDirective>( + C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc); + Dir->setTargetCallLoc(TargetCallLoc); + return Dir; +} + +OMPDispatchDirective *OMPDispatchDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + return createEmptyDirective<OMPDispatchDirective>(C, NumClauses, + /*HasAssociatedStmt=*/true, + /*NumChildren=*/0); +} diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index ca35c6dccbf8c..5993268971f8b 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -967,6 +967,11 @@ void StmtPrinter::VisitOMPInteropDirective(OMPInteropDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPDispatchDirective(OMPDispatchDirective *Node) { + Indent() << "#pragma omp dispatch"; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index bf130ed4ff3d3..fa3ab3ce977a5 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1144,6 +1144,10 @@ void StmtProfiler::VisitOMPInteropDirective(const OMPInteropDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPDispatchDirective(const OMPDispatchDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index e289e953d47ff..00abb3062ca61 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -660,6 +660,7 @@ void clang::getOpenMPCaptureRegions( case OMPD_atomic: case OMPD_target_data: case OMPD_distribute_simd: + case OMPD_dispatch: CaptureRegions.push_back(OMPD_unknown); break; case OMPD_tile: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index fb719efb1a35d..b4ddfa586d1aa 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -378,6 +378,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) { case Stmt::OMPInteropDirectiveClass: llvm_unreachable("Interop directive not supported yet."); break; + case Stmt::OMPDispatchDirectiveClass: + llvm_unreachable("Dispatch directive not supported yet."); + break; } } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 1ea01409d3d36..54e24e94e6611 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2207,6 +2207,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_target_teams_distribute_parallel_for: case OMPD_target_teams_distribute_parallel_for_simd: case OMPD_target_teams_distribute_simd: + case OMPD_dispatch: Diag(Tok, diag::err_omp_unexpected_directive) << 1 << getOpenMPDirectiveName(DKind); break; @@ -2430,7 +2431,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_target_teams_distribute: case OMPD_target_teams_distribute_parallel_for: case OMPD_target_teams_distribute_parallel_for_simd: - case OMPD_target_teams_distribute_simd: { + case OMPD_target_teams_distribute_simd: + case OMPD_dispatch: { // Special processing for flush and depobj clauses. Token ImplicitTok; bool ImplicitClauseAllowed = false; diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index a9a487bd47a38..12f47cb0630d0 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1487,6 +1487,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: case Stmt::OMPTeamsDistributeSimdDirectiveClass: case Stmt::OMPInteropDirectiveClass: + case Stmt::OMPDispatchDirectiveClass: case Stmt::ReturnStmtClass: case Stmt::SEHExceptStmtClass: case Stmt::SEHFinallyStmtClass: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index fcb95e3a8442c..48fe19e50ee71 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3979,7 +3979,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_distribute: case OMPD_distribute_simd: case OMPD_ordered: - case OMPD_target_data: { + case OMPD_target_data: + case OMPD_dispatch: { Sema::CapturedParamNameType Params[] = { std::make_pair(StringRef(), QualType()) // __context with shared vars }; @@ -6120,6 +6121,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( "No associated statement allowed for 'omp interop' directive"); Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc); break; + case OMPD_dispatch: + Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc); + break; case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_threadprivate: @@ -9758,6 +9763,64 @@ StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt, DSAStack->isCancelRegion()); } +static Expr *getDirectCallExpr(Expr *E) { + E = E->IgnoreParenCasts()->IgnoreImplicit(); + if (auto *CE = dyn_cast<CallExpr>(E)) + if (CE->getDirectCallee()) + return E; + return nullptr; +} + +StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + if (!AStmt) + return StmtError(); + + Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt(); + + // 5.1 OpenMP + // expression-stmt : an expression statement with one of the following forms: + // expression = target-call ( [expression-list] ); + // target-call ( [expression-list] ); + + SourceLocation TargetCallLoc; + + if (!CurContext->isDependentContext()) { + Expr *TargetCall = nullptr; + + auto *E = dyn_cast<Expr>(S); + if (!E) { + Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call); + return StmtError(); + } + + E = E->IgnoreParenCasts()->IgnoreImplicit(); + + if (auto *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Assign) + TargetCall = getDirectCallExpr(BO->getRHS()); + } else { + if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E)) + if (COCE->getOperator() == OO_Equal) + TargetCall = getDirectCallExpr(COCE->getArg(1)); + if (!TargetCall) + TargetCall = getDirectCallExpr(E); + } + if (!TargetCall) { + Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call); + return StmtError(); + } + TargetCallLoc = TargetCall->getExprLoc(); + } + + setFunctionHasBranchProtectedScope(); + + return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, + TargetCallLoc); +} + StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -13349,6 +13412,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_target_parallel_for_simd: case OMPD_target_teams_distribute_parallel_for: case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_dispatch: CaptureRegion = OMPD_task; break; case OMPD_target_data: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6fa91035a0c48..86a25149a23c1 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -9069,6 +9069,17 @@ TreeTransform<Derived>::TransformOMPInteropDirective(OMPInteropDirective *D) { return Res; } +template <typename Derived> +StmtResult +TreeTransform<Derived>::TransformOMPDispatchDirective(OMPDispatchDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_dispatch, DirName, nullptr, + D->getBeginLoc()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + //===----------------------------------------------------------------------===// // OpenMP clause transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 22e1f57e3313e..6e552e9a2441f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2593,6 +2593,12 @@ void ASTStmtReader::VisitOMPInteropDirective(OMPInteropDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPDispatchDirective(OMPDispatchDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + D->setTargetCallLoc(Record.readSourceLocation()); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -3513,6 +3519,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_DISPATCH_DIRECTIVE: + S = OMPDispatchDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = CXXOperatorCallExpr::CreateEmpty( Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index ed14058aeb0d6..97ecd5a773ea1 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2547,6 +2547,13 @@ void ASTStmtWriter::VisitOMPInteropDirective(OMPInteropDirective *D) { Code = serialization::STMT_OMP_INTEROP_DIRECTIVE; } +void ASTStmtWriter::VisitOMPDispatchDirective(OMPDispatchDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Record.AddSourceLocation(D->getTargetCallLoc()); + Code = serialization::STMT_OMP_DISPATCH_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index fbd5fd87fcf0e..1498efd135d2c 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1295,6 +1295,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: case Stmt::OMPTileDirectiveClass: case Stmt::OMPInteropDirectiveClass: + case Stmt::OMPDispatchDirectiveClass: case Stmt::CapturedStmtClass: { const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState()); Engine.addAbortedBlock(node, currBldrCtx->getBlock()); diff --git a/clang/test/OpenMP/dispatch_ast_print.cpp b/clang/test/OpenMP/dispatch_ast_print.cpp new file mode 100644 index 0000000000000..3dea4cbcd3f97 --- /dev/null +++ b/clang/test/OpenMP/dispatch_ast_print.cpp @@ -0,0 +1,215 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fopenmp -fopenmp-version=51 \ +// RUN: -fsyntax-only -verify %s + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \ +// RUN: -fsyntax-only -verify %s + +// expected-no-diagnostics + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \ +// RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \ +// RUN: -ast-dump %s | FileCheck %s --check-prefix=DUMP + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \ +// RUN: -emit-pch -o %t %s + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \ +// RUN: -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \ +// RUN: -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT + +#ifndef HEADER +#define HEADER + +int foo_gpu(int A, int *B) { return 0;} +//PRINT: #pragma omp declare variant(foo_gpu) +//DUMP: FunctionDecl{{.*}} foo +//DUMP: OMPDeclareVariantAttr {{.*}}Implicit construct{{.*}} +#pragma omp declare variant(foo_gpu) \ + match(construct={dispatch}, device={arch(arm)}) +int foo(int, int*); + +template <typename T, typename TP> +void fooTemp() { + T a; + TP b; + //PRINT: #pragma omp dispatch nowait + //DUMP: OMPDispatchDirective + //DUMP: OMPNowaitClause + #pragma omp dispatch nowait + foo(a, b); +} + +int *get_device_ptr(); +int get_device(); +int other(); + +//DUMP: FunctionDecl{{.*}} test_one +void test_one() +{ + int aaa, bbb, var; + //PRINT: #pragma omp dispatch depend(in : var) nowait + //DUMP: OMPDispatchDirective + //DUMP: OMPDependClause + //DUMP: OMPNowaitClause + #pragma omp dispatch depend(in:var) nowait + foo(aaa, &bbb); + + int *dp = get_device_ptr(); + int dev = get_device(); + //PRINT: #pragma omp dispatch device(dev) is_device_ptr(dp) + //DUMP: OMPDispatchDirective + //DUMP: OMPDeviceClause + //DUMP: OMPIs_device_ptrClause + #pragma omp dispatch device(dev) is_device_ptr(dp) + foo(aaa, dp); + + //PRINT: #pragma omp dispatch + //PRINT: foo(other(), &bbb); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + foo(other(), &bbb); + + fooTemp<int, int*>(); +} + +struct Obj { + Obj(); + ~Obj(); + int disp_method_variant1(); + #pragma omp declare variant(disp_method_variant1) \ + match(construct={dispatch}, device={arch(arm)}) + int disp_method1(); + + static int disp_method_variant2() { return 1; } + #pragma omp declare variant(disp_method_variant2) \ + match(construct={dispatch}, device={arch(arm)}) + static int disp_method2() { return 2; } +}; + +Obj foo_vari(); +#pragma omp declare variant(foo_vari) \ + match(construct={dispatch}, device={arch(arm)}) +Obj foo_obj(); + +//DUMP: FunctionDecl{{.*}} test_two +void test_two(Obj o1, Obj &o2, Obj *o3) +{ + //PRINT: #pragma omp dispatch + //PRINT: o1.disp_method1(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + o1.disp_method1(); + + //PRINT: #pragma omp dispatch + //PRINT: o2.disp_method1(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + o2.disp_method1(); + + //PRINT: #pragma omp dispatch + //PRINT: o3->disp_method1(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + o3->disp_method1(); + + //PRINT: #pragma omp dispatch + //PRINT: Obj::disp_method2(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + Obj::disp_method2(); + + int ret; + //PRINT: #pragma omp dispatch + //PRINT: ret = o1.disp_method1(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + ret = o1.disp_method1(); + + //PRINT: #pragma omp dispatch + //PRINT: ret = o2.disp_method1(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + ret = o2.disp_method1(); + + //PRINT: #pragma omp dispatch + //PRINT: ret = o3->disp_method1(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + ret = o3->disp_method1(); + + //PRINT: #pragma omp dispatch + //PRINT: ret = Obj::disp_method2(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + ret = Obj::disp_method2(); + + //PRINT: #pragma omp dispatch + //PRINT: (void)Obj::disp_method2(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + (void)Obj::disp_method2(); + + // Full C++ operator= case with temps and EH. + Obj o; + //PRINT: #pragma omp dispatch + //PRINT: o = foo_obj(); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + o = foo_obj(); +} + +struct A { + A& disp_operator(A other); + #pragma omp declare variant(disp_operator) \ + match(construct={dispatch}, device={arch(arm)}) + A& operator=(A other); +}; + +struct Obj2 { + A xx; + Obj2& disp_operator(Obj2 other); + #pragma omp declare variant(disp_operator) \ + match(construct={dispatch}, device={arch(arm)}) + Obj2& operator=(Obj2 other); + + void foo() { + Obj2 z; + //PRINT: #pragma omp dispatch + //PRINT: z = z; + //DUMP: OMPDispatchDirective + #pragma omp dispatch + z = z; + //PRINT: #pragma omp dispatch + //PRINT: z.operator=(z); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + z.operator=(z); + } + void bar() { + Obj2 j; + //PRINT: #pragma omp dispatch + //PRINT: j = {this->xx}; + //DUMP: OMPDispatchDirective + #pragma omp dispatch + j = {this->xx}; + //PRINT: #pragma omp dispatch + //PRINT: j.operator=({this->xx}); + //DUMP: OMPDispatchDirective + #pragma omp dispatch + j.operator=({this->xx}); + } +}; + +void test_three() +{ + Obj2 z1, z; + #pragma omp dispatch + z1 = z; + #pragma omp dispatch + z1.operator=(z); +} +#endif // HEADER diff --git a/clang/test/OpenMP/dispatch_messages.cpp b/clang/test/OpenMP/dispatch_messages.cpp new file mode 100644 index 0000000000000..221c7b784c00e --- /dev/null +++ b/clang/test/OpenMP/dispatch_messages.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp \ +// RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions %s + +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -verify -fopenmp \ +// RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions %s + +int disp_variant(); +#pragma omp declare variant(disp_variant) \ + match(construct = {dispatch}, device = {arch(arm)}) +int disp_call(); + +struct Obj { + int disp_method_variant1(); + #pragma omp declare variant(disp_method_variant1) \ + match(construct={dispatch}, device={arch(arm)}) + int disp_method1(); + int disp_method_variant2(); + #pragma omp declare variant(disp_method_variant2) \ + match(construct={dispatch}, device={arch(arm)}) + int disp_method2(); +}; + +void testit_one(int dnum) { + // expected-error@+1 {{cannot contain more than one 'device' clause}} + #pragma omp dispatch device(dnum) device(3) + disp_call(); + + // expected-error@+1 {{cannot contain more than one 'nowait' clause}} + #pragma omp dispatch nowait device(dnum) nowait + disp_call(); +} + +void testit_two() { + //expected-error@+2 {{cannot return from OpenMP region}} + #pragma omp dispatch + return disp_call(); +} + +void testit_three(int (*fptr)(void), Obj *obj, int (Obj::*mptr)(void)) { + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + fptr(); + + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + (obj->*mptr)(); + + int ret; + + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + ret = fptr(); + + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + ret = (obj->*mptr)(); +} + +void testit_four(int *x, int y, Obj *obj) +{ + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + *x = y; + + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + y = disp_call() + disp_call(); + + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + y = (y = disp_call()); + + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + y += disp_call(); + + //expected-error@+2 {{statement after '#pragma omp dispatch' must be a direct call to a target function or an assignment to one}} + #pragma omp dispatch + for (int I = 0; I < 8; ++I) { + disp_call(); + } +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 841b36a6036c9..88b31e78feec8 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -5668,6 +5668,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPTargetTeamsDistributeSimdDirective"); case CXCursor_OMPInteropDirective: return cxstring::createRef("OMPInteropDirective"); + case CXCursor_OMPDispatchDirective: + return cxstring::createRef("OMPDispatchDirective"); case CXCursor_OverloadCandidate: return cxstring::createRef("OverloadCandidate"); case CXCursor_TypeAliasTemplateDecl: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 2f8d1e35936ec..d715d761f6911 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -810,6 +810,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPInteropDirectiveClass: K = CXCursor_OMPInteropDirective; break; + case Stmt::OMPDispatchDirectiveClass: + K = CXCursor_OMPDispatchDirective; + break; case Stmt::BuiltinBitCastExprClass: K = CXCursor_BuiltinBitCastExpr; } diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 7845e4bc98dbf..6e494da564384 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -1655,6 +1655,14 @@ def OMP_interop : Directive<"interop"> { VersionedClause<OMPC_Use>, ]; } +def OMP_dispatch : Directive<"dispatch"> { + let allowedClauses = [ + VersionedClause<OMPC_Device>, + VersionedClause<OMPC_IsDevicePtr>, + VersionedClause<OMPC_NoWait>, + VersionedClause<OMPC_Depend> + ]; +} def OMP_Unknown : Directive<"unknown"> { let isDefault = true; } diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 9a77dd7f098d6..31221b2f26c99 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -1078,6 +1078,7 @@ __OMP_TRAIT_PROPERTY(user, condition, true) __OMP_TRAIT_PROPERTY(user, condition, false) __OMP_TRAIT_PROPERTY(user, condition, unknown) +__OMP_TRAIT_SELECTOR_AND_PROPERTY(construct, dispatch) // Note that we put isa last so that the other conditions are checked first. // This allows us to issue warnings wrt. isa only if we match otherwise. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits