diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h index 8eb736bb098fe..50d6d5b59ef7d 100644 --- a/flang/include/flang/Semantics/openmp-directive-sets.h +++ b/flang/include/flang/Semantics/openmp-directive-sets.h @@ -211,6 +211,7 @@ static const OmpDirectiveSet blockConstructSet{ Directive::OMPD_parallel, Directive::OMPD_parallel_masked, Directive::OMPD_parallel_workshare, + Directive::OMPD_scope, Directive::OMPD_single, Directive::OMPD_target, Directive::OMPD_target_data, @@ -281,6 +282,7 @@ static const OmpDirectiveSet workShareSet{ Directive::OMPD_workshare, Directive::OMPD_parallel_workshare, Directive::OMPD_parallel_sections, + Directive::OMPD_scope, Directive::OMPD_sections, Directive::OMPD_single, } | allDoSet, diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index fc54da8babe63..01a40d6e2204e 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -1650,6 +1650,15 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, return sectionsOp; } +static void genScopeOp(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, + ConstructQueue::const_iterator item) { + TODO(loc, "Scope construct"); +} + static mlir::omp::SingleOp genSingleOp(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, @@ -2478,6 +2487,9 @@ static void genOMPDispatch(lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_simd: genStandaloneSimd(converter, symTable, semaCtx, eval, loc, queue, item); break; + case llvm::omp::Directive::OMPD_scope: + genScopeOp(converter, symTable, semaCtx, eval, loc, queue, item); + break; case llvm::omp::Directive::OMPD_single: genSingleOp(converter, symTable, semaCtx, eval, loc, queue, item); break; diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 59a8757e58e8c..e740c421ca802 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -697,6 +697,7 @@ TYPE_PARSER(construct(first( "PARALLEL MASKED" >> pure(llvm::omp::Directive::OMPD_parallel_masked), "PARALLEL WORKSHARE" >> pure(llvm::omp::Directive::OMPD_parallel_workshare), "PARALLEL" >> pure(llvm::omp::Directive::OMPD_parallel), + "SCOPE" >> pure(llvm::omp::Directive::OMPD_scope), "SINGLE" >> pure(llvm::omp::Directive::OMPD_single), "TARGET DATA" >> pure(llvm::omp::Directive::OMPD_target_data), "TARGET PARALLEL" >> pure(llvm::omp::Directive::OMPD_target_parallel), diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 04df988223e8f..19ceb2a3ebc31 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2386,6 +2386,9 @@ class UnparseVisitor { case llvm::omp::Directive::OMPD_parallel: Word("PARALLEL "); break; + case llvm::omp::Directive::OMPD_scope: + Word("SCOPE "); + break; case llvm::omp::Directive::OMPD_single: Word("SINGLE "); break; diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 46486907ceb9e..1c2cf304d0ee9 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -972,6 +972,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { HasInvalidWorksharingNesting( beginDir.source, llvm::omp::nestedWorkshareErrSet); break; + case llvm::omp::Directive::OMPD_scope: case llvm::omp::Directive::OMPD_single: // TODO: This check needs to be extended while implementing nesting of // regions checks. @@ -1864,6 +1865,9 @@ void OmpStructureChecker::Enter(const parser::OmpEndBlockDirective &x) { const auto &dir{std::get(x.t)}; ResetPartialContext(dir.source); switch (dir.v) { + case llvm::omp::Directive::OMPD_scope: + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_end_scope); + break; // 2.7.3 end-single-clause -> copyprivate-clause | // nowait-clause case llvm::omp::Directive::OMPD_single: @@ -1886,7 +1890,8 @@ void OmpStructureChecker::Enter(const parser::OmpEndBlockDirective &x) { // end_workshareare popped as they are pushed while entering the // EndBlockDirective. void OmpStructureChecker::Leave(const parser::OmpEndBlockDirective &x) { - if ((GetContext().directive == llvm::omp::Directive::OMPD_end_single) || + if ((GetContext().directive == llvm::omp::Directive::OMPD_end_scope) || + (GetContext().directive == llvm::omp::Directive::OMPD_end_single) || (GetContext().directive == llvm::omp::Directive::OMPD_end_workshare)) { dirContext_.pop_back(); } diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 33936ba4c2b34..513e42bee976a 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -1526,6 +1526,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPBlockConstruct &x) { case llvm::omp::Directive::OMPD_master: case llvm::omp::Directive::OMPD_ordered: case llvm::omp::Directive::OMPD_parallel: + case llvm::omp::Directive::OMPD_scope: case llvm::omp::Directive::OMPD_single: case llvm::omp::Directive::OMPD_target: case llvm::omp::Directive::OMPD_target_data: @@ -1557,6 +1558,7 @@ void OmpAttributeVisitor::Post(const parser::OpenMPBlockConstruct &x) { case llvm::omp::Directive::OMPD_masked: case llvm::omp::Directive::OMPD_parallel_masked: case llvm::omp::Directive::OMPD_parallel: + case llvm::omp::Directive::OMPD_scope: case llvm::omp::Directive::OMPD_single: case llvm::omp::Directive::OMPD_target: case llvm::omp::Directive::OMPD_task: diff --git a/flang/test/Lower/OpenMP/Todo/scope.f90 b/flang/test/Lower/OpenMP/Todo/scope.f90 new file mode 100644 index 0000000000000..16a067dc8f256 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/scope.f90 @@ -0,0 +1,13 @@ +! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s -fopenmp-version=51 2>&1 | FileCheck %s +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s -fopenmp-version=51 2>&1 | FileCheck %s + +! CHECK: not yet implemented: Scope construct +program omp_scope + integer i + i = 10 + + !$omp scope private(i) + print *, "omp scope", i + !$omp end scope + +end program omp_scope diff --git a/flang/test/Parser/OpenMP/scope.f90 b/flang/test/Parser/OpenMP/scope.f90 new file mode 100644 index 0000000000000..6574136311e71 --- /dev/null +++ b/flang/test/Parser/OpenMP/scope.f90 @@ -0,0 +1,24 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=51 %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=51 %s | FileCheck --check-prefix="PARSE-TREE" %s + +program omp_scope + integer i + i = 10 + +!CHECK: !$OMP SCOPE PRIVATE(i) +!CHECK: !$OMP END SCOPE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = scope +!PARSE-TREE: OmpClauseList -> OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'i' +!PARSE-TREE: Block +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: OmpEndBlockDirective +!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = scope +!PARSE-TREE: OmpClauseList -> OmpClause -> Nowait + + !$omp scope private(i) + print *, "omp scope", i + !$omp end scope nowait +end program omp_scope diff --git a/flang/test/Semantics/OpenMP/invalid-branch.f90 b/flang/test/Semantics/OpenMP/invalid-branch.f90 index ed9e4d268f65a..28aab8b122f3f 100644 --- a/flang/test/Semantics/OpenMP/invalid-branch.f90 +++ b/flang/test/Semantics/OpenMP/invalid-branch.f90 @@ -105,4 +105,12 @@ program omp_invalid_branch !$omp end parallel 9 print *, "2nd alternate return" + !CHECK: invalid branch into an OpenMP structured block + goto 100 + !$omp scope + 100 continue + !CHECK: invalid branch leaving an OpenMP structured block + goto 200 + !$omp end scope + 200 continue end program diff --git a/flang/test/Semantics/OpenMP/nested01.f90 b/flang/test/Semantics/OpenMP/nested01.f90 index 49c964ab86aa6..0936e4c1b45a5 100644 --- a/flang/test/Semantics/OpenMP/nested01.f90 +++ b/flang/test/Semantics/OpenMP/nested01.f90 @@ -25,6 +25,13 @@ !$omp end target enddo + !$omp do + do i = 1, N + !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region + !$omp scope + !$omp end scope + end do + !$omp end do !$omp do do i = 1, N diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 1834ad4d037f3..d592f369a17f9 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -892,7 +892,7 @@ def OMP_Scan : Directive<"scan"> { let association = AS_Separating; let category = CA_Subsidiary; } -def OMP_scope : Directive<"scope"> { +def OMP_Scope : Directive<"scope"> { let allowedClauses = [ VersionedClause, VersionedClause, @@ -905,6 +905,14 @@ def OMP_scope : Directive<"scope"> { let association = AS_Block; let category = CA_Executable; } +def OMP_EndScope : Directive<"end scope"> { + let allowedOnceClauses = [ + VersionedClause, + ]; + let leafConstructs = OMP_Scope.leafConstructs; + let association = OMP_Scope.association; + let category = OMP_Scope.category; +} def OMP_Section : Directive<"section"> { let association = AS_Separating; let category = CA_Subsidiary;