[flang-commits] [flang] f2622a1 - [flang][OpenMP] Add semantic check to allow only loop iteration variables in a `linear` clause within `distribute` construct.

Arnamoy Bhattacharyya via flang-commits flang-commits at lists.llvm.org
Fri Jun 4 14:31:11 PDT 2021


Author: Arnamoy Bhattacharyya
Date: 2021-06-04T17:32:25-04:00
New Revision: f2622a150adea31290daee0d04bf385d387fbc04

URL: https://github.com/llvm/llvm-project/commit/f2622a150adea31290daee0d04bf385d387fbc04
DIFF: https://github.com/llvm/llvm-project/commit/f2622a150adea31290daee0d04bf385d387fbc04.diff

LOG: [flang][OpenMP] Add semantic check to allow only loop iteration variables in a `linear` clause within `distribute` construct.

Implement the following semantic check:

"A list item may not appear in a linear clause, unless it is the loop iteration variable."

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D100224

Added: 
    flang/test/Semantics/omp-linear-iter.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 89107097e560..29a0c7926714 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -297,6 +297,10 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
       llvm::omp::teamSet.test(GetContextParent().directive)) {
     HasInvalidTeamsNesting(beginDir.v, beginDir.source);
   }
+  if ((beginDir.v == llvm::omp::Directive::OMPD_distribute_parallel_do_simd) ||
+      (beginDir.v == llvm::omp::Directive::OMPD_distribute_simd)) {
+    CheckDistLinear(x);
+  }
 }
 const parser::Name OmpStructureChecker::GetLoopIndex(
     const parser::DoConstruct *x) {
@@ -465,6 +469,77 @@ void OmpStructureChecker::CheckCycleConstraints(
   parser::Walk(x, ompCycleChecker);
 }
 
+void OmpStructureChecker::CheckDistLinear(
+    const parser::OpenMPLoopConstruct &x) {
+
+  const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
+  const auto &clauses{std::get<parser::OmpClauseList>(beginLoopDir.t)};
+
+  semantics::UnorderedSymbolSet indexVars;
+
+  // Collect symbols of all the variables from linear clauses
+  for (const auto &clause : clauses.v) {
+    if (const auto *linearClause{
+            std::get_if<parser::OmpClause::Linear>(&clause.u)}) {
+
+      std::list<parser::Name> values;
+      // Get the variant type
+      if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(
+              linearClause->v.u)) {
+        const auto &withM{
+            std::get<parser::OmpLinearClause::WithModifier>(linearClause->v.u)};
+        values = withM.names;
+      } else {
+        const auto &withOutM{std::get<parser::OmpLinearClause::WithoutModifier>(
+            linearClause->v.u)};
+        values = withOutM.names;
+      }
+      for (auto const &v : values) {
+        indexVars.insert(*(v.symbol));
+      }
+    }
+  }
+
+  if (!indexVars.empty()) {
+    // Get collapse level, if given, to find which loops are "associated."
+    std::int64_t collapseVal{GetOrdCollapseLevel(x)};
+    // Include the top loop if no collapse is specified
+    if (collapseVal == 0)
+      collapseVal = 1;
+
+    // Match the loop index variables with the collected symbols from linear
+    // clauses.
+    if (const auto &loopConstruct{
+            std::get<std::optional<parser::DoConstruct>>(x.t)}) {
+      for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) {
+        if (loop->IsDoNormal()) {
+          const parser::Name &itrVal{GetLoopIndex(loop)};
+          if (itrVal.symbol) {
+            // Remove the symbol from the collcted set
+            indexVars.erase(*(itrVal.symbol));
+          }
+          collapseVal--;
+          if (collapseVal == 0)
+            break;
+        }
+        // Get the next DoConstruct if block is not empty.
+        const auto &block{std::get<parser::Block>(loop->t)};
+        const auto it{block.begin()};
+        loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it)
+                                 : nullptr;
+      }
+    }
+
+    // Show error for the remaining variables
+    for (auto var : indexVars) {
+      const Symbol &root{GetAssociationRoot(var)};
+      context_.Say(parser::FindSourceLocation(x),
+          "Variable '%s' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`"_err_en_US,
+          root.name());
+    }
+  }
+}
+
 void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &) {
   if (llvm::omp::simdSet.test(GetContext().directive)) {
     ExitSIMDNest();

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 009c0850380e..9ca69eb14c33 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -219,6 +219,7 @@ class OmpStructureChecker
   void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
   void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
   void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
+  void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
   void CheckSIMDNest(const parser::OpenMPConstruct &x);
   std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
   void CheckIfDoOrderedClause(const parser::OmpBlockDirective &blkDirectiv);

diff  --git a/flang/test/Semantics/omp-linear-iter.f90 b/flang/test/Semantics/omp-linear-iter.f90
new file mode 100644
index 000000000000..c8932d32a55f
--- /dev/null
+++ b/flang/test/Semantics/omp-linear-iter.f90
@@ -0,0 +1,85 @@
+! RUN: %S/test_errors.sh %s %t %flang -fopenmp
+! OpenMP Version 4.5
+! Various checks with the ordered construct
+
+SUBROUTINE LINEAR_GOOD(N)
+  INTEGER N, i, j, a, b(10)
+  !$omp target
+  !$omp teams
+  !$omp distribute parallel do simd linear(i) 
+  do i = 1, N
+     a = 3.14
+  enddo
+  !$omp end distribute parallel do simd
+  !$omp end teams
+  !$omp end target
+END SUBROUTINE LINEAR_GOOD
+
+SUBROUTINE LINEAR_BAD(N)
+  INTEGER N, i, j, a, b(10)
+
+  !$omp target
+  !$omp teams
+  !ERROR: Variable 'j' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`
+  !$omp distribute parallel do simd linear(j) 
+  do i = 1, N
+      a = 3.14
+  enddo
+  !$omp end distribute parallel do simd
+  !$omp end teams
+  !$omp end target
+
+  !$omp target
+  !$omp teams
+  !ERROR: Variable 'j' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`
+  !ERROR: Variable 'b' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`
+  !$omp distribute parallel do simd linear(j) linear(b)
+  do i = 1, N
+     a = 3.14
+  enddo
+  !$omp end distribute parallel do simd
+  !$omp end teams
+  !$omp end target 
+
+  !$omp target
+  !$omp teams
+  !ERROR: Variable 'j' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`
+  !ERROR: Variable 'b' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`
+  !$omp distribute parallel do simd linear(j, b)
+  do i = 1, N
+     a = 3.14
+  enddo
+  !$omp end distribute parallel do simd
+  !$omp end teams
+  !$omp end target 
+
+  !ERROR: `DISTRIBUTE` region has to be strictly nested inside `TEAMS` region.
+  !ERROR: Variable 'j' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`
+  !$omp distribute simd linear(i,j)
+   do i = 1, N
+      do j = 1, N
+         a = 3.14
+      enddo
+   enddo
+   !$omp end distribute simd
+
+   !ERROR: `DISTRIBUTE` region has to be strictly nested inside `TEAMS` region.
+   !ERROR: Variable 'j' not allowed in `LINEAR` clause, only loop iterator can be specified in `LINEAR` clause of a construct combined with `DISTRIBUTE`
+   !$omp distribute simd linear(i,j) collapse(1)
+   do i = 1, N
+      do j = 1, N
+         a = 3.14
+      enddo
+   enddo
+   !$omp end distribute simd
+
+   !ERROR: `DISTRIBUTE` region has to be strictly nested inside `TEAMS` region.
+   !$omp distribute simd linear(i,j) collapse(2)
+   do i = 1, N
+      do j = 1, N
+         a = 3.14
+      enddo
+   enddo
+   !$omp end distribute simd
+
+END SUBROUTINE LINEAR_BAD


        


More information about the flang-commits mailing list