From fe30cf18ab3eb1aba5ea7e44574e27fdde791c1d Mon Sep 17 00:00:00 2001 From: swatheesh-mcw Date: Fri, 28 Mar 2025 20:51:52 +0530 Subject: [PATCH] Revert "Revert "[flang][openmp] Adds Parser and Semantic Support for Interop Construct, and Init and Use Clauses."" (#132343) Reverts llvm/llvm-project#132005 --- flang/examples/FeatureList/FeatureList.cpp | 8 + flang/include/flang/Parser/dump-parse-tree.h | 8 + flang/include/flang/Parser/parse-tree.h | 56 ++++- .../flang/Semantics/openmp-modifiers.h | 2 + flang/lib/Lower/OpenMP/OpenMP.cpp | 10 + flang/lib/Parser/openmp-parsers.cpp | 36 ++- flang/lib/Parser/unparse.cpp | 41 ++++ flang/lib/Semantics/check-omp-structure.cpp | 82 +++++++ flang/lib/Semantics/check-omp-structure.h | 2 + flang/lib/Semantics/openmp-modifiers.cpp | 32 +++ .../Lower/OpenMP/Todo/interop-construct.f90 | 9 + .../test/Parser/OpenMP/interop-construct.f90 | 209 ++++++++++++++++++ .../Semantics/OpenMP/interop-construct.f90 | 30 +++ llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 + 14 files changed, 525 insertions(+), 2 deletions(-) create mode 100644 flang/test/Lower/OpenMP/Todo/interop-construct.f90 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 25485bbb8ff4..94fdfa3e4dea 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -522,6 +522,13 @@ public: READ_FEATURE(OmpScheduleClause) READ_FEATURE(OmpScheduleClause::Kind) READ_FEATURE(OmpScheduleClause::Modifier) + READ_FEATURE(OmpInteropRuntimeIdentifier) + READ_FEATURE(OmpInteropPreference) + READ_FEATURE(OmpInteropType) + READ_FEATURE(OmpInteropType::Value) + READ_FEATURE(OmpInitClause) + READ_FEATURE(OmpInitClause::Modifier) + READ_FEATURE(OmpUseClause) READ_FEATURE(OmpDeviceModifier) READ_FEATURE(OmpDeviceClause) READ_FEATURE(OmpDeviceClause::Modifier) @@ -541,6 +548,7 @@ public: 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 9bff2dab974e..41ad15794ad1 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -657,6 +657,13 @@ public: NODE_ENUM(OmpDeviceModifier, Value) NODE(parser, OmpDeviceTypeClause) NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription) + NODE(parser, OmpInteropRuntimeIdentifier) + NODE(parser, OmpInteropPreference) + NODE(parser, OmpInteropType) + NODE_ENUM(OmpInteropType, Value) + NODE(parser, OmpInitClause) + NODE(OmpInitClause, Modifier) + NODE(parser, OmpUseClause) NODE(parser, OmpUpdateClause) NODE(parser, OmpChunkModifier) NODE_ENUM(OmpChunkModifier, Value) @@ -675,6 +682,7 @@ public: 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 029c3de354b6..b026c26dc08c 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3829,6 +3829,33 @@ struct OmpExpectation { WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value); }; +// REF: [5.1:217-220], [5.2:293-294] +// +// OmpInteropRuntimeIdentifier -> // 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.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 -> @@ -4486,6 +4513,25 @@ 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 +// interop-var: Ompobject +// There can be at most only two interop-type. +struct OmpInitClause { + TUPLE_CLASS_BOILERPLATE(OmpInitClause); + MODIFIER_BOILERPLATE(OmpInteropPreference, OmpInteropType); + std::tuple 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); @@ -4935,6 +4981,14 @@ struct OpenMPFlushConstruct { CharBlock source; }; +// Ref: [5.1:217-220], [5.2:291-292] +// +// interop -> INTEROP clause[ [ [,] clause]...] +struct OpenMPInteropConstruct { + WRAPPER_CLASS_BOILERPLATE(OpenMPInteropConstruct, OmpDirectiveSpecification); + CharBlock source; +}; + struct OpenMPSimpleStandaloneConstruct { WRAPPER_CLASS_BOILERPLATE( OpenMPSimpleStandaloneConstruct, OmpDirectiveSpecification); @@ -4946,7 +5000,7 @@ struct OpenMPStandaloneConstruct { CharBlock source; std::variant + OpenMPDepobjConstruct, OmpMetadirectiveDirective, OpenMPInteropConstruct> u; }; diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index 7cdbf65adebe..4fbd80f989e7 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/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index b8ef18860e9b..1304f06ed28c 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -424,6 +424,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); }, @@ -3363,6 +3366,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 f76a13665547..e84abf87c1cb 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -425,6 +425,17 @@ 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))) + TYPE_PARSER(construct( // Using Parser or Parser has the problem // that they will attempt to treat what follows the '=' as initialization. @@ -552,6 +563,11 @@ TYPE_PARSER(sourced( TYPE_PARSER(sourced(construct(OmpDirectiveNameParser{}))) +TYPE_PARSER(sourced( + construct( + construct(Parser{})) || + construct(Parser{}))) + TYPE_PARSER(sourced(construct( Parser{}))) @@ -788,6 +804,11 @@ TYPE_PARSER( // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) TYPE_PARSER(construct(Parser{})) +// init clause +TYPE_PARSER(construct( + maybe(nonemptyList(Parser{}) / ":"), + Parser{})) + // 2.8.1 ALIGNED (list: alignment) TYPE_PARSER(construct(Parser{}, maybe(":" >> nonemptyList(Parser{})))) @@ -927,6 +948,8 @@ TYPE_PARSER( // "IF" >> construct(construct( parenthesized(Parser{}))) || "INBRANCH" >> construct(construct()) || + "INIT" >> construct(construct( + parenthesized(Parser{}))) || "INCLUSIVE" >> construct(construct( parenthesized(Parser{}))) || "INITIALIZER" >> construct(construct( @@ -1016,6 +1039,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" >> @@ -1251,6 +1276,13 @@ TYPE_PARSER(sourced( // IsDirective(llvm::omp::Directive::OMPD_depobj)) >= Parser{}))) +// OMP 5.2 14.1 Interop construct +TYPE_PARSER(sourced( // + construct( + predicated(OmpDirectiveNameParser{}, + IsDirective(llvm::omp::Directive::OMPD_interop)) >= + Parser{}))) + // Standalone Constructs TYPE_PARSER( sourced( // @@ -1263,7 +1295,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 8cdbf8ed2a67..85c633802e41 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2180,6 +2180,30 @@ public: Walk(std::get>>(x.t), ": "); Walk(std::get(x.t)); } + void Unparse(const OmpInteropPreference &x) { Walk(x.v, ","); } + void Unparse(const OmpInitClause &x) { + using Modifier = OmpInitClause::Modifier; + auto &modifiers{std::get>>(x.t)}; + bool isTypeStart{true}; + for (const Modifier &m : *modifiers) { + if (auto *interopPreferenceMod{ + std::get_if(&m.u)}) { + Put("PREFER_TYPE("); + Walk(*interopPreferenceMod); + Put("),"); + } else if (auto *interopTypeMod{ + std::get_if(&m.u)}) { + if (isTypeStart) { + isTypeStart = false; + } else { + Put(","); + } + Walk(*interopTypeMod); + } + } + Put(": "); + Walk(std::get(x.t)); + } void Unparse(const OmpMapClause &x) { using Modifier = OmpMapClause::Modifier; Walk(std::get>>(x.t), ": "); @@ -2710,6 +2734,22 @@ public: Put("\n"); EndOpenMP(); } + + void Unparse(const OpenMPInteropConstruct &x) { + BeginOpenMP(); + Word("!$OMP INTEROP"); + using Flags = OmpDirectiveSpecification::Flags; + if (std::get(x.v.t) == Flags::DeprecatedSyntax) { + Walk("(", std::get>(x.v.t), ")"); + Walk(" ", std::get>(x.v.t)); + } else { + Walk(" ", std::get>(x.v.t)); + Walk(" (", std::get>(x.v.t), ")"); + } + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPDeclarativeAssumes &x) { BeginOpenMP(); Word("!$OMP ASSUMES "); @@ -3004,6 +3044,7 @@ public: OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation + 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 4df889ea8b83..757d2316e6b5 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5730,6 +5730,88 @@ 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.v.t)}; + std::set objectSymbolList; + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_interop); + const auto &clauseList{std::get>(x.v.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_)) { + + auto &modifiers{OmpGetModifiers(initClause.v)}; + auto &&interopTypeModifier{ + OmpGetRepeatableModifier( + modifiers)}; + for (const auto &it : interopTypeModifier) { + if (it->v == parser::OmpInteropType::Value::TargetSync) { + ++targetSyncCount; + } else { + ++targetCount; + } + } + } + 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 { + objectSymbolList.insert(objectSymbol); + } + }, + [&](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 *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 { + objectSymbolList.insert(objectSymbol); + } + }, + [&](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 { + objectSymbolList.insert(objectSymbol); + } + }, + [&](const auto &) {}, + }, + clause.u); + } + 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); + } +} + +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 d802afeefe72..a8869561cf5e 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -73,6 +73,8 @@ public: 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/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index 73ad7751ee51..c84e832ee52a 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/Lower/OpenMP/Todo/interop-construct.f90 b/flang/test/Lower/OpenMP/Todo/interop-construct.f90 new file mode 100644 index 000000000000..4f6966786399 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/interop-construct.f90 @@ -0,0 +1,9 @@ +! REQUIRES: openmp_runtime +! RUN: %not_todo_cmd %flang_fc1 -emit-llvm %openmp_flags -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 new file mode 100644 index 000000000000..82a1b1195dc3 --- /dev/null +++ b/flang/test/Parser/OpenMP/interop-construct.f90 @@ -0,0 +1,209 @@ +! REQUIRES: openmp_runtime +! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version=52 %openmp_flags %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp-version=52 %openmp_flags %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 -> OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = interop +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Device -> OmpDeviceClause +!PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | Flags = None +!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 -> OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = interop +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!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: | | | Flags = None +!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 -> OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = interop +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!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' +!PARSE-TREE: | | | Flags = None +!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: & +!UNPARSE: !$OMP&arr) 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 -> OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = interop +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | Modifier -> OmpInteropPreference -> OmpInteropRuntimeIdentifier -> CharLiteralConstant +!PARSE-TREE: | | | | | string = 'cuda' +!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' +!PARSE-TREE: | | | OmpClause -> Nowait +!PARSE-TREE: | | | Flags = None +!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 -> OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = interop +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!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' +!PARSE-TREE: | | | Flags = None +!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 000000000000..dfcd55c4adab --- /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 %openmp_flags -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 diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 75347061d9a9..e2a1449d8cc7 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";