diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -60,13 +60,16 @@ Directive::OMPD_parallel_workshare, Directive::OMPD_parallel_sections, Directive::OMPD_sections, Directive::OMPD_single} | doSet}; -static OmpDirectiveSet taskloopSet{ - Directive::OMPD_taskloop, Directive::OMPD_taskloop_simd}; +static OmpDirectiveSet taskloopSet{Directive::OMPD_taskloop, + Directive::OMPD_taskloop_simd, Directive::OMPD_tile, + Directive::OMPD_unroll}; static OmpDirectiveSet targetSet{Directive::OMPD_target, Directive::OMPD_target_parallel, Directive::OMPD_target_parallel_do, Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd, Directive::OMPD_target_teams, Directive::OMPD_target_teams_distribute, - Directive::OMPD_target_teams_distribute_simd}; + Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_tile, + OMPD_unroll}; +static OmpDirectiveSet tileSet{Directive::OMPD_tile}; static OmpDirectiveSet simdSet{Directive::OMPD_distribute_parallel_do_simd, Directive::OMPD_distribute_simd, Directive::OMPD_parallel_do_simd, Directive::OMPD_do_simd, Directive::OMPD_simd, @@ -85,6 +88,7 @@ Directive::OMPD_teams_distribute_simd}; static OmpDirectiveSet taskGeneratingSet{ OmpDirectiveSet{Directive::OMPD_task} | taskloopSet}; +static OmpDirectiveSet unrollSet{Directive::OMPD_unroll}; static OmpDirectiveSet nestedOrderedErrSet{Directive::OMPD_critical, Directive::OMPD_ordered, Directive::OMPD_atomic, Directive::OMPD_task, Directive::OMPD_taskloop}; @@ -250,6 +254,8 @@ const parser::DefinedOperator::IntrinsicOperator &); void CheckReductionTypeList(const parser::OmpClause::Reduction &); void CheckMasterNesting(const parser::OpenMPBlockConstruct &x); + void CheckTileConstruct(const parser::OpenMPLoopConstruct &x); + void CheckUnrollConstruct(const parser::OpenMPLoopConstruct &x); void ChecksOnOrderedAsBlock(); void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x); void ChecksOnOrderedAsStandalone(); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -376,7 +376,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { const auto &beginLoopDir{std::get(x.t)}; const auto &beginDir{std::get(beginLoopDir.t)}; - // check matching, End directive is optional if (const auto &endLoopDir{ std::get>(x.t)}) { @@ -420,6 +419,13 @@ llvm::omp::teamSet.test(GetContextParent().directive)) { HasInvalidTeamsNesting(beginDir.v, beginDir.source); } + if (beginDir.v == llvm::omp::Directive::OMPD_tile) { + CheckTileConstruct(x); + } + else if (beginDir.v == llvm::omp::Directive::OMPD_unroll) { + CheckUnrollConstruct(x); + } + if ((beginDir.v == llvm::omp::Directive::OMPD_distribute_parallel_do_simd) || (beginDir.v == llvm::omp::Directive::OMPD_distribute_simd)) { CheckDistLinear(x); @@ -640,6 +646,46 @@ parser::Walk(x, ompCycleChecker); } +void OmpStructureChecker::CheckTileConstruct( + const parser::OpenMPLoopConstruct &x) { + + const auto &beginLoopDir{std::get(x.t)}; + const auto &clauseList{std::get(beginLoopDir.t)}; + + for (const auto &clause : clauseList.v) { + if (const auto *sizeClause{ + std::get_if(&clause.u)}) { + for (const auto &s : sizeClause->v) { + const std::optional u = GetIntValue(s); + if (*u < 0) { + context_.Say(clause.source, + "The parameter value of the SIZES clause must be greater than " + "zero "_err_en_US); + } + } + } + } +} + +void OmpStructureChecker::CheckUnrollConstruct( + const parser::OpenMPLoopConstruct &x) { + + const auto &beginLoopDir{std::get(x.t)}; + const auto &clauseList{std::get(beginLoopDir.t)}; + + for (const auto &clause : clauseList.v) { + if (const auto *sizeClause{ + std::get_if(&clause.u)}) { + const std::optional u = GetIntValue(sizeClause->v); + if (*u < 1) { + context_.Say(clause.source, + "The parameter value of the PARTIAL clause must be greater than " + "one "_err_en_US); + } + } + } +} + void OmpStructureChecker::CheckDistLinear( const parser::OpenMPLoopConstruct &x) { diff --git a/flang/test/Parser/omp-tile-multisize.f90 b/flang/test/Parser/omp-tile-multisize.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Parser/omp-tile-multisize.f90 @@ -0,0 +1,31 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine openmp_tiles(x, y, z) + +integer, intent(inout)::x, y, z + +!CHECK : !$omp tile sizes +!$omp tile sizes(2, 3, 4) +!CHECK : do +do x = 1, 100 +do y = 1, 100 +do z = 1, 100 + call F1() +!CHECK: end do +end do +end do +end do +!CHECK : !$omp end tile +!$omp end tile + +!PARSE-TREE: OpenMPConstruct->OpenMPLoopConstruct +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE: OmpLoopDirective->llvm::omp::Directive = tile +!PARSE-TREE: OmpClauseList->OmpClause->Sizes->Scalar->Integer->Expr->LiteralConstant -> IntLiteralConstant = '2' +!PARSE-TREE: Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '3' +!PARSE-TREE: Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '4' + +END subroutine openmp_tiles + + diff --git a/flang/test/Parser/omp-tile-size.f90 b/flang/test/Parser/omp-tile-size.f90 --- a/flang/test/Parser/omp-tile-size.f90 +++ b/flang/test/Parser/omp-tile-size.f90 @@ -3,7 +3,7 @@ subroutine openmp_tiles(x) - integer, intent(inout)::x + integer, intent(inout)::x !CHECK: !$omp tile sizes !$omp tile sizes(2) @@ -19,5 +19,5 @@ !PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = tile -!PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' +!PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr-> LiteralConstant -> IntLiteralConstant = '2' END subroutine openmp_tiles diff --git a/flang/test/Parser/omp-tile-size.f90 b/flang/test/Parser/omp-tile-size2.f90 copy from flang/test/Parser/omp-tile-size.f90 copy to flang/test/Parser/omp-tile-size2.f90 --- a/flang/test/Parser/omp-tile-size.f90 +++ b/flang/test/Parser/omp-tile-size2.f90 @@ -3,10 +3,10 @@ subroutine openmp_tiles(x) - integer, intent(inout)::x - + integer, intent(inout)::x + integer, parameter :: k = 3 !CHECK: !$omp tile sizes -!$omp tile sizes(2) +!$omp tile sizes(k) !CHECK: do do x = 1, 100 call F1() @@ -15,9 +15,9 @@ !CHECK: !$omp end tile !$omp end tile - +!PARSE-TREE: Initialization -> Constant -> Expr -> LiteralConstant -> IntLiteralConstant = '3' !PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = tile -!PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' +!PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr-> Designator -> DataRef -> Name = 'k' END subroutine openmp_tiles diff --git a/flang/test/Parser/omp-tile-size.f90 b/flang/test/Parser/omp-tile-size3.f90 copy from flang/test/Parser/omp-tile-size.f90 copy to flang/test/Parser/omp-tile-size3.f90 --- a/flang/test/Parser/omp-tile-size.f90 +++ b/flang/test/Parser/omp-tile-size3.f90 @@ -3,10 +3,10 @@ subroutine openmp_tiles(x) - integer, intent(inout)::x + integer, intent(inout)::x !CHECK: !$omp tile sizes -!$omp tile sizes(2) +!$omp tile sizes(2+1) !CHECK: do do x = 1, 100 call F1() @@ -19,5 +19,7 @@ !PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct !PARSE-TREE: OmpBeginLoopDirective !PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = tile -!PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr = '2_4' +!PARSE-TREE: OmpClauseList -> OmpClause -> Sizes -> Scalar -> Integer -> Expr-> Add +!PARSE-TREE: Expr -> LiteralConstant -> IntLiteralConstant = '2' +!PARSE-TREE: Expr -> LiteralConstant -> IntLiteralConstant = '1' END subroutine openmp_tiles diff --git a/flang/test/Parser/omp-unroll_2.f90 b/flang/test/Parser/omp-unroll_2.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Parser/omp-unroll_2.f90 @@ -0,0 +1,25 @@ +! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine openmp_parse_unroll(x) + + integer, intent(inout)::x + +!CHECK: !$omp unroll partial +!$omp unroll partial(2+2) +!CHECK: do + do x = 1, 100 + call F1() +!CHECK: end do + end do +!CHECK: !$omp end unroll +!$omp end unroll + +!PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = unroll +!PARSE-TREE: OmpClauseList -> OmpClause -> Partial -> Scalar -> Integer -> Constant -> Expr = 'Add' +!PARSE-TREE: Expr -> LiteralConstant -> IntLiteralConstant = '2' +!PARSE-TREE: Expr -> LiteralConstant -> IntLiteralConstant = '2' + +END subroutine openmp_parse_unroll diff --git a/flang/test/Semantics/OpenMP/omp-do-tile.f90 b/flang/test/Semantics/OpenMP/omp-do-tile.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/OpenMP/omp-do-tile.f90 @@ -0,0 +1,17 @@ +!RUN: % python %S/../test_errors.py %s %flang -fopenmp +!OpenMP Version 5.1 +!2.11.9.1 tile Cconstruct + +program omp_dotile + integer::i, j, k,z + !ERROR: The parameter value in the SIZES clause must be greater than one + !$omp tile sizes(2, -2, 2) + do i = 1,100 + do j = 1,100 + do k = 1,100 + print *,"hello" + end do + end do + end do + !$omp end tile +end program omp_dotile diff --git a/flang/test/Semantics/OpenMP/omp-do-unroll.f90 b/flang/test/Semantics/OpenMP/omp-do-unroll.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/OpenMP/omp-do-unroll.f90 @@ -0,0 +1,14 @@ +!RUN : %python %S/../test_errors.py %s %flang -fopenmp +!OpenMP Version 5.1 +!2.11.9.2 unroll Construct + + program omp_doUnroll + integer::j + integer, parameter :: x = 3 + !ERROR: The parameter value in the PARTIAL clause must be greater than one + !$omp unroll partial(x) + do j = 1,10 + print *,"hello" + end do + !$omp end unroll +end program omp_doUnroll