https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/154377
>From 4442fced8216bf8e26522e2b88884b127e4cfc40 Mon Sep 17 00:00:00 2001 From: skc7 <krishna.sank...@amd.com> Date: Tue, 19 Aug 2025 21:43:06 +0530 Subject: [PATCH 1/3] [flang][openmp] Add parser/semantic support for workdistribute --- .../flang/Semantics/openmp-directive-sets.h | 7 ++ flang/lib/Parser/openmp-parsers.cpp | 6 +- flang/lib/Semantics/check-omp-structure.cpp | 95 +++++++++++++++++++ flang/lib/Semantics/check-omp-structure.h | 1 + flang/lib/Semantics/resolve-directives.cpp | 8 +- flang/test/Parser/OpenMP/workdistribute.f90 | 27 ++++++ .../Semantics/OpenMP/workdistribute01.f90 | 16 ++++ .../Semantics/OpenMP/workdistribute02.f90 | 34 +++++++ .../Semantics/OpenMP/workdistribute03.f90 | 34 +++++++ 9 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 flang/test/Parser/OpenMP/workdistribute.f90 create mode 100644 flang/test/Semantics/OpenMP/workdistribute01.f90 create mode 100644 flang/test/Semantics/OpenMP/workdistribute02.f90 create mode 100644 flang/test/Semantics/OpenMP/workdistribute03.f90 diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h index cc66cc833e8b7..01e8481e05721 100644 --- a/flang/include/flang/Semantics/openmp-directive-sets.h +++ b/flang/include/flang/Semantics/openmp-directive-sets.h @@ -143,6 +143,7 @@ static const OmpDirectiveSet topTargetSet{ Directive::OMPD_target_teams_distribute_parallel_do_simd, Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_target_teams_loop, + Directive::OMPD_target_teams_workdistribute, }; static const OmpDirectiveSet allTargetSet{topTargetSet}; @@ -172,6 +173,7 @@ static const OmpDirectiveSet topTeamsSet{ Directive::OMPD_teams_distribute_parallel_do_simd, Directive::OMPD_teams_distribute_simd, Directive::OMPD_teams_loop, + Directive::OMPD_teams_workdistribute, }; static const OmpDirectiveSet bottomTeamsSet{ @@ -187,6 +189,7 @@ static const OmpDirectiveSet allTeamsSet{ Directive::OMPD_target_teams_distribute_parallel_do_simd, Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_target_teams_loop, + Directive::OMPD_target_teams_workdistribute, } | topTeamsSet, }; @@ -230,6 +233,9 @@ static const OmpDirectiveSet blockConstructSet{ Directive::OMPD_taskgroup, Directive::OMPD_teams, Directive::OMPD_workshare, + Directive::OMPD_target_teams_workdistribute, + Directive::OMPD_teams_workdistribute, + Directive::OMPD_workdistribute, }; static const OmpDirectiveSet loopConstructSet{ @@ -376,6 +382,7 @@ static const OmpDirectiveSet nestedReduceWorkshareAllowedSet{ }; static const OmpDirectiveSet nestedTeamsAllowedSet{ + Directive::OMPD_workdistribute, Directive::OMPD_distribute, Directive::OMPD_distribute_parallel_do, Directive::OMPD_distribute_parallel_do_simd, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 56cee4ab38e9b..51b49a591b02f 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1870,11 +1870,15 @@ TYPE_PARSER( // MakeBlockConstruct(llvm::omp::Directive::OMPD_target_data) || MakeBlockConstruct(llvm::omp::Directive::OMPD_target_parallel) || MakeBlockConstruct(llvm::omp::Directive::OMPD_target_teams) || + MakeBlockConstruct( + llvm::omp::Directive::OMPD_target_teams_workdistribute) || MakeBlockConstruct(llvm::omp::Directive::OMPD_target) || MakeBlockConstruct(llvm::omp::Directive::OMPD_task) || MakeBlockConstruct(llvm::omp::Directive::OMPD_taskgroup) || MakeBlockConstruct(llvm::omp::Directive::OMPD_teams) || - MakeBlockConstruct(llvm::omp::Directive::OMPD_workshare)) + MakeBlockConstruct(llvm::omp::Directive::OMPD_teams_workdistribute) || + MakeBlockConstruct(llvm::omp::Directive::OMPD_workshare) || + MakeBlockConstruct(llvm::omp::Directive::OMPD_workdistribute)) #undef MakeBlockConstruct // OMP SECTIONS Directive diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 2b36b085ae08d..4c4e17c39c03a 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -141,6 +141,67 @@ class OmpWorkshareBlockChecker { parser::CharBlock source_; }; +// 'OmpWorkdistributeBlockChecker' is used to check the validity of the +// assignment statements and the expressions enclosed in an OpenMP +// workdistribute construct +class OmpWorkdistributeBlockChecker { +public: + OmpWorkdistributeBlockChecker( + SemanticsContext &context, parser::CharBlock source) + : context_{context}, source_{source} {} + + template <typename T> bool Pre(const T &) { return true; } + template <typename T> void Post(const T &) {} + + bool Pre(const parser::AssignmentStmt &assignment) { + const auto &var{std::get<parser::Variable>(assignment.t)}; + const auto &expr{std::get<parser::Expr>(assignment.t)}; + const auto *lhs{GetExpr(context_, var)}; + const auto *rhs{GetExpr(context_, expr)}; + if (lhs && rhs) { + Tristate isDefined{semantics::IsDefinedAssignment( + lhs->GetType(), lhs->Rank(), rhs->GetType(), rhs->Rank())}; + if (isDefined == Tristate::Yes) { + context_.Say(expr.source, + "Defined assignment statement is not " + "allowed in a WORKDISTRIBUTE construct"_err_en_US); + } + } + return true; + } + + bool Pre(const parser::Expr &expr) { + if (const auto *e{GetExpr(context_, expr)}) { + for (const Symbol &symbol : evaluate::CollectSymbols(*e)) { + const Symbol &root{GetAssociationRoot(symbol)}; + if (IsFunction(root)) { + std::string attrs{""}; + if (!IsElementalProcedure(root)) { + attrs = " non-ELEMENTAL"; + } + if (root.attrs().test(Attr::IMPURE)) { + if (attrs != "") { + attrs = "," + attrs; + } + attrs = " IMPURE" + attrs; + } + if (attrs != "") { + context_.Say(expr.source, + "User defined%s function '%s' is not allowed in a " + "WORKDISTRIBUTE construct"_err_en_US, + attrs, root.name()); + } + } + } + } + return false; + } + +private: + SemanticsContext &context_; + parser::CharBlock source_; +}; + // `OmpUnitedTaskDesignatorChecker` is used to check if the designator // can appear within the TASK construct class OmpUnitedTaskDesignatorChecker { @@ -813,6 +874,13 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { "TARGET construct with nested TEAMS region contains statements or " "directives outside of the TEAMS construct"_err_en_US); } + if (GetContext().directive == llvm::omp::Directive::OMPD_workdistribute && + GetContextParent().directive != llvm::omp::Directive::OMPD_teams) { + context_.Say(x.BeginDir().DirName().source, + "%s region can only be strictly nested within the " + "teams region"_err_en_US, + ContextDirectiveAsFortran()); + } } CheckNoBranching(block, beginSpec.DirId(), beginSpec.source); @@ -896,6 +964,17 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { HasInvalidWorksharingNesting( beginSpec.source, llvm::omp::nestedWorkshareErrSet); break; + case llvm::omp::OMPD_workdistribute: + if (!CurrentDirectiveIsNested()) { + context_.Say(beginSpec.source, + "A workdistribute region must be nested inside teams region only."_err_en_US); + } + CheckWorkdistributeBlockStmts(block, beginSpec.source); + break; + case llvm::omp::OMPD_teams_workdistribute: + case llvm::omp::OMPD_target_teams_workdistribute: + CheckWorkdistributeBlockStmts(block, beginSpec.source); + break; case llvm::omp::Directive::OMPD_scope: case llvm::omp::Directive::OMPD_single: // TODO: This check needs to be extended while implementing nesting of @@ -4497,6 +4576,22 @@ void OmpStructureChecker::CheckWorkshareBlockStmts( } } +void OmpStructureChecker::CheckWorkdistributeBlockStmts( + const parser::Block &block, parser::CharBlock source) { + OmpWorkdistributeBlockChecker ompWorkdistributeBlockChecker{context_, source}; + + for (auto it{block.begin()}; it != block.end(); ++it) { + if (parser::Unwrap<parser::AssignmentStmt>(*it)) { + parser::Walk(*it, ompWorkdistributeBlockChecker); + } else { + context_.Say(source, + "The structured block in a WORKDISTRIBUTE construct may consist of " + "only " + "SCALAR or ARRAY assignments"_err_en_US); + } + } +} + void OmpStructureChecker::CheckIfContiguous(const parser::OmpObject &object) { if (auto contig{IsContiguous(context_, object)}; contig && !*contig) { const parser::Name *name{GetObjectName(object)}; diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index b548a455ee077..08519c4836ed8 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -245,6 +245,7 @@ class OmpStructureChecker llvmOmpClause clause, const parser::OmpObjectList &ompObjectList); bool CheckTargetBlockOnlyTeams(const parser::Block &); void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock); + void CheckWorkdistributeBlockStmts(const parser::Block &, parser::CharBlock); void CheckIteratorRange(const parser::OmpIteratorSpecifier &x); void CheckIteratorModifier(const parser::OmpIterator &x); diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 6a4660c9882ab..069d78554e9c2 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -1736,10 +1736,13 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPBlockConstruct &x) { case llvm::omp::Directive::OMPD_task: case llvm::omp::Directive::OMPD_taskgroup: case llvm::omp::Directive::OMPD_teams: + case llvm::omp::Directive::OMPD_workdistribute: case llvm::omp::Directive::OMPD_workshare: case llvm::omp::Directive::OMPD_parallel_workshare: case llvm::omp::Directive::OMPD_target_teams: + case llvm::omp::Directive::OMPD_target_teams_workdistribute: case llvm::omp::Directive::OMPD_target_parallel: + case llvm::omp::Directive::OMPD_teams_workdistribute: PushContext(dirSpec.source, dirId); break; default: @@ -1769,9 +1772,12 @@ void OmpAttributeVisitor::Post(const parser::OpenMPBlockConstruct &x) { case llvm::omp::Directive::OMPD_target: case llvm::omp::Directive::OMPD_task: case llvm::omp::Directive::OMPD_teams: + case llvm::omp::Directive::OMPD_workdistribute: case llvm::omp::Directive::OMPD_parallel_workshare: case llvm::omp::Directive::OMPD_target_teams: - case llvm::omp::Directive::OMPD_target_parallel: { + case llvm::omp::Directive::OMPD_target_parallel: + case llvm::omp::Directive::OMPD_target_teams_workdistribute: + case llvm::omp::Directive::OMPD_teams_workdistribute: { bool hasPrivate; for (const auto *allocName : allocateNames_) { hasPrivate = false; diff --git a/flang/test/Parser/OpenMP/workdistribute.f90 b/flang/test/Parser/OpenMP/workdistribute.f90 new file mode 100644 index 0000000000000..874538d5f0296 --- /dev/null +++ b/flang/test/Parser/OpenMP/workdistribute.f90 @@ -0,0 +1,27 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=61 %s | FileCheck --check-prefix="PARSE-TREE" %s + +!UNPARSE: SUBROUTINE teams_workdistribute +!UNPARSE: USE :: iso_fortran_env +!UNPARSE: REAL(KIND=4_4) a +!UNPARSE: REAL(KIND=4_4), DIMENSION(10_4) :: x +!UNPARSE: REAL(KIND=4_4), DIMENSION(10_4) :: y +!UNPARSE: !$OMP TEAMS WORKDISTRIBUTE +!UNPARSE: y=a*x+y +!UNPARSE: !$OMP END TEAMS WORKDISTRIBUTE +!UNPARSE: END SUBROUTINE teams_workdistribute + +!PARSE-TREE: | | | OmpBeginDirective +!PARSE-TREE: | | | | OmpDirectiveName -> llvm::omp::Directive = teams workdistribute +!PARSE-TREE: | | | OmpEndDirective +!PARSE-TREE: | | | | OmpDirectiveName -> llvm::omp::Directive = teams workdistribute + +subroutine teams_workdistribute() + use iso_fortran_env + real(kind=real32) :: a + real(kind=real32), dimension(10) :: x + real(kind=real32), dimension(10) :: y + !$omp teams workdistribute + y = a * x + y + !$omp end teams workdistribute +end subroutine teams_workdistribute diff --git a/flang/test/Semantics/OpenMP/workdistribute01.f90 b/flang/test/Semantics/OpenMP/workdistribute01.f90 new file mode 100644 index 0000000000000..76ddbc74ea4ec --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute01.f90 @@ -0,0 +1,16 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! OpenMP Version 6.0 +! workdistribute Construct +! Invalid do construct inside !$omp workdistribute + +subroutine workdistribute() + integer n, i + !ERROR: A workdistribute region must be nested inside teams region only. + !ERROR: The structured block in a WORKDISTRIBUTE construct may consist of only SCALAR or ARRAY assignments + !$omp workdistribute + do i = 1, n + print *, "omp workdistribute" + end do + !$omp end workdistribute + +end subroutine workdistribute diff --git a/flang/test/Semantics/OpenMP/workdistribute02.f90 b/flang/test/Semantics/OpenMP/workdistribute02.f90 new file mode 100644 index 0000000000000..ad2cde2c3daf0 --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute02.f90 @@ -0,0 +1,34 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! OpenMP Version 6.0 +! workdistribute Construct +! The !omp workdistribute construct must not contain any user defined +! function calls unless the function is ELEMENTAL. + +module my_mod + contains + integer function my_func() + my_func = 10 + end function my_func + + impure integer function impure_my_func() + impure_my_func = 20 + end function impure_my_func + + impure elemental integer function impure_ele_my_func() + impure_ele_my_func = 20 + end function impure_ele_my_func +end module my_mod + +subroutine workdistribute(aa, bb, cc, n) + use my_mod + integer n + real aa(n), bb(n), cc(n) + !$omp teams + !$omp workdistribute + !ERROR: User defined non-ELEMENTAL function 'my_func' is not allowed in a WORKDISTRIBUTE construct + aa = my_func() + aa = bb * cc + !$omp end workdistribute + !$omp end teams + +end subroutine workdistribute diff --git a/flang/test/Semantics/OpenMP/workdistribute03.f90 b/flang/test/Semantics/OpenMP/workdistribute03.f90 new file mode 100644 index 0000000000000..eac28cb39c47f --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute03.f90 @@ -0,0 +1,34 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! OpenMP Version 6.0 +! workdistribute Construct +! All array assignments, scalar assignments, and masked array assignments +! must be intrinsic assignments. + +module defined_assign + interface assignment(=) + module procedure work_assign + end interface + + contains + subroutine work_assign(a,b) + integer, intent(out) :: a + logical, intent(in) :: b(:) + end subroutine work_assign +end module defined_assign + +program omp_workdistribute + use defined_assign + + integer :: a, aa(10), bb(10) + logical :: l(10) + l = .TRUE. + + !$omp teams + !$omp workdistribute + !ERROR: Defined assignment statement is not allowed in a WORKDISTRIBUTE construct + a = l + aa = bb + !$omp end workdistribute + !$omp end teams + +end program omp_workdistribute >From 029719370c496c83a7892be69be13d0eda7580c7 Mon Sep 17 00:00:00 2001 From: skc7 <krishna.sank...@amd.com> Date: Thu, 21 Aug 2025 12:23:17 +0530 Subject: [PATCH 2/3] Fix error messages. --- flang/lib/Semantics/check-omp-structure.cpp | 41 +++++++++---------- flang/test/Parser/OpenMP/workdistribute.f90 | 4 +- .../Semantics/OpenMP/workdistribute01.f90 | 4 +- .../Semantics/OpenMP/workdistribute02.f90 | 2 +- .../Semantics/OpenMP/workdistribute03.f90 | 2 +- .../Semantics/OpenMP/workdistribute04.f90 | 15 +++++++ 6 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 flang/test/Semantics/OpenMP/workdistribute04.f90 diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 4c4e17c39c03a..6f76c9a4420e7 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -143,7 +143,7 @@ class OmpWorkshareBlockChecker { // 'OmpWorkdistributeBlockChecker' is used to check the validity of the // assignment statements and the expressions enclosed in an OpenMP -// workdistribute construct +// WORKDISTRIBUTE construct class OmpWorkdistributeBlockChecker { public: OmpWorkdistributeBlockChecker( @@ -163,8 +163,7 @@ class OmpWorkdistributeBlockChecker { lhs->GetType(), lhs->Rank(), rhs->GetType(), rhs->Rank())}; if (isDefined == Tristate::Yes) { context_.Say(expr.source, - "Defined assignment statement is not " - "allowed in a WORKDISTRIBUTE construct"_err_en_US); + "Defined assignment statement is not allowed in a WORKDISTRIBUTE construct"_err_en_US); } } return true; @@ -172,25 +171,23 @@ class OmpWorkdistributeBlockChecker { bool Pre(const parser::Expr &expr) { if (const auto *e{GetExpr(context_, expr)}) { + if (!e) + return false; for (const Symbol &symbol : evaluate::CollectSymbols(*e)) { const Symbol &root{GetAssociationRoot(symbol)}; if (IsFunction(root)) { - std::string attrs{""}; + std::vector<std::string> attrs; if (!IsElementalProcedure(root)) { - attrs = " non-ELEMENTAL"; + attrs.push_back("non-ELEMENTAL"); } if (root.attrs().test(Attr::IMPURE)) { - if (attrs != "") { - attrs = "," + attrs; - } - attrs = " IMPURE" + attrs; - } - if (attrs != "") { - context_.Say(expr.source, - "User defined%s function '%s' is not allowed in a " - "WORKDISTRIBUTE construct"_err_en_US, - attrs, root.name()); + attrs.push_back("IMPURE"); } + std::string attrsStr = + attrs.empty() ? "" : " " + llvm::join(attrs, ", "); + context_.Say(expr.source, + "User defined%s function '%s' is not allowed in a WORKDISTRIBUTE construct"_err_en_US, + attrsStr, root.name()); } } } @@ -877,8 +874,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { if (GetContext().directive == llvm::omp::Directive::OMPD_workdistribute && GetContextParent().directive != llvm::omp::Directive::OMPD_teams) { context_.Say(x.BeginDir().DirName().source, - "%s region can only be strictly nested within the " - "teams region"_err_en_US, + "%s region can only be strictly nested within TEAMS region"_err_en_US, ContextDirectiveAsFortran()); } } @@ -967,7 +963,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { case llvm::omp::OMPD_workdistribute: if (!CurrentDirectiveIsNested()) { context_.Say(beginSpec.source, - "A workdistribute region must be nested inside teams region only."_err_en_US); + "A WORKDISTRIBUTE region must be nested inside TEAMS region only."_err_en_US); } CheckWorkdistributeBlockStmts(block, beginSpec.source); break; @@ -4578,6 +4574,11 @@ void OmpStructureChecker::CheckWorkshareBlockStmts( void OmpStructureChecker::CheckWorkdistributeBlockStmts( const parser::Block &block, parser::CharBlock source) { + unsigned version{context_.langOptions().OpenMPVersion}; + if (version < 60) + context_.Say(source, + "WORKDISTRIBUTE construct is only supported from openMP 6.0"_err_en_US); + OmpWorkdistributeBlockChecker ompWorkdistributeBlockChecker{context_, source}; for (auto it{block.begin()}; it != block.end(); ++it) { @@ -4585,9 +4586,7 @@ void OmpStructureChecker::CheckWorkdistributeBlockStmts( parser::Walk(*it, ompWorkdistributeBlockChecker); } else { context_.Say(source, - "The structured block in a WORKDISTRIBUTE construct may consist of " - "only " - "SCALAR or ARRAY assignments"_err_en_US); + "The structured block in a WORKDISTRIBUTE construct may consist of only SCALAR or ARRAY assignments"_err_en_US); } } } diff --git a/flang/test/Parser/OpenMP/workdistribute.f90 b/flang/test/Parser/OpenMP/workdistribute.f90 index 874538d5f0296..09273ab0485cd 100644 --- a/flang/test/Parser/OpenMP/workdistribute.f90 +++ b/flang/test/Parser/OpenMP/workdistribute.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 -fopenmp -fopenmp-version=61 %s | FileCheck --check-prefix="PARSE-TREE" %s +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s !UNPARSE: SUBROUTINE teams_workdistribute !UNPARSE: USE :: iso_fortran_env diff --git a/flang/test/Semantics/OpenMP/workdistribute01.f90 b/flang/test/Semantics/OpenMP/workdistribute01.f90 index 76ddbc74ea4ec..f7e36976dfb65 100644 --- a/flang/test/Semantics/OpenMP/workdistribute01.f90 +++ b/flang/test/Semantics/OpenMP/workdistribute01.f90 @@ -1,11 +1,11 @@ -! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 ! OpenMP Version 6.0 ! workdistribute Construct ! Invalid do construct inside !$omp workdistribute subroutine workdistribute() integer n, i - !ERROR: A workdistribute region must be nested inside teams region only. + !ERROR: A WORKDISTRIBUTE region must be nested inside TEAMS region only. !ERROR: The structured block in a WORKDISTRIBUTE construct may consist of only SCALAR or ARRAY assignments !$omp workdistribute do i = 1, n diff --git a/flang/test/Semantics/OpenMP/workdistribute02.f90 b/flang/test/Semantics/OpenMP/workdistribute02.f90 index ad2cde2c3daf0..6de3a55f545b5 100644 --- a/flang/test/Semantics/OpenMP/workdistribute02.f90 +++ b/flang/test/Semantics/OpenMP/workdistribute02.f90 @@ -1,4 +1,4 @@ -! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 ! OpenMP Version 6.0 ! workdistribute Construct ! The !omp workdistribute construct must not contain any user defined diff --git a/flang/test/Semantics/OpenMP/workdistribute03.f90 b/flang/test/Semantics/OpenMP/workdistribute03.f90 index eac28cb39c47f..828170a016ed2 100644 --- a/flang/test/Semantics/OpenMP/workdistribute03.f90 +++ b/flang/test/Semantics/OpenMP/workdistribute03.f90 @@ -1,4 +1,4 @@ -! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 ! OpenMP Version 6.0 ! workdistribute Construct ! All array assignments, scalar assignments, and masked array assignments diff --git a/flang/test/Semantics/OpenMP/workdistribute04.f90 b/flang/test/Semantics/OpenMP/workdistribute04.f90 new file mode 100644 index 0000000000000..7f8e358279bc6 --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute04.f90 @@ -0,0 +1,15 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! OpenMP Version 6.0 +! workdistribute Construct +! Invalid do construct inside !$omp workdistribute + +subroutine teams_workdistribute() + use iso_fortran_env + real(kind=real32) :: a + real(kind=real32), dimension(10) :: x + real(kind=real32), dimension(10) :: y + !ERROR: WORKDISTRIBUTE construct is only supported from openMP 6.0 + !$omp teams workdistribute + y = a * x + y + !$omp end teams workdistribute +end subroutine teams_workdistribute >From 7e40d31a339baf49541334e2250355dab6f665bf Mon Sep 17 00:00:00 2001 From: skc7 <krishna.sank...@amd.com> Date: Fri, 22 Aug 2025 20:59:19 +0530 Subject: [PATCH 3/3] Fix comment in test --- flang/test/Semantics/OpenMP/workdistribute04.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flang/test/Semantics/OpenMP/workdistribute04.f90 b/flang/test/Semantics/OpenMP/workdistribute04.f90 index 7f8e358279bc6..2100108006f9b 100644 --- a/flang/test/Semantics/OpenMP/workdistribute04.f90 +++ b/flang/test/Semantics/OpenMP/workdistribute04.f90 @@ -1,7 +1,7 @@ ! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 ! OpenMP Version 6.0 ! workdistribute Construct -! Invalid do construct inside !$omp workdistribute +! Unsuported OpenMP version subroutine teams_workdistribute() use iso_fortran_env _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits