[flang-commits] [flang] [Flang][OpenMP] Add some semantic checks for Linear clause (PR #111354)

Thirumalai Shaktivel via flang-commits flang-commits at lists.llvm.org
Tue Oct 8 22:43:31 PDT 2024


https://github.com/Thirumalai-Shaktivel updated https://github.com/llvm/llvm-project/pull/111354

>From b88ca31ee40ffebb50ad837ea737eddda69480ab Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Mon, 7 Oct 2024 10:15:21 +0000
Subject: [PATCH 1/4] [LLVM-Flang][OpenMP] Add some semantic checks for Linear
 clause based on the OpenMP 5.2 restrictions

---
 flang/lib/Semantics/check-omp-structure.cpp | 109 +++++++++++++++++++-
 1 file changed, 105 insertions(+), 4 deletions(-)

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 5ef504aa72326e..9fe9701fe449d3 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -303,6 +303,30 @@ void OmpStructureChecker::CheckMultListItems() {
     CheckMultipleOccurrence(
         listVars, nontempNameList, itr->second->source, "NONTEMPORAL");
   }
+
+  // Linear clause
+  auto linearClauses{FindClauses(llvm::omp::Clause::OMPC_linear)};
+  for (auto itr{linearClauses.first}; itr != linearClauses.second; ++itr) {
+    const auto &linearClause{
+        std::get<parser::OmpClause::Linear>(itr->second->u)};
+    std::list<parser::Name> nameList;
+    common::visit(
+        common::visitors{
+            [&](const parser::OmpLinearClause::WithoutModifier
+                    &withoutModifier) {
+              for (const auto &name : withoutModifier.names) {
+                nameList.push_back(name);
+              }
+            },
+            [&](const parser::OmpLinearClause::WithModifier &withModifier) {
+              for (const auto &name : withModifier.names) {
+                nameList.push_back(name);
+              }
+            },
+        },
+        linearClause.v.u);
+    CheckMultipleOccurrence(listVars, nameList, itr->second->source, "LINEAR");
+  }
 }
 
 bool OmpStructureChecker::HasInvalidWorksharingNesting(
@@ -2256,11 +2280,12 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
         }
       }
     }
-    // Sema checks related to presence of multiple list items within the same
-    // clause
-    CheckMultListItems();
   } // SIMD
 
+  // Semantic checks related to presence of multiple list items within the same
+  // clause
+  CheckMultListItems();
+
   // 2.7.3 Single Construct Restriction
   if (GetContext().directive == llvm::omp::Directive::OMPD_end_single) {
     CheckNotAllowedIfClause(
@@ -2975,16 +3000,92 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
 void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_linear);
 
+  parser::CharBlock source{GetContext().clauseSource};
   // 2.7 Loop Construct Restriction
   if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
           .test(GetContext().directive)) {
     if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(x.v.u)) {
-      context_.Say(GetContext().clauseSource,
+      context_.Say(source,
           "A modifier may not be specified in a LINEAR clause "
           "on the %s directive"_err_en_US,
           ContextDirectiveAsFortran());
+      return;
     }
   }
+
+  auto checkForValidLinearClause = [&](const parser::Name &name, bool is_ref) {
+    parser::CharBlock source{GetContext().clauseSource};
+    std::string listItemName{name.ToString()};
+    if (!is_ref && !name.symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
+      context_.Say(source,
+          "The list item `%s` specified with other than linear-modifier `REF`"
+          " must be of type INTEGER"_err_en_US,
+          listItemName);
+    }
+    if (GetContext().directive == llvm::omp::Directive::OMPD_declare_simd &&
+        !IsDummy(*name.symbol)) {
+      context_.Say(source,
+          "The list item `%s` must be a dummy argument"_err_en_US,
+          listItemName);
+    }
+    if (IsPointer(*name.symbol) ||
+        name.symbol->test(Symbol::Flag::CrayPointer)) {
+      context_.Say(source,
+          "The list item `%s` in a LINEAR clause must not be Cray Pointer "
+          "or a variable with POINTER attribute"_err_en_US,
+          listItemName);
+    }
+    if (FindCommonBlockContaining(*name.symbol)) {
+      context_.Say(source,
+          "'%s' is a common block name and must not appear in an "
+          "LINEAR clause"_err_en_US,
+          listItemName);
+    }
+  };
+
+  // OpenMP 5.2: Linear clause Restrictions
+  common::visit(
+      common::visitors{
+          [&](const parser::OmpLinearClause::WithoutModifier &withoutModifier) {
+            for (const auto &name : withoutModifier.names) {
+              if (name.symbol) {
+                checkForValidLinearClause(name, false);
+              }
+            }
+          },
+          [&](const parser::OmpLinearClause::WithModifier &withModifier) {
+            for (const auto &name : withModifier.names) {
+              if (name.symbol) {
+                checkForValidLinearClause(name,
+                    (withModifier.modifier.v ==
+                        parser::OmpLinearModifier::Type::Ref));
+                std::string listItemName{name.ToString()};
+                if (withModifier.modifier.v !=
+                        parser::OmpLinearModifier::Type::Val &&
+                    IsDummy(*name.symbol) && IsValue(*name.symbol)) {
+                  context_.Say(source,
+                      "The list item `%s` specified with the linear-modifier "
+                      "`REF` or `UVAL` must be a dummy argument without "
+                      "`VALUE` attribute"_err_en_US,
+                      listItemName);
+                }
+                if (withModifier.modifier.v ==
+                        parser::OmpLinearModifier::Type::Ref &&
+                    !(IsAllocatable(*name.symbol) ||
+                        IsAssumedShape(*name.symbol) ||
+                        IsPolymorphic(*name.symbol))) {
+                  context_.Say(source,
+                      "The list item `%s` specified with the linear-modifier "
+                      "`REF` must be polymorphic variable, assumed-shape "
+                      "array, "
+                      "or a variable with the `ALLOCATABLE` attribute"_err_en_US,
+                      listItemName);
+                }
+              }
+            }
+          },
+      },
+      x.v.u);
 }
 
 void OmpStructureChecker::CheckAllowedMapTypes(

>From eee003dc6ca384cf199a57d1b5146f37299f8b30 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Mon, 7 Oct 2024 10:15:49 +0000
Subject: [PATCH 2/4] [LLVM-Flang][OpenMP] Skip Linear clause semantic check if
 ordered clause with (n) is specified

---
 flang/lib/Semantics/check-omp-structure.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 9fe9701fe449d3..aa3171b3124b52 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3013,6 +3013,15 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
     }
   }
 
