From f1569b1ece5516d31d8c748f7b2981a688e32826 Mon Sep 17 00:00:00 2001 From: sameeran joshi Date: Mon, 14 Dec 2020 13:30:26 +0530 Subject: [PATCH] [Flang][OpenMP-5.0] Semantic checks for flush construct. From OMP 5.0 [2.17.8] Restriction: If memory-order-clause is release,acquire, or acq_rel, list items must not be specified on the flush directive. Reviewed By: kiranchandramohan, clementval Differential Revision: https://reviews.llvm.org/D89879 --- flang/include/flang/Parser/parse-tree.h | 2 +- flang/lib/Lower/OpenMP.cpp | 3 +- flang/lib/Parser/openmp-parsers.cpp | 2 +- flang/lib/Parser/unparse.cpp | 2 +- flang/lib/Semantics/check-omp-structure.cpp | 12 ++- .../test/Semantics/omp-clause-validity01.f90 | 1 + flang/test/Semantics/omp-flush01.f90 | 39 +++++++++ flang/test/Semantics/omp-flush02.f90 | 86 +++++++++++++++++++ llvm/include/llvm/Frontend/OpenMP/OMP.td | 2 +- 9 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 flang/test/Semantics/omp-flush01.f90 create mode 100644 flang/test/Semantics/omp-flush02.f90 diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 5d2909a4142a..27998c308cc0 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3747,7 +3747,7 @@ struct OpenMPCancelConstruct { struct OpenMPFlushConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct); CharBlock source; - std::tuple, + std::tuple>, std::optional> t; }; diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp index cfe4b0b86b67..97946caa68a0 100644 --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -109,7 +109,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, std::get>( flushConstruct.t)) genObjectList(*ompObjectList, converter, operandRange); - if (std::get>( + if (std::get>>( flushConstruct.t)) TODO("Handle OmpMemoryOrderClause"); converter.getFirOpBuilder().create( diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index fd209abc4138..67c377e798ca 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -331,7 +331,7 @@ TYPE_PARSER(sourced(construct( many(maybe(","_tok) >> sourced(Parser{}))))) TYPE_PARSER(sourced(construct(verbatim("FLUSH"_tok), - maybe(Parser{}), + many(maybe(","_tok) >> sourced(Parser{})), maybe(parenthesized(Parser{}))))) // Simple Standalone Directives diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index c5df6990d102..bd1c1a2c71eb 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2460,7 +2460,7 @@ public: void Unparse(const OpenMPFlushConstruct &x) { BeginOpenMP(); Word("!$OMP FLUSH "); - Walk(std::get>(x.t)); + Walk(std::get>>(x.t)); Walk(" (", std::get>(x.t), ")"); Put("\n"); EndOpenMP(); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index e58e2e509fb8..978e1c7962a4 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -226,7 +226,17 @@ void OmpStructureChecker::Enter(const parser::OpenMPFlushConstruct &x) { PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_flush); } -void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) { +void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) { + if (FindClause(llvm::omp::Clause::OMPC_acquire) || + FindClause(llvm::omp::Clause::OMPC_release) || + FindClause(llvm::omp::Clause::OMPC_acq_rel)) { + if (const auto &flushList{ + std::get>(x.t)}) { + context_.Say(parser::FindSourceLocation(flushList), + "If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items " + "must not be specified on the FLUSH directive"_err_en_US); + } + } dirContext_.pop_back(); } diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90 index 601e39021e44..3f5345137866 100644 --- a/flang/test/Semantics/omp-clause-validity01.f90 +++ b/flang/test/Semantics/omp-clause-validity01.f90 @@ -487,6 +487,7 @@ use omp_lib !$omp flush acq_rel !$omp flush release !$omp flush acquire + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive !$omp flush release (c) !ERROR: SEQ_CST clause is not allowed on the FLUSH directive !$omp flush seq_cst diff --git a/flang/test/Semantics/omp-flush01.f90 b/flang/test/Semantics/omp-flush01.f90 new file mode 100644 index 000000000000..cca78e7a09cd --- /dev/null +++ b/flang/test/Semantics/omp-flush01.f90 @@ -0,0 +1,39 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp + +! 2.17.8 Flush construct [OpenMP 5.0] +! memory-order-clause -> +! acq_rel +! release +! acquire +use omp_lib + implicit none + + integer :: i, a, b + real, DIMENSION(10) :: array + + a = 1.0 + !$omp parallel num_threads(4) + !Only memory-order-clauses. + if (omp_get_thread_num() == 1) then + ! Allowed clauses. + !$omp flush acq_rel + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !$omp flush release + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !$omp flush acquire + + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush private(array) + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush num_threads(4) + + ! Mix allowed and not allowed clauses. + !ERROR: expected end of line + !ERROR: expected end of line + !$omp flush num_threads(4) acquire + end if + !$omp end parallel +end + diff --git a/flang/test/Semantics/omp-flush02.f90 b/flang/test/Semantics/omp-flush02.f90 new file mode 100644 index 000000000000..6e417c49a3b0 --- /dev/null +++ b/flang/test/Semantics/omp-flush02.f90 @@ -0,0 +1,86 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp + +! Check OpenMP 5.0 - 2.17.8 flush Construct +! Restriction - +! If memory-order-clause is release, acquire, or acq_rel, list items must not be specified on the flush directive. + +use omp_lib + implicit none + + TYPE someStruct + REAL :: rr + end TYPE + integer :: i, a, b + real, DIMENSION(10) :: array + TYPE(someStruct) :: structObj + + a = 1.0 + !$omp parallel num_threads(4) + !No list flushes all. + if (omp_get_thread_num() == 1) THEN + !$omp flush + END IF + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !Only memory-order-clauses. + if (omp_get_thread_num() == 1) THEN + ! Not allowed clauses. + !ERROR: SEQ_CST clause is not allowed on the FLUSH directive + !$omp flush seq_cst + !ERROR: RELAXED clause is not allowed on the FLUSH directive + !$omp flush relaxed + + ! Not allowed more than once. + !ERROR: At most one ACQ_REL clause can appear on the FLUSH directive + !$omp flush acq_rel acq_rel + !ERROR: At most one RELEASE clause can appear on the FLUSH directive + !$omp flush release release + !ERROR: At most one ACQUIRE clause can appear on the FLUSH directive + !$omp flush acquire acquire + + ! Mix of allowed and not allowed. + !ERROR: SEQ_CST clause is not allowed on the FLUSH directive + !$omp flush seq_cst acquire + END IF + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + ! No memory-order-clause only list-items. + if (omp_get_thread_num() == 2) THEN + !$omp flush (a) + !$omp flush (i, a, b) + !$omp flush (array, structObj%rr) + ! Too many flush with repeating list items. + !$omp flush (i, a, b, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, b, b, b, b) + !ERROR: No explicit type declared for 'notpresentitem' + !$omp flush (notPresentItem) + END IF + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + if (omp_get_thread_num() == 3) THEN + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush acq_rel (array) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush acq_rel (array, a, i) + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush release (array) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush release (array, a) + + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush acquire (array) + !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive + !$omp flush acquire (array, a, structObj%rr) + END IF + !$omp end parallel + + !$omp parallel num_threads(4) + array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !$omp master + !$omp flush (array) + !$omp end master + !$omp end parallel +end + diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 13aa1381d679..59198f8a64fb 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -446,7 +446,7 @@ def OMP_TaskGroup : Directive<"taskgroup"> { ]; } def OMP_Flush : Directive<"flush"> { - let allowedClauses = [ + let allowedOnceClauses = [ VersionedClause, VersionedClause, VersionedClause,