[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