[flang-commits] [flang] 7dc18a6 - [flang][OpenMP] Added semantic checks for hint clause
Nimish Mishra via flang-commits
flang-commits at lists.llvm.org
Thu Jul 14 05:55:56 PDT 2022
Author: Nimish Mishra
Date: 2022-07-14T18:24:57+05:30
New Revision: 7dc18a62e40e241019ec77e70f01bc41d39ab748
URL: https://github.com/llvm/llvm-project/commit/7dc18a62e40e241019ec77e70f01bc41d39ab748
DIFF: https://github.com/llvm/llvm-project/commit/7dc18a62e40e241019ec77e70f01bc41d39ab748.diff
LOG: [flang][OpenMP] Added semantic checks for hint clause
This patch improves semantic checks for hint clause.
It checks "hint-expression is a constant expression
that evaluates to a scalar value with kind
`omp_sync_hint_kind` and a value that is a valid
synchronization hint."
Reviewed By: peixin
Differential Revision: https://reviews.llvm.org/D127615
Added:
flang/test/Semantics/OpenMP/omp-atomic-hint-clause.f90
flang/test/Semantics/OpenMP/omp-critical-hint-clause.f90
Modified:
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6dc97eaddb952..64255d2afa004 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -314,6 +314,48 @@ void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
}
}
+template <class D>
+void OmpStructureChecker::CheckHintClause(
+ D *leftOmpClauseList, D *rightOmpClauseList) {
+ auto checkForValidHintClause = [&](const D *clauseList) {
+ for (const auto &clause : clauseList->v) {
+ const Fortran::parser::OmpClause *ompClause = nullptr;
+ if constexpr (std::is_same_v<D,
+ const Fortran::parser::OmpAtomicClauseList>) {
+ ompClause = std::get_if<Fortran::parser::OmpClause>(&clause.u);
+ if (!ompClause)
+ continue;
+ } else if constexpr (std::is_same_v<D,
+ const Fortran::parser::OmpClauseList>) {
+ ompClause = &clause;
+ }
+ if (const Fortran::parser::OmpClause::Hint *
+ hintClause{
+ std::get_if<Fortran::parser::OmpClause::Hint>(&ompClause->u)}) {
+ std::optional<std::int64_t> hintValue = GetIntValue(hintClause->v);
+ if (hintValue && hintValue.value() >= 0) {
+ if((hintValue.value() & 0xC) == 0xC /*`omp_sync_hint_nonspeculative` and `omp_lock_hint_speculative`*/
+ || (hintValue.value() & 0x3) == 0x3 /*`omp_sync_hint_uncontended` and omp_sync_hint_contended*/ )
+ context_.Say(clause.source,
+ "Hint clause value "
+ "is not a valid OpenMP synchronization value"_err_en_US);
+ } else {
+ context_.Say(clause.source,
+ "Hint clause must have non-negative constant "
+ "integer expression"_err_en_US);
+ }
+ }
+ }
+ };
+
+ if (leftOmpClauseList) {
+ checkForValidHintClause(leftOmpClauseList);
+ }
+ if (rightOmpClauseList) {
+ checkForValidHintClause(rightOmpClauseList);
+ }
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
// Simd Construct with Ordered Construct Nesting check
// We cannot use CurrentDirectiveIsNested() here because
@@ -1277,6 +1319,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPCriticalConstruct &x) {
parser::MessageFormattedText{
"Hint clause other than omp_sync_hint_none cannot be specified for an unnamed CRITICAL directive"_err_en_US});
}
+ CheckHintClause<const parser::OmpClauseList>(&ompClause, nullptr);
}
void OmpStructureChecker::Leave(const parser::OpenMPCriticalConstruct &) {
@@ -1580,6 +1623,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
CheckAtomicMemoryOrderClause(
&std::get<parser::OmpAtomicClauseList>(atomicConstruct.t),
nullptr);
+ CheckHintClause<const parser::OmpAtomicClauseList>(
+ &std::get<parser::OmpAtomicClauseList>(atomicConstruct.t),
+ nullptr);
},
[&](const parser::OmpAtomicUpdate &atomicUpdate) {
const auto &dir{std::get<parser::Verbatim>(atomicUpdate.t)};
@@ -1591,6 +1637,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
.statement);
CheckAtomicMemoryOrderClause(
&std::get<0>(atomicUpdate.t), &std::get<2>(atomicUpdate.t));
+ CheckHintClause<const parser::OmpAtomicClauseList>(
+ &std::get<0>(atomicUpdate.t), &std::get<2>(atomicUpdate.t));
},
[&](const auto &atomicConstruct) {
const auto &dir{std::get<parser::Verbatim>(atomicConstruct.t)};
@@ -1598,6 +1646,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
dir.source, llvm::omp::Directive::OMPD_atomic);
CheckAtomicMemoryOrderClause(&std::get<0>(atomicConstruct.t),
&std::get<2>(atomicConstruct.t));
+ CheckHintClause<const parser::OmpAtomicClauseList>(
+ &std::get<0>(atomicConstruct.t),
+ &std::get<2>(atomicConstruct.t));
},
},
x.u);
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index a4748157d04fc..0ff0b90bbe690 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -268,6 +268,7 @@ class OmpStructureChecker
void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
int GetDirectiveNest(const int index) { return directiveNest_[index]; }
+ template <typename D> void CheckHintClause(D *, D *);
enum directiveNestType {
SIMDNest,
diff --git a/flang/test/Semantics/OpenMP/omp-atomic-hint-clause.f90 b/flang/test/Semantics/OpenMP/omp-atomic-hint-clause.f90
new file mode 100644
index 0000000000000..048dd978eed56
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/omp-atomic-hint-clause.f90
@@ -0,0 +1,105 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+! Semantic checks on hint clauses, as they appear on atomic constructs
+
+program sample
+ use omp_lib
+ integer :: x, y
+ logical :: z
+ real :: k
+ integer :: p(1)
+ integer, parameter :: a = 1
+ !$omp atomic hint(1) write
+ y = 2
+
+ !$omp atomic read hint(2)
+ y = x
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp atomic hint(3)
+ y = y + 10
+
+ !$omp atomic update hint(5)
+ y = x
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp atomic hint(7) capture
+ y = x
+ x = y
+ !$omp end atomic
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp atomic update hint(x)
+ y = y * 1
+
+ !$omp atomic read hint(4)
+ y = x
+
+ !$omp atomic hint(8)
+ x = x * y
+
+ !$omp atomic write hint(omp_sync_hint_uncontended)
+ x = 10 * y
+
+ !$omp atomic hint(omp_lock_hint_speculative)
+ x = y + x
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp atomic hint(omp_sync_hint_uncontended + omp_sync_hint) read
+ y = x
+
+ !$omp atomic hint(omp_sync_hint_nonspeculative)
+ y = y * 9
+
+ !$omp atomic hint(omp_sync_hint_none) read
+ y = x
+
+ !$omp atomic read hint(omp_sync_hint_uncontended + omp_lock_hint_speculative)
+ y = x
+
+ !$omp atomic hint(omp_lock_hint_nonspeculative + omp_lock_hint_uncontended)
+ x = x * y
+
+ !$omp atomic write hint(omp_lock_hint_contended + omp_sync_hint_speculative)
+ x = 10 * y
+
+ !$omp atomic hint(omp_lock_hint_contended + omp_sync_hint_nonspeculative)
+ x = y + x
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp atomic hint(omp_sync_hint_uncontended + omp_sync_hint_contended) read
+ y = x
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp atomic hint(omp_sync_hint_nonspeculative + omp_lock_hint_speculative)
+ y = y * 9
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !$omp atomic hint(1.0) read
+ y = x
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Operands of + must be numeric; have LOGICAL(4) and INTEGER(4)
+ !$omp atomic hint(z + omp_sync_hint_nonspeculative) read
+ y = x
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp atomic hint(k + omp_sync_hint_speculative) read
+ y = x
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp atomic hint(p(1) + omp_sync_hint_uncontended) write
+ x = 10 * y
+
+ !$omp atomic write hint(a)
+ x = y + x
+
+ !$omp atomic hint(abs(-1)) write
+ x = 7
+
+ !$omp atomic hint(omp_sync_hint_uncontended + omp_sync_hint_uncontended + omp_sync_hint_speculative) write
+ x = 7
+end program
diff --git a/flang/test/Semantics/OpenMP/omp-critical-hint-clause.f90 b/flang/test/Semantics/OpenMP/omp-critical-hint-clause.f90
new file mode 100644
index 0000000000000..33088c6caf359
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/omp-critical-hint-clause.f90
@@ -0,0 +1,118 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+! Semantic checks on hint clauses, as they appear on critical construct
+
+program sample
+ use omp_lib
+ integer :: y
+ logical :: z
+ real :: k
+ integer :: p(1)
+
+ !$omp critical (name) hint(1)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(2)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp critical (name) hint(3)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(5)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp critical (name) hint(7)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp critical (name) hint(x)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(4)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(8)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_sync_hint_uncontended)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_lock_hint_speculative)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp critical (name) hint(omp_sync_hint_uncontended + omp_sync_hint)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_sync_hint_nonspeculative)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_sync_hint_none)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_sync_hint_uncontended + omp_lock_hint_speculative)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_lock_hint_nonspeculative + omp_lock_hint_uncontended)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_lock_hint_contended + omp_sync_hint_speculative)
+ y = 2
+ !$omp end critical (name)
+
+ !$omp critical (name) hint(omp_lock_hint_contended + omp_sync_hint_nonspeculative)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp critical (name) hint(omp_sync_hint_uncontended + omp_sync_hint_contended)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause value is not a valid OpenMP synchronization value
+ !$omp critical (name) hint(omp_sync_hint_nonspeculative + omp_lock_hint_speculative)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !$omp critical (name) hint(1.0)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Operands of + must be numeric; have LOGICAL(4) and INTEGER(4)
+ !$omp critical (name) hint(z + omp_sync_hint_nonspeculative)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp critical (name) hint(k + omp_sync_hint_speculative)
+ y = 2
+ !$omp end critical (name)
+
+ !ERROR: Hint clause must have non-negative constant integer expression
+ !ERROR: Must be a constant value
+ !$omp critical (name) hint(p(1) + omp_sync_hint_uncontended)
+ y = 2
+ !$omp end critical (name)
+end program
+
More information about the flang-commits
mailing list