+  // OpenMP 5.2: Ordered clause restriction
+  if (const auto *clause{
+          FindClause(GetContext(), llvm::omp::Clause::OMPC_ordered)}) {
+    const auto &orderedClause{std::get<parser::OmpClause::Ordered>(clause->u)};
+    if (orderedClause.v) {
+      return;
+    }
+  }
+
   auto checkForValidLinearClause = [&](const parser::Name &name, bool is_ref) {
     parser::CharBlock source{GetContext().clauseSource};
     std::string listItemName{name.ToString()};

>From bdb5b0f4e14f06c5aa15336c6e4cf985c6b3c905 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Mon, 7 Oct 2024 10:16:36 +0000
Subject: [PATCH 3/4] [Test] Add a test and update a check

---
 .../OpenMP/declarative-directive.f90          |  1 +
 .../test/Semantics/OpenMP/linear-clause01.f90 | 45 +++++++++++++++++++
 2 files changed, 46 insertions(+)
 create mode 100644 flang/test/Semantics/OpenMP/linear-clause01.f90

diff --git a/flang/test/Semantics/OpenMP/declarative-directive.f90 b/flang/test/Semantics/OpenMP/declarative-directive.f90
index 8d6762b87adb95..17dc50b70e5421 100644
--- a/flang/test/Semantics/OpenMP/declarative-directive.f90
+++ b/flang/test/Semantics/OpenMP/declarative-directive.f90
@@ -23,6 +23,7 @@ end subroutine requires_2
 
 subroutine declare_simd_1(a, b)
   real(8), intent(inout) :: a, b
+  !ERROR: 'a' in ALIGNED clause must be of type C_PTR, POINTER or ALLOCATABLE
   !$omp declare simd(declare_simd_1) aligned(a)
   a = 3.14 + b
 end subroutine declare_simd_1
diff --git a/flang/test/Semantics/OpenMP/linear-clause01.f90 b/flang/test/Semantics/OpenMP/linear-clause01.f90
new file mode 100644
index 00000000000000..654aa07f5bd403
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/linear-clause01.f90
@@ -0,0 +1,45 @@
+! REQUIRES: openmp_runtime
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags
+! OpenMP Version 5.2
+! Various checks for the linear clause
+! 5.4.6 `linear` Clause
+
+! Case 1
+subroutine linear_clause_01(arg)
+    integer, intent(in) :: arg(:)
+    !ERROR: A modifier may not be specified in a LINEAR clause on the DO directive
+    !$omp do linear(uval(arg))
+    do i = 1, 5
+        print *, arg(i)
+    end do
+end subroutine linear_clause_01
+
+! Case 2
+subroutine linear_clause_02(arg_01, arg_02)
+    !ERROR: The list item `arg_01` specified with other than linear-modifier `REF` must be of type INTEGER
+    !$omp declare simd linear(val(arg_01))
+    real, intent(in) :: arg_01(:)
+
+    !ERROR: The list item `arg_02` specified with the linear-modifier `REF` or `UVAL` must be a dummy argument without `VALUE` attribute
+    !$omp declare simd linear(uval(arg_02))
+    integer, value, intent(in) :: arg_02
+
+    !ERROR: The list item `var` must be a dummy argument
+    !ERROR: The list item `var` in a LINEAR clause must not be Cray Pointer or a variable with POINTER attribute
+    !$omp declare simd linear(uval(var))
+    integer, pointer :: var
+end subroutine linear_clause_02
+
+! Case 3
+subroutine linear_clause_03(arg)
+    integer, intent(in) :: arg
+    !ERROR: The list item `arg` specified with the linear-modifier `REF` must be polymorphic variable, assumed-shape array, or a variable with the `ALLOCATABLE` attribute
+    !ERROR: List item 'arg' present at multiple LINEAR clauses
+    !$omp declare simd linear(ref(arg)) linear(arg)
+
+    integer :: i
+    common /cc/ i
+    !ERROR: The list item `i` must be a dummy argument
+    !ERROR: 'i' is a common block name and must not appear in an LINEAR clause
+    !$omp declare simd linear(i)
+end subroutine linear_clause_03

>From 599b31f2c01671bfca30b93932d052a2d42fb8f9 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Wed, 9 Oct 2024 05:42:43 +0000
Subject: [PATCH 4/4] [Test] Fix a test to be valid

OpenMP 5.2 restriction: Each list item must have C_PTR or Cray pointer type or have the POINTER or ALLOCATABLE attribute.
---
 flang/test/Examples/omp-declarative-directive.f90 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/test/Examples/omp-declarative-directive.f90 b/flang/test/Examples/omp-declarative-directive.f90
index 632ebcec17885b..4a9ad9142bb187 100644
--- a/flang/test/Examples/omp-declarative-directive.f90
+++ b/flang/test/Examples/omp-declarative-directive.f90
@@ -7,7 +7,7 @@
 ! 2.8.2 declare-simd
 
 subroutine declare_simd_1(a, b)
-  real(8), intent(inout) :: a, b
+  real(8), intent(inout), allocatable :: a, b
   !$omp declare simd(declare_simd_1) aligned(a)
   a = 3.14 + b
 end subroutine declare_simd_1



More information about the flang-commits mailing list