From 317ed94e29a0b5d6bea7e3d5f314937270c9ff84 Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Thu, 19 Dec 2024 19:51:49 +0530 Subject: [PATCH 01/10] Adds Parser and Semantic Support for the below construct and clauses: - Interop Construct - Init Clause - Use Clause Note: The other clauses supported by Interop Construct such as Destroy, Use, Depend and Device are added already. --- flang/examples/FeatureList/FeatureList.cpp | 9 + flang/include/flang/Parser/dump-parse-tree.h | 9 + flang/include/flang/Parser/parse-tree.h | 41 +++- flang/lib/Lower/OpenMP/OpenMP.cpp | 7 + flang/lib/Parser/openmp-parsers.cpp | 28 ++- flang/lib/Parser/unparse.cpp | 19 ++ flang/lib/Semantics/check-omp-structure.cpp | 85 ++++++++ flang/lib/Semantics/check-omp-structure.h | 2 + .../test/Parser/OpenMP/interop-construct.f90 | 204 ++++++++++++++++++ .../Semantics/OpenMP/interop-construct.f90 | 30 +++ llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 + 11 files changed, 434 insertions(+), 2 deletions(-) create mode 100644 flang/test/Parser/OpenMP/interop-construct.f90 create mode 100644 flang/test/Semantics/OpenMP/interop-construct.f90 diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index a1a908820e39c..7b29e5be9dcd2 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -522,6 +522,14 @@ struct NodeVisitor { READ_FEATURE(OmpScheduleClause) READ_FEATURE(OmpScheduleClause::Kind) READ_FEATURE(OmpScheduleClause::Modifier) + READ_FEATURE(InteropType) + READ_FEATURE(InteropType::Kind) + READ_FEATURE(InteropPreference) + READ_FEATURE(OmpInitClause) + READ_FEATURE(OmpInitClause::InteropModifier) + READ_FEATURE(OmpInitClause::InteropTypes) + READ_FEATURE(OmpInitClause::InteropVar) + READ_FEATURE(OmpUseClause) READ_FEATURE(OmpDeviceModifier) READ_FEATURE(OmpDeviceClause) READ_FEATURE(OmpDeviceClause::Modifier) @@ -542,6 +550,7 @@ struct NodeVisitor { READ_FEATURE(OpenACCConstruct) READ_FEATURE(OpenACCDeclarativeConstruct) READ_FEATURE(OpenACCLoopConstruct) + READ_FEATURE(OpenMPInteropConstruct) READ_FEATURE(OpenACCRoutineConstruct) READ_FEATURE(OpenACCStandaloneDeclarativeConstruct) READ_FEATURE(OpenACCStandaloneConstruct) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 25fcc843f3732..2e24e19930616 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -656,6 +656,14 @@ class ParseTreeDumper { NODE_ENUM(OmpDeviceModifier, Value) NODE(parser, OmpDeviceTypeClause) NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription) + NODE(parser, InteropType) + NODE_ENUM(InteropType, Kind) + NODE(parser, InteropPreference) + NODE(parser, OmpInitClause) + NODE(OmpInitClause, InteropModifier) + NODE(OmpInitClause, InteropTypes) + NODE(OmpInitClause, InteropVar) + NODE(parser, OmpUseClause) NODE(parser, OmpUpdateClause) NODE(parser, OmpChunkModifier) NODE_ENUM(OmpChunkModifier, Value) @@ -675,6 +683,7 @@ class ParseTreeDumper { NODE(parser, OpenACCDeclarativeConstruct) NODE(parser, OpenACCEndConstruct) NODE(parser, OpenACCLoopConstruct) + NODE(parser, OpenMPInteropConstruct) NODE(parser, OpenACCRoutineConstruct) NODE(parser, OpenACCStandaloneDeclarativeConstruct) NODE(parser, OpenACCStandaloneConstruct) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 1b1d4125464e3..37c53a63a4e68 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4481,6 +4481,36 @@ struct OmpWhenClause { t; }; +// REF: [5.1:217-220], [5.2:293-294] +// +// init-clause -> INIT ([interop-modifier,] [interop-type,] +// interop-type: interop-var) +// interop-modifier: prefer_type(preference-list) +// interop-type: target, targetsync +// There can be at most only two interop-type. +struct InteropType { + ENUM_CLASS(Kind, Target, TargetSync) + WRAPPER_CLASS_BOILERPLATE(InteropType, Kind); +}; + +struct InteropPreference { + UNION_CLASS_BOILERPLATE(InteropPreference); + std::variant u; +}; + +struct OmpInitClause { + TUPLE_CLASS_BOILERPLATE(OmpInitClause); + WRAPPER_CLASS(InteropModifier, std::list); + WRAPPER_CLASS(InteropTypes, std::list); + WRAPPER_CLASS(InteropVar, OmpObject); + std::tuple, InteropTypes, InteropVar> t; +}; + +// REF: [5.1:217-220], [5.2:294] +// +// 14.1.3 use-clause -> USE (interop-var) +WRAPPER_CLASS(OmpUseClause, OmpObject); + // OpenMP Clauses struct OmpClause { UNION_CLASS_BOILERPLATE(OmpClause); @@ -4939,6 +4969,15 @@ struct OmpSimpleStandaloneDirective { CharBlock source; }; +// Ref: [5.1:217-220], [5.2:291-292] +// +// interop -> INTEROP clause[ [ [,] clause]...] +struct OpenMPInteropConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPInteropConstruct); + CharBlock source; + std::tuple t; +}; + struct OpenMPSimpleStandaloneConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct); CharBlock source; @@ -4950,7 +4989,7 @@ struct OpenMPStandaloneConstruct { CharBlock source; std::variant + OpenMPDepobjConstruct, OmpMetadirectiveDirective, OpenMPInteropConstruct> u; }; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 2cfc1bd88dcef..ce34f27d4e8fc 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -3364,6 +3364,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct"); } +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPInteropConstruct &interopConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPInteropConstruct"); +} + static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 8c5c7063553ed..5a45acb4c3f50 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -757,6 +757,22 @@ TYPE_PARSER( // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) TYPE_PARSER(construct(Parser{})) +// InteropTypes +TYPE_PARSER(construct( + "TARGETSYNC" >> pure(InteropType::Kind::TargetSync) || + "TARGET" >> pure(InteropType::Kind::Target))) + +// InteropPreference +TYPE_PARSER(construct( + construct(charLiteralConstant) || + construct(scalarIntConstantExpr))) + +// init clause +TYPE_PARSER(construct( + maybe(verbatim("PREFER_TYPE"_tok) >> + parenthesized(nonemptyList(Parser{})) / ","), + nonemptyList(Parser{}) / ":", Parser{})) + // 2.8.1 ALIGNED (list: alignment) TYPE_PARSER(construct(Parser{}, maybe(":" >> nonemptyList(Parser{})))) @@ -896,6 +912,8 @@ TYPE_PARSER( // "IF" >> construct(construct( parenthesized(Parser{}))) || "INBRANCH" >> construct(construct()) || + "INIT" >> construct(construct( + parenthesized(Parser{}))) || "INCLUSIVE" >> construct(construct( parenthesized(Parser{}))) || "INITIALIZER" >> construct(construct( @@ -985,6 +1003,8 @@ TYPE_PARSER( // parenthesized(scalarIntExpr))) || "TO" >> construct(construct( parenthesized(Parser{}))) || + "USE" >> construct(construct( + parenthesized(Parser{}))) || "USE_DEVICE_PTR" >> construct(construct( parenthesized(Parser{}))) || "USE_DEVICE_ADDR" >> @@ -1212,6 +1232,10 @@ TYPE_PARSER(sourced(construct(first( TYPE_PARSER(sourced(construct( Parser{}, Parser{}))) +// 14.1 Interop construct +TYPE_PARSER(sourced(construct( + verbatim("INTEROP"_tok), sourced(Parser{})))) + // Standalone Constructs TYPE_PARSER( sourced(construct( @@ -1223,7 +1247,9 @@ TYPE_PARSER( construct(Parser{}) || construct( Parser{}) || - construct(Parser{})) / + construct(Parser{}) || + construct( + Parser{})) / endOfLine) // Directives enclosing structured-block diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index c5de5d1d08dd5..72014ab65bbf6 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2179,6 +2179,15 @@ class UnparseVisitor { Walk(std::get>>(x.t), ": "); Walk(std::get(x.t)); } + void Unparse(const OmpInitClause::InteropTypes &x) { Walk(x.v, ","); } + void Unparse(const OmpInitClause::InteropModifier &x) { Walk(x.v, ","); } + void Unparse(const OmpInitClause &x) { + Walk("PREFER_TYPE(", + std::get>(x.t), "),"); + Walk(std::get(x.t)); + Put(": "); + Walk(std::get(x.t)); + } void Unparse(const OmpMapClause &x) { using Modifier = OmpMapClause::Modifier; Walk(std::get>>(x.t), ": "); @@ -2740,6 +2749,15 @@ class UnparseVisitor { Put("\n"); EndOpenMP(); } + + void Unparse(const OpenMPInteropConstruct &x) { + BeginOpenMP(); + Word("!$OMP INTEROP"); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPDeclarativeAssumes &x) { BeginOpenMP(); Word("!$OMP ASSUMES "); @@ -3037,6 +3055,7 @@ class UnparseVisitor { OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation + WALK_NESTED_ENUM(InteropType, Kind) // OMP InteropVar WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 5fcebdca0bc5f..a0ff4c29b6d71 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5638,6 +5638,91 @@ void OmpStructureChecker::Leave(const parser::DoConstruct &x) { Base::Leave(x); } +void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { + bool isDependClauseOccured{false}; + int targetCount{0}, targetSyncCount{0}; + const auto &dir{std::get(x.t)}; + std::list ObjectNameList; + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_interop); + const auto &clauseList{std::get(x.t)}; + for (const auto &clause : clauseList.v) { + common::visit( + common::visitors{ + [&](const parser::OmpClause::Init &InitClause) { + const auto &InteropTypeList{ + std::get( + InitClause.v.t)}; + for (auto &InteropTypeVal : InteropTypeList.v) { + if (*(parser::Unwrap( + InteropTypeVal)) == + parser::InteropType::Kind::TargetSync) { + ++targetSyncCount; + } else { + ++targetCount; + } + if (targetCount > 1 || targetSyncCount > 1) { + context_.Say(GetContext().directiveSource, + "Each interop-type may be specified at most once."_err_en_US); + } + } + const auto &InteropVar{parser::Unwrap( + std::get(InitClause.v.t))}; + const auto *name{parser::Unwrap(InteropVar)}; + const auto ObjectName{name->ToString()}; + if (ObjectNameList.end() != + std::find(ObjectNameList.begin(), ObjectNameList.end(), + ObjectName)) { + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); + } else { + ObjectNameList.push_back(ObjectName); + } + }, + [&](const parser::OmpClause::Depend &DependClause) { + isDependClauseOccured = true; + }, + [&](const parser::OmpClause::Destroy &DestroyClause) { + const auto &InteropVar{ + parser::Unwrap(DestroyClause.v)}; + const auto *name{parser::Unwrap(InteropVar)}; + const auto ObjectName{name->ToString()}; + if (ObjectNameList.end() != + std::find(ObjectNameList.begin(), ObjectNameList.end(), + ObjectName)) { + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); + } else { + ObjectNameList.push_back(ObjectName); + } + }, + [&](const parser::OmpClause::Use &UseClause) { + const auto &InteropVar{ + parser::Unwrap(UseClause.v)}; + const auto *name{parser::Unwrap(InteropVar)}; + const auto ObjectName{name->ToString()}; + if (ObjectNameList.end() != + std::find(ObjectNameList.begin(), ObjectNameList.end(), + ObjectName)) { + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); + } else { + ObjectNameList.push_back(ObjectName); + } + }, + [&](const auto &) {}, + }, + clause.u); + } + if (isDependClauseOccured && !targetSyncCount) { + context_.Say(GetContext().directiveSource, + "A depend clause can only appear on the directive if the interop-type includes targetsync"_err_en_US); + } +} + +void OmpStructureChecker::Leave(const parser::OpenMPInteropConstruct &) { + dirContext_.pop_back(); +} + void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) { CheckAllowedClause(clause); diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 4c4e65cd7a2db..4f7308a0dbf8d 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -73,6 +73,8 @@ class OmpStructureChecker void Enter(const parser::OpenMPConstruct &); void Leave(const parser::OpenMPConstruct &); + void Enter(const parser::OpenMPInteropConstruct &); + void Leave(const parser::OpenMPInteropConstruct &); void Enter(const parser::OpenMPDeclarativeConstruct &); void Leave(const parser::OpenMPDeclarativeConstruct &); diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90 new file mode 100644 index 0000000000000..9fd2b3d63d5c5 --- /dev/null +++ b/flang/test/Parser/OpenMP/interop-construct.f90 @@ -0,0 +1,204 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine test_interop_01() + !$omp interop device(1) + print *,'pass' +end subroutine test_interop_01 + +!UNPARSE: SUBROUTINE test_interop_01 +!UNPARSE: !$OMP INTEROP DEVICE(1_4) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_01 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_01' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Device -> OmpDeviceClause +!PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_01' + +subroutine test_interop_02() + use omp_lib + integer(omp_interop_kind) :: obj1, obj2, obj3 + !$omp interop init(targetsync: obj) use(obj1) destroy(obj3) + print *,'pass' +end subroutine test_interop_02 + +!UNPARSE: SUBROUTINE test_interop_02 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj1, obj2, obj3 +!UNPARSE: !$OMP INTEROP INIT(TARGETSYNC: obj) USE(obj1) DESTROY(obj3) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_02 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_02' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj1' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj2' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj3' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync +!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Use -> OmpUseClause -> OmpObject -> Designator -> DataRef -> Name = 'obj1' +!PARSE-TREE: | | | OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'obj3' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_02' + +subroutine test_interop_03() + use omp_lib + Integer(omp_interop_kind) :: obj + !$omp interop init(targetsync: obj) depend(inout: obj) + print *,'pass' +end subroutine test_interop_03 + +!UNPARSE: SUBROUTINE test_interop_03 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj +!UNPARSE: !$OMP INTEROP INIT(TARGETSYNC: obj) DEPEND(INOUT: obj) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_03 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_03' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync +!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Depend -> OmpDependClause -> TaskDep +!PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout +!PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_03' + +subroutine test_interop_04() + use omp_lib + integer(omp_interop_kind) :: obj + integer, dimension(1,10) :: arr + !$omp interop init(prefer_type("cuda"),targetsync,target: obj) depend(inout: arr) nowait + print *,'pass' +end subroutine test_interop_04 + +!UNPARSE: SUBROUTINE test_interop_04 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj +!UNPARSE: INTEGER, DIMENSION(1_4,10_4) :: arr +!UNPARSE: !$OMP INTEROP INIT(PREFER_TYPE("cuda"),TARGETSYNC,TARGET: obj) DEPEND(INOUT: a& +!UNPARSE: !$OMP&rr) NOWAIT +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_04 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_04' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj' +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | AttrSpec -> ArraySpec -> ExplicitShapeSpec +!PARSE-TREE: | | | | SpecificationExpr -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | ExplicitShapeSpec +!PARSE-TREE: | | | | SpecificationExpr -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'arr' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | InteropModifier -> InteropPreference -> CharLiteralConstant +!PARSE-TREE: | | | | | string = 'cuda' +!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync +!PARSE-TREE: | | | | InteropType -> Kind = Target +!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Depend -> OmpDependClause -> TaskDep +!PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout +!PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'arr' +!PARSE-TREE: | | | OmpClause -> Nowait +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_04' + + +subroutine test_interop_05() + use omp_lib + integer(omp_interop_kind) :: obj + !$omp interop init(prefer_type(omp_ifr_sycl), targetsync: obj) device(device_num:0) + print *,'pass' +end subroutine test_interop_05 + +!UNPARSE: SUBROUTINE test_interop_05 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj +!UNPARSE: !$OMP INTEROP INIT(PREFER_TYPE(4_4),TARGETSYNC: obj) DEVICE(DEVICE_NUM: 0_4) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_05 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_05' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | InteropModifier -> InteropPreference -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_ifr_sycl' +!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync +!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Device -> OmpDeviceClause +!PARSE-TREE: | | | | Modifier -> OmpDeviceModifier -> Value = Device_Num +!PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '0' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_05' + diff --git a/flang/test/Semantics/OpenMP/interop-construct.f90 b/flang/test/Semantics/OpenMP/interop-construct.f90 new file mode 100644 index 0000000000000..727455b1a369b --- /dev/null +++ b/flang/test/Semantics/OpenMP/interop-construct.f90 @@ -0,0 +1,30 @@ +! REQUIRES: openmp_runtime + +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 +! OpenMP Version 5.2 +! 14.1 Interop construct +! To check various semantic errors for inteorp construct. + +subroutine test_interop_01() + use omp_lib + integer(omp_interop_kind) :: obj + !ERROR: Each interop-var may be specified for at most one action-clause of each interop construct. + !$omp interop init(targetsync,target: obj) use(obj) + print *, 'pass' +end subroutine test_interop_01 + +subroutine test_interop_02() + use omp_lib + integer(omp_interop_kind) :: obj + !ERROR: Each interop-type may be specified at most once. + !$omp interop init(targetsync,target,targetsync: obj) + print *, 'pass' +end subroutine test_interop_02 + +subroutine test_interop_03() + use omp_lib + integer(omp_interop_kind) :: obj + !ERROR: A depend clause can only appear on the directive if the interop-type includes targetsync + !$omp interop init(target: obj) depend(inout: obj) + print *, 'pass' +end subroutine test_interop_03 \ No newline at end of file diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 75347061d9a92..e2a1449d8cc76 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -244,6 +244,7 @@ def OMPC_Indirect : Clause<"indirect"> { } def OMPC_Init : Clause<"init"> { let clangClass = "OMPInitClause"; + let flangClass = "OmpInitClause"; } def OMPC_Initializer : Clause<"initializer"> { let flangClass = "OmpInitializerClause"; @@ -526,6 +527,7 @@ def OMPC_Update : Clause<"update"> { } def OMPC_Use : Clause<"use"> { let clangClass = "OMPUseClause"; + let flangClass = "OmpUseClause"; } def OMPC_UsesAllocators : Clause<"uses_allocators"> { let clangClass = "OMPUsesAllocatorsClause"; From a361683d48721a3027437283e02347ddb8be9420 Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Mon, 6 Jan 2025 18:48:49 +0530 Subject: [PATCH 02/10] Modified the declaration and definition of modifiers and addressed review comments. --- flang/examples/FeatureList/FeatureList.cpp | 11 +++-- flang/include/flang/Parser/dump-parse-tree.h | 11 +++-- flang/include/flang/Parser/parse-tree.h | 44 +++++++++++++------ .../flang/Semantics/openmp-modifiers.h | 2 + flang/lib/Parser/openmp-parsers.cpp | 31 +++++++------ flang/lib/Parser/unparse.cpp | 29 +++++++++--- flang/lib/Semantics/check-omp-structure.cpp | 37 +++++++++------- flang/lib/Semantics/openmp-modifiers.cpp | 32 ++++++++++++++ .../test/Parser/OpenMP/interop-construct.f90 | 29 ++++++------ 9 files changed, 150 insertions(+), 76 deletions(-) diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index 7b29e5be9dcd2..2b71d11ed59d2 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -522,13 +522,12 @@ struct NodeVisitor { READ_FEATURE(OmpScheduleClause) READ_FEATURE(OmpScheduleClause::Kind) READ_FEATURE(OmpScheduleClause::Modifier) - READ_FEATURE(InteropType) - READ_FEATURE(InteropType::Kind) - READ_FEATURE(InteropPreference) + READ_FEATURE(OmpInteropType) + READ_FEATURE(OmpInteropType::Value) + READ_FEATURE(OmpInteropRuntimeIdentifier) + READ_FEATURE(OmpInteropPreference) READ_FEATURE(OmpInitClause) - READ_FEATURE(OmpInitClause::InteropModifier) - READ_FEATURE(OmpInitClause::InteropTypes) - READ_FEATURE(OmpInitClause::InteropVar) + READ_FEATURE(OmpInitClause::Modifier) READ_FEATURE(OmpUseClause) READ_FEATURE(OmpDeviceModifier) READ_FEATURE(OmpDeviceClause) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 2e24e19930616..6fd1214ebb71d 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -656,13 +656,12 @@ class ParseTreeDumper { NODE_ENUM(OmpDeviceModifier, Value) NODE(parser, OmpDeviceTypeClause) NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription) - NODE(parser, InteropType) - NODE_ENUM(InteropType, Kind) - NODE(parser, InteropPreference) + NODE(parser, OmpInteropType) + NODE_ENUM(OmpInteropType, Value) + NODE(parser, OmpInteropRuntimeIdentifier) + NODE(parser, OmpInteropPreference) NODE(parser, OmpInitClause) - NODE(OmpInitClause, InteropModifier) - NODE(OmpInitClause, InteropTypes) - NODE(OmpInitClause, InteropVar) + NODE(OmpInitClause, Modifier) NODE(parser, OmpUseClause) NODE(parser, OmpUpdateClause) NODE(parser, OmpChunkModifier) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 37c53a63a4e68..1c1b4df6b86af 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3824,6 +3824,33 @@ struct OmpExpectation { WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value); }; +// REF: [5.1:217-220], [5.2:293-294] +// +// InteropType -> target || targetsync // since 5.2 +// There can be at most only two interop-type. +struct OmpInteropType { + ENUM_CLASS(Value, Target, TargetSync) + WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value); +}; + +// REF: [5.1:217-220], [5.2:293-294] +// +// OmpRuntimeIdentifier -> // since 5.2 +// CharLiteralConstant || ScalarIntConstantExpr +struct OmpInteropRuntimeIdentifier { + UNION_CLASS_BOILERPLATE(OmpInteropRuntimeIdentifier); + std::variant u; +}; + +// REF: [5.1:217-220], [5.2:293-294] +// +// OmpInteropPreference -> // since 5.2 +// ([OmpRuntimeIdentifier, ...]) +struct OmpInteropPreference { + WRAPPER_CLASS_BOILERPLATE( + OmpInteropPreference, std::list); +}; + // Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69] // // iterator-modifier -> @@ -4487,23 +4514,12 @@ struct OmpWhenClause { // interop-type: interop-var) // interop-modifier: prefer_type(preference-list) // interop-type: target, targetsync +// interop-var: Ompobject // There can be at most only two interop-type. -struct InteropType { - ENUM_CLASS(Kind, Target, TargetSync) - WRAPPER_CLASS_BOILERPLATE(InteropType, Kind); -}; - -struct InteropPreference { - UNION_CLASS_BOILERPLATE(InteropPreference); - std::variant u; -}; - struct OmpInitClause { TUPLE_CLASS_BOILERPLATE(OmpInitClause); - WRAPPER_CLASS(InteropModifier, std::list); - WRAPPER_CLASS(InteropTypes, std::list); - WRAPPER_CLASS(InteropVar, OmpObject); - std::tuple, InteropTypes, InteropVar> t; + MODIFIER_BOILERPLATE(OmpInteropPreference, OmpInteropType); + std::tuple t; }; // REF: [5.1:217-220], [5.2:294] diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index 7cdbf65adebe1..4fbd80f989e72 100644 --- a/flang/include/flang/Semantics/openmp-modifiers.h +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -77,6 +77,8 @@ DECLARE_DESCRIPTOR(parser::OmpDependenceType); DECLARE_DESCRIPTOR(parser::OmpDeviceModifier); DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier); DECLARE_DESCRIPTOR(parser::OmpExpectation); +DECLARE_DESCRIPTOR(parser::OmpInteropPreference); +DECLARE_DESCRIPTOR(parser::OmpInteropType); DECLARE_DESCRIPTOR(parser::OmpIterator); DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier); DECLARE_DESCRIPTOR(parser::OmpLinearModifier); diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 5a45acb4c3f50..527005c32b424 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -394,6 +394,10 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( // "PRESENT" >> pure(OmpExpectation::Value::Present))) +TYPE_PARSER(construct( + "TARGETSYNC" >> pure(OmpInteropType::Value::TargetSync) || + "TARGET" >> pure(OmpInteropType::Value::Target))) + TYPE_PARSER(construct( // Using Parser or Parser has the problem // that they will attempt to treat what follows the '=' as initialization. @@ -466,6 +470,10 @@ TYPE_PARSER(construct( "TASK" >> pure(OmpReductionModifier::Value::Task) || "DEFAULT" >> pure(OmpReductionModifier::Value::Default))) +TYPE_PARSER(construct( + construct(charLiteralConstant) || + construct(scalarIntConstantExpr))) + TYPE_PARSER(construct( // "STEP" >> parenthesized(scalarIntExpr))) @@ -521,6 +529,14 @@ TYPE_PARSER(sourced( TYPE_PARSER(sourced(construct(OmpDirectiveNameParser{}))) +TYPE_PARSER(construct(verbatim("PREFER_TYPE"_tok) >> + parenthesized(nonemptyList(Parser{})))) + +TYPE_PARSER(sourced( + construct( + construct(Parser{})) || + construct(Parser{}))) + TYPE_PARSER(sourced(construct( Parser{}))) @@ -757,21 +773,10 @@ TYPE_PARSER( // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) TYPE_PARSER(construct(Parser{})) -// InteropTypes -TYPE_PARSER(construct( - "TARGETSYNC" >> pure(InteropType::Kind::TargetSync) || - "TARGET" >> pure(InteropType::Kind::Target))) - -// InteropPreference -TYPE_PARSER(construct( - construct(charLiteralConstant) || - construct(scalarIntConstantExpr))) - // init clause TYPE_PARSER(construct( - maybe(verbatim("PREFER_TYPE"_tok) >> - parenthesized(nonemptyList(Parser{})) / ","), - nonemptyList(Parser{}) / ":", Parser{})) + maybe(nonemptyList(Parser{}) / ":"), + Parser{})) // 2.8.1 ALIGNED (list: alignment) TYPE_PARSER(construct(Parser{}, diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 72014ab65bbf6..3f2df7b1a3152 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2179,14 +2179,29 @@ class UnparseVisitor { Walk(std::get>>(x.t), ": "); Walk(std::get(x.t)); } - void Unparse(const OmpInitClause::InteropTypes &x) { Walk(x.v, ","); } - void Unparse(const OmpInitClause::InteropModifier &x) { Walk(x.v, ","); } + void Unparse(const OmpInteropPreference &x) { Walk(x.v, ","); } void Unparse(const OmpInitClause &x) { - Walk("PREFER_TYPE(", - std::get>(x.t), "),"); - Walk(std::get(x.t)); + using Modifier = OmpInitClause::Modifier; + auto &modifiers{std::get>>(x.t)}; + bool is_type_start = true; + for (const Modifier &m : *modifiers) { + if (auto *interop_preference_mod{ + std::get_if(&m.u)}) { + Put("PREFER_TYPE("); + Walk(*interop_preference_mod); + Put("),"); + } else if (auto *interop_type_mod{ + std::get_if(&m.u)}) { + if (is_type_start) { + is_type_start = false; + } else { + Put(","); + } + Walk(*interop_type_mod); + } + } Put(": "); - Walk(std::get(x.t)); + Walk(std::get(x.t)); } void Unparse(const OmpMapClause &x) { using Modifier = OmpMapClause::Modifier; @@ -3055,7 +3070,7 @@ class UnparseVisitor { OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation - WALK_NESTED_ENUM(InteropType, Kind) // OMP InteropVar + WALK_NESTED_ENUM(OmpInteropType, Value) // OMP InteropType WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index a0ff4c29b6d71..85492d7948bea 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5649,24 +5649,31 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { common::visit( common::visitors{ [&](const parser::OmpClause::Init &InitClause) { - const auto &InteropTypeList{ - std::get( - InitClause.v.t)}; - for (auto &InteropTypeVal : InteropTypeList.v) { - if (*(parser::Unwrap( - InteropTypeVal)) == - parser::InteropType::Kind::TargetSync) { - ++targetSyncCount; - } else { - ++targetCount; - } - if (targetCount > 1 || targetSyncCount > 1) { - context_.Say(GetContext().directiveSource, - "Each interop-type may be specified at most once."_err_en_US); + if (OmpVerifyModifiers(InitClause.v, llvm::omp::OMPC_init, + GetContext().directiveSource, context_)) { + + auto &modifiers{OmpGetModifiers(InitClause.v)}; + auto &&interopTypeModifier{ + OmpGetRepeatableModifier( + modifiers)}; + for (auto it{interopTypeModifier.begin()}, + end{interopTypeModifier.end()}; + it != end; ++it) { + if (parser::ToUpperCaseLetters( + parser::OmpInteropType::EnumToString((*it)->v)) == + "TARGETSYNC") { + ++targetSyncCount; + } else { + ++targetCount; + } + if (targetCount > 1 || targetSyncCount > 1) { + context_.Say(GetContext().directiveSource, + "Each interop-type may be specified at most once."_err_en_US); + } } } const auto &InteropVar{parser::Unwrap( - std::get(InitClause.v.t))}; + std::get(InitClause.v.t))}; const auto *name{parser::Unwrap(InteropVar)}; const auto ObjectName{name->ToString()}; if (ObjectNameList.end() != diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index 73ad7751ee517..c84e832ee52a1 100644 --- a/flang/lib/Semantics/openmp-modifiers.cpp +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -240,6 +240,38 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"interop-preference", + /*props=*/ + { + {52, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {52, {Clause::OMPC_init}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"interop-type", + /*props=*/ + { + {52, {OmpProperty::Required}}, + }, + /*clauses=*/ + { + {52, {Clause::OMPC_init}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90 index 9fd2b3d63d5c5..37078f68e3e7c 100644 --- a/flang/test/Parser/OpenMP/interop-construct.f90 +++ b/flang/test/Parser/OpenMP/interop-construct.f90 @@ -1,5 +1,5 @@ -! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s -! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s +! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version=52 -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp-version=52 -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s subroutine test_interop_01() !$omp interop device(1) @@ -7,7 +7,7 @@ subroutine test_interop_01() end subroutine test_interop_01 !UNPARSE: SUBROUTINE test_interop_01 -!UNPARSE: !$OMP INTEROP DEVICE(1_4) +!UNPARSE: !$OMP INTEROP DEVICE(1_4) !UNPARSE: PRINT *, "pass" !UNPARSE: END SUBROUTINE test_interop_01 @@ -58,8 +58,8 @@ end subroutine test_interop_02 !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct !PARSE-TREE: | | | Verbatim !PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause -!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync -!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' !PARSE-TREE: | | | OmpClause -> Use -> OmpUseClause -> OmpObject -> Designator -> DataRef -> Name = 'obj1' !PARSE-TREE: | | | OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'obj3' !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt @@ -96,8 +96,8 @@ end subroutine test_interop_03 !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct !PARSE-TREE: | | | Verbatim !PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause -!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync -!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' !PARSE-TREE: | | | OmpClause -> Depend -> OmpDependClause -> TaskDep !PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout !PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'obj' @@ -146,11 +146,11 @@ end subroutine test_interop_04 !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct !PARSE-TREE: | | | Verbatim !PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause -!PARSE-TREE: | | | | InteropModifier -> InteropPreference -> CharLiteralConstant +!PARSE-TREE: | | | | Modifier -> OmpInteropPreference -> OmpInteropRuntimeIdentifier -> CharLiteralConstant !PARSE-TREE: | | | | | string = 'cuda' -!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync -!PARSE-TREE: | | | | InteropType -> Kind = Target -!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = Target +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' !PARSE-TREE: | | | OmpClause -> Depend -> OmpDependClause -> TaskDep !PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout !PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'arr' @@ -161,7 +161,6 @@ end subroutine test_interop_04 !PARSE-TREE: | | | | string = 'pass' !PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_04' - subroutine test_interop_05() use omp_lib integer(omp_interop_kind) :: obj @@ -190,9 +189,9 @@ end subroutine test_interop_05 !PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct !PARSE-TREE: | | | Verbatim !PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause -!PARSE-TREE: | | | | InteropModifier -> InteropPreference -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_ifr_sycl' -!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync -!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | | Modifier -> OmpInteropPreference -> OmpInteropRuntimeIdentifier -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_ifr_sycl' +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' !PARSE-TREE: | | | OmpClause -> Device -> OmpDeviceClause !PARSE-TREE: | | | | Modifier -> OmpDeviceModifier -> Value = Device_Num !PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '0' From fd72b6523e46e9f149dcbbf414080e4d2f240973 Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Tue, 7 Jan 2025 10:50:27 +0530 Subject: [PATCH 03/10] Preserved the alphabetical ordering of modifier declarations and definitions. --- flang/examples/FeatureList/FeatureList.cpp | 4 ++-- flang/include/flang/Parser/dump-parse-tree.h | 4 ++-- flang/include/flang/Parser/parse-tree.h | 18 +++++++++--------- flang/lib/Parser/openmp-parsers.cpp | 14 +++++++------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index 2b71d11ed59d2..e34f103a1df04 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -522,10 +522,10 @@ struct NodeVisitor { READ_FEATURE(OmpScheduleClause) READ_FEATURE(OmpScheduleClause::Kind) READ_FEATURE(OmpScheduleClause::Modifier) - READ_FEATURE(OmpInteropType) - READ_FEATURE(OmpInteropType::Value) READ_FEATURE(OmpInteropRuntimeIdentifier) READ_FEATURE(OmpInteropPreference) + READ_FEATURE(OmpInteropType) + READ_FEATURE(OmpInteropType::Value) READ_FEATURE(OmpInitClause) READ_FEATURE(OmpInitClause::Modifier) READ_FEATURE(OmpUseClause) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 6fd1214ebb71d..8f6fd868feaf0 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -656,10 +656,10 @@ class ParseTreeDumper { NODE_ENUM(OmpDeviceModifier, Value) NODE(parser, OmpDeviceTypeClause) NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription) - NODE(parser, OmpInteropType) - NODE_ENUM(OmpInteropType, Value) NODE(parser, OmpInteropRuntimeIdentifier) NODE(parser, OmpInteropPreference) + NODE(parser, OmpInteropType) + NODE_ENUM(OmpInteropType, Value) NODE(parser, OmpInitClause) NODE(OmpInitClause, Modifier) NODE(parser, OmpUseClause) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 1c1b4df6b86af..fe3bab873ee5a 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3824,15 +3824,6 @@ struct OmpExpectation { WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value); }; -// REF: [5.1:217-220], [5.2:293-294] -// -// InteropType -> target || targetsync // since 5.2 -// There can be at most only two interop-type. -struct OmpInteropType { - ENUM_CLASS(Value, Target, TargetSync) - WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value); -}; - // REF: [5.1:217-220], [5.2:293-294] // // OmpRuntimeIdentifier -> // since 5.2 @@ -3851,6 +3842,15 @@ struct OmpInteropPreference { OmpInteropPreference, std::list); }; +// REF: [5.1:217-220], [5.2:293-294] +// +// InteropType -> target || targetsync // since 5.2 +// There can be at most only two interop-type. +struct OmpInteropType { + ENUM_CLASS(Value, Target, TargetSync) + WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value); +}; + // Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69] // // iterator-modifier -> diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 527005c32b424..70fecb90deeda 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -394,6 +394,13 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( // "PRESENT" >> pure(OmpExpectation::Value::Present))) +TYPE_PARSER(construct( + construct(charLiteralConstant) || + construct(scalarIntConstantExpr))) + +TYPE_PARSER(construct(verbatim("PREFER_TYPE"_tok) >> + parenthesized(nonemptyList(Parser{})))) + TYPE_PARSER(construct( "TARGETSYNC" >> pure(OmpInteropType::Value::TargetSync) || "TARGET" >> pure(OmpInteropType::Value::Target))) @@ -470,10 +477,6 @@ TYPE_PARSER(construct( "TASK" >> pure(OmpReductionModifier::Value::Task) || "DEFAULT" >> pure(OmpReductionModifier::Value::Default))) -TYPE_PARSER(construct( - construct(charLiteralConstant) || - construct(scalarIntConstantExpr))) - TYPE_PARSER(construct( // "STEP" >> parenthesized(scalarIntExpr))) @@ -529,9 +532,6 @@ TYPE_PARSER(sourced( TYPE_PARSER(sourced(construct(OmpDirectiveNameParser{}))) -TYPE_PARSER(construct(verbatim("PREFER_TYPE"_tok) >> - parenthesized(nonemptyList(Parser{})))) - TYPE_PARSER(sourced( construct( construct(Parser{})) || From 06961c2c3b5ab2dd12f32ab917fb810e60c3ab09 Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Thu, 13 Mar 2025 18:20:12 +0530 Subject: [PATCH 04/10] Updated the testfile, rebased and added a test on Todo Lower side for interop construct. --- flang/lib/Lower/OpenMP/OpenMP.cpp | 3 + .../Lower/OpenMP/Todo/inteorp-construct.f90 | 8 +++ .../test/Parser/OpenMP/interop-construct.f90 | 58 +++++++++---------- .../Semantics/OpenMP/interop-construct.f90 | 36 ++++++------ 4 files changed, 58 insertions(+), 47 deletions(-) create mode 100644 flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index ce34f27d4e8fc..9dbb5e7a5f7bf 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -425,6 +425,9 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) { }, [](const parser::OpenMPDepobjConstruct &c) { return llvm::omp::OMPD_depobj; + }, + [](const parser::OpenMPInteropConstruct &c) { + return llvm::omp::OMPD_interop; }}, c.u); }, diff --git a/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 new file mode 100644 index 0000000000000..48c50f4a57f27 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 @@ -0,0 +1,8 @@ +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s + +! CHECK: not yet implemented: OpenMPInteropConstruct +program interop_test + use omp_lib + integer(omp_interop_kind) :: obj + !$omp interop init(targetsync,target: obj) +end program interop_test diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90 index 37078f68e3e7c..63718d80f87fe 100644 --- a/flang/test/Parser/OpenMP/interop-construct.f90 +++ b/flang/test/Parser/OpenMP/interop-construct.f90 @@ -1,10 +1,10 @@ ! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version=52 -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s ! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp-version=52 -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s -subroutine test_interop_01() - !$omp interop device(1) - print *,'pass' -end subroutine test_interop_01 +SUBROUTINE test_interop_01() + !$OMP INTEROP DEVICE(1) + PRINT *,'pass' +END SUBROUTINE test_interop_01 !UNPARSE: SUBROUTINE test_interop_01 !UNPARSE: !$OMP INTEROP DEVICE(1_4) @@ -26,12 +26,12 @@ end subroutine test_interop_01 !PARSE-TREE: | | | | string = 'pass' !PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_01' -subroutine test_interop_02() - use omp_lib - integer(omp_interop_kind) :: obj1, obj2, obj3 - !$omp interop init(targetsync: obj) use(obj1) destroy(obj3) - print *,'pass' -end subroutine test_interop_02 +SUBROUTINE test_interop_02() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj1, obj2, obj3 + !$OMP INTEROP INIT(TARGETSYNC: obj) USE(obj1) DESTROY(obj3) + PRINT *,'pass' +END SUBROUTINE test_interop_02 !UNPARSE: SUBROUTINE test_interop_02 !UNPARSE: USE :: omp_lib @@ -68,12 +68,12 @@ end subroutine test_interop_02 !PARSE-TREE: | | | | string = 'pass' !PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_02' -subroutine test_interop_03() - use omp_lib - Integer(omp_interop_kind) :: obj - !$omp interop init(targetsync: obj) depend(inout: obj) - print *,'pass' -end subroutine test_interop_03 +SUBROUTINE test_interop_03() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + !$OMP INTEROP INIT(TARGETSYNC: obj) DEPEND(INOUT: obj) + PRINT *,'pass' +END SUBROUTINE test_interop_03 !UNPARSE: SUBROUTINE test_interop_03 !UNPARSE: USE :: omp_lib @@ -107,13 +107,13 @@ end subroutine test_interop_03 !PARSE-TREE: | | | | string = 'pass' !PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_03' -subroutine test_interop_04() - use omp_lib - integer(omp_interop_kind) :: obj - integer, dimension(1,10) :: arr - !$omp interop init(prefer_type("cuda"),targetsync,target: obj) depend(inout: arr) nowait - print *,'pass' -end subroutine test_interop_04 +SUBROUTINE test_interop_04() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + INTEGER, DIMENSION(1,10) :: arr + !$OMP INTEROP INIT(PREFER_TYPE("cuda"),TARGETSYNC,TARGET: obj) DEPEND(INOUT: arr) NOWAIT + PRINT *,'pass' +END SUBROUTINE test_interop_04 !UNPARSE: SUBROUTINE test_interop_04 !UNPARSE: USE :: omp_lib @@ -161,12 +161,12 @@ end subroutine test_interop_04 !PARSE-TREE: | | | | string = 'pass' !PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_04' -subroutine test_interop_05() - use omp_lib - integer(omp_interop_kind) :: obj - !$omp interop init(prefer_type(omp_ifr_sycl), targetsync: obj) device(device_num:0) - print *,'pass' -end subroutine test_interop_05 +SUBROUTINE test_interop_05() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + !$OMP INTEROP INIT(PREFER_TYPE(omp_ifr_sycl), TARGETSYNC: obj) DEVICE(DEVICE_NUM:0) + PRINT *,'pass' +END SUBROUTINE test_interop_05 !UNPARSE: SUBROUTINE test_interop_05 !UNPARSE: USE :: omp_lib diff --git a/flang/test/Semantics/OpenMP/interop-construct.f90 b/flang/test/Semantics/OpenMP/interop-construct.f90 index 727455b1a369b..0dcc178d8023b 100644 --- a/flang/test/Semantics/OpenMP/interop-construct.f90 +++ b/flang/test/Semantics/OpenMP/interop-construct.f90 @@ -5,26 +5,26 @@ ! 14.1 Interop construct ! To check various semantic errors for inteorp construct. -subroutine test_interop_01() - use omp_lib - integer(omp_interop_kind) :: obj +SUBROUTINE test_interop_01() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj !ERROR: Each interop-var may be specified for at most one action-clause of each interop construct. - !$omp interop init(targetsync,target: obj) use(obj) - print *, 'pass' -end subroutine test_interop_01 + !$OMP INTEROP INIT(TARGETSYNC,TARGET: obj) USE(obj) + PRINT *, 'pass' +END SUBROUTINE test_interop_01 -subroutine test_interop_02() - use omp_lib - integer(omp_interop_kind) :: obj +SUBROUTINE test_interop_02() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj !ERROR: Each interop-type may be specified at most once. - !$omp interop init(targetsync,target,targetsync: obj) - print *, 'pass' -end subroutine test_interop_02 + !$OMP INTEROP INIT(TARGETSYNC,TARGET,TARGETSYNC: obj) + PRINT *, 'pass' +END SUBROUTINE test_interop_02 -subroutine test_interop_03() - use omp_lib - integer(omp_interop_kind) :: obj +SUBROUTINE test_interop_03() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj !ERROR: A depend clause can only appear on the directive if the interop-type includes targetsync - !$omp interop init(target: obj) depend(inout: obj) - print *, 'pass' -end subroutine test_interop_03 \ No newline at end of file + !$OMP INTEROP INIT(TARGET: obj) DEPEND(INOUT: obj) + PRINT *, 'pass' +END SUBROUTINE test_interop_03 From 830dff873dd22e7aa754d44fe1c1124492d6cc3f Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Fri, 14 Mar 2025 16:23:22 +0530 Subject: [PATCH 05/10] Addressed review comments and changed object name check with object symbol check. --- flang/lib/Parser/unparse.cpp | 14 ++-- flang/lib/Semantics/check-omp-structure.cpp | 86 ++++++++++----------- 2 files changed, 47 insertions(+), 53 deletions(-) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 3f2df7b1a3152..b440eadcdd0c8 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2183,21 +2183,21 @@ class UnparseVisitor { void Unparse(const OmpInitClause &x) { using Modifier = OmpInitClause::Modifier; auto &modifiers{std::get>>(x.t)}; - bool is_type_start = true; + bool isTypeStart = true; for (const Modifier &m : *modifiers) { - if (auto *interop_preference_mod{ + if (auto *interopPreferenceMod{ std::get_if(&m.u)}) { Put("PREFER_TYPE("); - Walk(*interop_preference_mod); + Walk(*interopPreferenceMod); Put("),"); - } else if (auto *interop_type_mod{ + } else if (auto *interopTypeMod{ std::get_if(&m.u)}) { - if (is_type_start) { - is_type_start = false; + if (isTypeStart) { + isTypeStart = false; } else { Put(","); } - Walk(*interop_type_mod); + Walk(*interopTypeMod); } } Put(": "); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 85492d7948bea..3faf07675dac0 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5642,86 +5642,80 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { bool isDependClauseOccured{false}; int targetCount{0}, targetSyncCount{0}; const auto &dir{std::get(x.t)}; - std::list ObjectNameList; + std::set objectSymbolList; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_interop); const auto &clauseList{std::get(x.t)}; for (const auto &clause : clauseList.v) { common::visit( common::visitors{ - [&](const parser::OmpClause::Init &InitClause) { - if (OmpVerifyModifiers(InitClause.v, llvm::omp::OMPC_init, - GetContext().directiveSource, context_)) { + [&](const parser::OmpClause::Init &initClause) { + if (OmpVerifyModifiers(initClause.v, llvm::omp::OMPC_init, + GetContext().directiveSource, context_)) { - auto &modifiers{OmpGetModifiers(InitClause.v)}; + auto &modifiers{OmpGetModifiers(initClause.v)}; auto &&interopTypeModifier{ OmpGetRepeatableModifier( modifiers)}; - for (auto it{interopTypeModifier.begin()}, - end{interopTypeModifier.end()}; - it != end; ++it) { - if (parser::ToUpperCaseLetters( - parser::OmpInteropType::EnumToString((*it)->v)) == - "TARGETSYNC") { + for (const auto &it : interopTypeModifier) { + if (it->v == parser::OmpInteropType::Value::TargetSync) { ++targetSyncCount; } else { ++targetCount; } - if (targetCount > 1 || targetSyncCount > 1) { - context_.Say(GetContext().directiveSource, - "Each interop-type may be specified at most once."_err_en_US); - } } } - const auto &InteropVar{parser::Unwrap( - std::get(InitClause.v.t))}; - const auto *name{parser::Unwrap(InteropVar)}; - const auto ObjectName{name->ToString()}; - if (ObjectNameList.end() != - std::find(ObjectNameList.begin(), ObjectNameList.end(), - ObjectName)) { - context_.Say(GetContext().directiveSource, + const auto &interopVar{parser::Unwrap( + std::get(initClause.v.t))}; + const auto *name{parser::Unwrap(interopVar)}; + const auto *objectSymbol{name->symbol}; + if (llvm::is_contained(objectSymbolList, objectSymbol)) { + context_.Say( + GetContext().directiveSource, "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); } else { - ObjectNameList.push_back(ObjectName); + objectSymbolList.insert(objectSymbol); } }, - [&](const parser::OmpClause::Depend &DependClause) { + [&](const parser::OmpClause::Depend &dependClause) { isDependClauseOccured = true; }, - [&](const parser::OmpClause::Destroy &DestroyClause) { - const auto &InteropVar{ - parser::Unwrap(DestroyClause.v)}; - const auto *name{parser::Unwrap(InteropVar)}; - const auto ObjectName{name->ToString()}; - if (ObjectNameList.end() != - std::find(ObjectNameList.begin(), ObjectNameList.end(), - ObjectName)) { - context_.Say(GetContext().directiveSource, + [&](const parser::OmpClause::Destroy &destroyClause) { + const auto &interopVar{ + parser::Unwrap(destroyClause.v)}; + const auto *name{parser::Unwrap(interopVar)}; + const auto *objectSymbol{name->symbol}; + if (llvm::is_contained(objectSymbolList, objectSymbol)) { + context_.Say( + GetContext().directiveSource, "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); } else { - ObjectNameList.push_back(ObjectName); + objectSymbolList.insert(objectSymbol); } }, - [&](const parser::OmpClause::Use &UseClause) { - const auto &InteropVar{ - parser::Unwrap(UseClause.v)}; - const auto *name{parser::Unwrap(InteropVar)}; - const auto ObjectName{name->ToString()}; - if (ObjectNameList.end() != - std::find(ObjectNameList.begin(), ObjectNameList.end(), - ObjectName)) { - context_.Say(GetContext().directiveSource, + [&](const parser::OmpClause::Use &useClause) { + const auto &interopVar{ + parser::Unwrap(useClause.v)}; + const auto *name{parser::Unwrap(interopVar)}; + const auto *objectSymbol{name->symbol}; + if (llvm::is_contained(objectSymbolList, objectSymbol)) { + context_.Say( + GetContext().directiveSource, "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); } else { - ObjectNameList.push_back(ObjectName); + objectSymbolList.insert(objectSymbol); } }, [&](const auto &) {}, }, clause.u); } - if (isDependClauseOccured && !targetSyncCount) { + if (targetCount > 1 || targetSyncCount > 1) { context_.Say(GetContext().directiveSource, + "Each interop-type may be specified at most once."_err_en_US); + } + if (isDependClauseOccured && !targetSyncCount) { + context_.Say( + GetContext().directiveSource, "A depend clause can only appear on the directive if the interop-type includes targetsync"_err_en_US); } } From e14498b5ef1b7f4be0e18159c4f6264d5c7662b4 Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Mon, 17 Mar 2025 11:17:43 +0530 Subject: [PATCH 06/10] Addressed NIT comments. --- flang/lib/Parser/openmp-parsers.cpp | 2 +- flang/lib/Parser/unparse.cpp | 2 +- flang/lib/Semantics/check-omp-structure.cpp | 8 ++++---- flang/test/Semantics/OpenMP/interop-construct.f90 | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 70fecb90deeda..1aa3527c754fc 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1237,7 +1237,7 @@ TYPE_PARSER(sourced(construct(first( TYPE_PARSER(sourced(construct( Parser{}, Parser{}))) -// 14.1 Interop construct +// OMP 5.2 14.1 Interop construct TYPE_PARSER(sourced(construct( verbatim("INTEROP"_tok), sourced(Parser{})))) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index b440eadcdd0c8..37a17d3b88085 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2183,7 +2183,7 @@ class UnparseVisitor { void Unparse(const OmpInitClause &x) { using Modifier = OmpInitClause::Modifier; auto &modifiers{std::get>>(x.t)}; - bool isTypeStart = true; + bool isTypeStart{true}; for (const Modifier &m : *modifiers) { if (auto *interopPreferenceMod{ std::get_if(&m.u)}) { diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 3faf07675dac0..13e07ebf01c44 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5671,7 +5671,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { if (llvm::is_contained(objectSymbolList, objectSymbol)) { context_.Say( GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5687,7 +5687,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { if (llvm::is_contained(objectSymbolList, objectSymbol)) { context_.Say( GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5700,7 +5700,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { if (llvm::is_contained(objectSymbolList, objectSymbol)) { context_.Say( GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US); + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5716,7 +5716,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { if (isDependClauseOccured && !targetSyncCount) { context_.Say( GetContext().directiveSource, - "A depend clause can only appear on the directive if the interop-type includes targetsync"_err_en_US); + "A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC"_err_en_US); } } diff --git a/flang/test/Semantics/OpenMP/interop-construct.f90 b/flang/test/Semantics/OpenMP/interop-construct.f90 index 0dcc178d8023b..5df7fe8b655e7 100644 --- a/flang/test/Semantics/OpenMP/interop-construct.f90 +++ b/flang/test/Semantics/OpenMP/interop-construct.f90 @@ -8,7 +8,7 @@ SUBROUTINE test_interop_01() USE omp_lib INTEGER(OMP_INTEROP_KIND) :: obj - !ERROR: Each interop-var may be specified for at most one action-clause of each interop construct. + !ERROR: Each interop-var may be specified for at most one action-clause of each INTEROP construct. !$OMP INTEROP INIT(TARGETSYNC,TARGET: obj) USE(obj) PRINT *, 'pass' END SUBROUTINE test_interop_01 @@ -24,7 +24,7 @@ END SUBROUTINE test_interop_02 SUBROUTINE test_interop_03() USE omp_lib INTEGER(OMP_INTEROP_KIND) :: obj - !ERROR: A depend clause can only appear on the directive if the interop-type includes targetsync + !ERROR: A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC !$OMP INTEROP INIT(TARGET: obj) DEPEND(INOUT: obj) PRINT *, 'pass' END SUBROUTINE test_interop_03 From d7d40c3dac1b3a856bc8b375b138a0ead5ca4fbe Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Mon, 17 Mar 2025 21:54:12 +0530 Subject: [PATCH 07/10] Changed the InteropRuntimeIdentifier comment on parse-tree.h --- flang/include/flang/Parser/parse-tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index fe3bab873ee5a..371d7653b3b34 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3826,7 +3826,7 @@ struct OmpExpectation { // REF: [5.1:217-220], [5.2:293-294] // -// OmpRuntimeIdentifier -> // since 5.2 +// OmpInteropRuntimeIdentifier -> // since 5.2 // CharLiteralConstant || ScalarIntConstantExpr struct OmpInteropRuntimeIdentifier { UNION_CLASS_BOILERPLATE(OmpInteropRuntimeIdentifier); From 1c24552faf0951e15c5c7abcff090b7d091a2fc2 Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Tue, 18 Mar 2025 11:15:58 +0530 Subject: [PATCH 08/10] Formatted check-omp-structures.cpp --- flang/lib/Semantics/check-omp-structure.cpp | 24 +++++++++------------ 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 13e07ebf01c44..11438a486966c 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5650,7 +5650,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { common::visitors{ [&](const parser::OmpClause::Init &initClause) { if (OmpVerifyModifiers(initClause.v, llvm::omp::OMPC_init, - GetContext().directiveSource, context_)) { + GetContext().directiveSource, context_)) { auto &modifiers{OmpGetModifiers(initClause.v)}; auto &&interopTypeModifier{ @@ -5669,9 +5669,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { const auto *name{parser::Unwrap(interopVar)}; const auto *objectSymbol{name->symbol}; if (llvm::is_contained(objectSymbolList, objectSymbol)) { - context_.Say( - GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5685,9 +5684,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { const auto *name{parser::Unwrap(interopVar)}; const auto *objectSymbol{name->symbol}; if (llvm::is_contained(objectSymbolList, objectSymbol)) { - context_.Say( - GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5698,9 +5696,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { const auto *name{parser::Unwrap(interopVar)}; const auto *objectSymbol{name->symbol}; if (llvm::is_contained(objectSymbolList, objectSymbol)) { - context_.Say( - GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5711,12 +5708,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { } if (targetCount > 1 || targetSyncCount > 1) { context_.Say(GetContext().directiveSource, - "Each interop-type may be specified at most once."_err_en_US); + "Each interop-type may be specified at most once."_err_en_US); } if (isDependClauseOccured && !targetSyncCount) { - context_.Say( - GetContext().directiveSource, - "A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC"_err_en_US); + context_.Say(GetContext().directiveSource, + "A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC"_err_en_US); } } From 4d2d1680460b9ad7d3905f17a14aa922b0959cf2 Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Tue, 18 Mar 2025 11:22:23 +0530 Subject: [PATCH 09/10] Formatted using git clang-format --- flang/lib/Semantics/check-omp-structure.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 11438a486966c..afd2814bba30c 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5670,7 +5670,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { const auto *objectSymbol{name->symbol}; if (llvm::is_contained(objectSymbolList, objectSymbol)) { context_.Say(GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5685,7 +5685,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { const auto *objectSymbol{name->symbol}; if (llvm::is_contained(objectSymbolList, objectSymbol)) { context_.Say(GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5697,7 +5697,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { const auto *objectSymbol{name->symbol}; if (llvm::is_contained(objectSymbolList, objectSymbol)) { context_.Say(GetContext().directiveSource, - "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); } else { objectSymbolList.insert(objectSymbol); } @@ -5708,11 +5708,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { } if (targetCount > 1 || targetSyncCount > 1) { context_.Say(GetContext().directiveSource, - "Each interop-type may be specified at most once."_err_en_US); + "Each interop-type may be specified at most once."_err_en_US); } if (isDependClauseOccured && !targetSyncCount) { context_.Say(GetContext().directiveSource, - "A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC"_err_en_US); + "A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC"_err_en_US); } } From 40b5b8d499d9d4c9a12f9519dc48be54048537ec Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Tue, 18 Mar 2025 18:32:09 +0530 Subject: [PATCH 10/10] Modified the testcases for Interop construct --- flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 | 1 + flang/test/Parser/OpenMP/interop-construct.f90 | 1 + 2 files changed, 2 insertions(+) diff --git a/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 index 48c50f4a57f27..f7920c09464ed 100644 --- a/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 +++ b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 @@ -1,3 +1,4 @@ +! REQUIRES: openmp_runtime ! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s ! CHECK: not yet implemented: OpenMPInteropConstruct diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90 index 63718d80f87fe..a1781d559b46d 100644 --- a/flang/test/Parser/OpenMP/interop-construct.f90 +++ b/flang/test/Parser/OpenMP/interop-construct.f90 @@ -1,3 +1,4 @@ +! REQUIRES: openmp_runtime ! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version=52 -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s ! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp-version=52 -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s