[flang-commits] [flang] 6d1c183 - [Flang] [OpenMP] [Semantics] Add missing semantic check for MAP clause.

Raghu Maddhipatla via flang-commits flang-commits at lists.llvm.org
Thu Sep 7 13:42:30 PDT 2023


Author: Raghu Maddhipatla
Date: 2023-09-07T15:42:25-05:00
New Revision: 6d1c183c6f8be717e466f6c55f74729d178c8ee2

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

LOG: [Flang] [OpenMP] [Semantics] Add missing semantic check for MAP clause.

Added support for following semantic check for MAP clause.
  - A list item cannot appear in both a map clause and a data-sharing attribute clause on the same target construct.

Reviewed By: NimishMishra

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

Added: 
    flang/test/Semantics/OpenMP/target01.f90
    flang/test/Semantics/OpenMP/target02.f90

Modified: 
    flang/include/flang/Semantics/symbol.h
    flang/lib/Semantics/resolve-directives.cpp
    flang/lib/Semantics/symbol.cpp
    flang/test/Semantics/OpenMP/firstprivate01.f90
    flang/test/Semantics/OpenMP/symbol08.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 1ba489fe21a7227..7280a4eaa5fca57 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -643,8 +643,8 @@ class Symbol {
       // OpenMP data-sharing attribute
       OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
       // OpenMP data-mapping attribute
-      OmpMapTo, OmpMapFrom, OmpMapAlloc, OmpMapRelease, OmpMapDelete,
-      OmpUseDevicePtr, OmpUseDeviceAddr,
+      OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapAlloc, OmpMapRelease,
+      OmpMapDelete, OmpUseDevicePtr, OmpUseDeviceAddr,
       // OpenMP data-copying attribute
       OmpCopyIn, OmpCopyPrivate,
       // OpenMP miscellaneous flags
@@ -674,6 +674,7 @@ class Symbol {
   void set_offset(std::size_t offset) { offset_ = offset; }
   // Give the symbol a name with a 
diff erent source location but same chars.
   void ReplaceName(const SourceName &);
+  std::string OmpFlagToClauseName(Flag ompFlag);
 
   // Does symbol have this type of details?
   template <typename D> bool has() const {

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 84f00ef82755ef9..38beae33f40e95a 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -529,6 +529,34 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
   void Post(const parser::EorLabel &eorLabel) { CheckSourceLabel(eorLabel.v); }
 
   void Post(const parser::OmpMapClause &x) {
+    Symbol::Flag ompFlag = Symbol::Flag::OmpMapToFrom;
+    if (const auto &maptype{std::get<std::optional<parser::OmpMapType>>(x.t)}) {
+      using Type = parser::OmpMapType::Type;
+      const Type &type{std::get<Type>(maptype->t)};
+      switch (type) {
+      case Type::To:
+        ompFlag = Symbol::Flag::OmpMapTo;
+        break;
+      case Type::From:
+        ompFlag = Symbol::Flag::OmpMapFrom;
+        break;
+      case Type::Tofrom:
+        ompFlag = Symbol::Flag::OmpMapToFrom;
+        break;
+      case Type::Alloc:
+        ompFlag = Symbol::Flag::OmpMapAlloc;
+        break;
+      case Type::Release:
+        ompFlag = Symbol::Flag::OmpMapRelease;
+        break;
+      case Type::Delete:
+        ompFlag = Symbol::Flag::OmpMapDelete;
+        break;
+      default:
+        assert(false && "Unsupported map-type");
+        break;
+      }
+    }
     const auto &ompObjList{std::get<parser::OmpObjectList>(x.t)};
     for (const auto &ompObj : ompObjList.v) {
       common::visit(
@@ -536,6 +564,10 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
               [&](const parser::Designator &designator) {
                 if (const auto *name{
                         semantics::getDesignatorNameIfDataRef(designator)}) {
+                  if (name->symbol) {
+                    name->symbol->set(ompFlag);
+                    AddToContextObjectWithDSA(*name->symbol, ompFlag);
+                  }
                   if (name->symbol &&
                       semantics::IsAssumedSizeArray(*name->symbol)) {
                     context_.Say(designator.source,
@@ -1908,6 +1940,27 @@ void OmpAttributeVisitor::ResolveOmpObject(
             if (const auto *name{
                     semantics::getDesignatorNameIfDataRef(designator)}) {
               if (auto *symbol{ResolveOmp(*name, ompFlag, currScope())}) {
+                auto checkExclusivelists =
+                    [&](const Symbol *symbol1, Symbol::Flag firstOmpFlag,
+                        Symbol *symbol2, Symbol::Flag secondOmpFlag) {
+                      if ((symbol1->test(firstOmpFlag) &&
+                              symbol2->test(secondOmpFlag)) ||
+                          (symbol1->test(secondOmpFlag) &&
+                              symbol2->test(firstOmpFlag))) {
+                        context_.Say(designator.source,
+                            "Variable '%s' may not "
+                            "appear on both %s and %s "
+                            "clauses on a %s construct"_err_en_US,
+                            symbol2->name(),
+                            const_cast<Symbol *>(symbol1)->OmpFlagToClauseName(
+                                firstOmpFlag),
+                            symbol2->OmpFlagToClauseName(secondOmpFlag),
+                            parser::ToUpperCaseLetters(
+                                llvm::omp::getOpenMPDirectiveName(
+                                    GetContext().directive)
+                                    .str()));
+                      }
+                    };
                 if (dataCopyingAttributeFlags.test(ompFlag)) {
                   CheckDataCopyingClause(*name, *symbol, ompFlag);
                 } else {
@@ -1943,28 +1996,37 @@ void OmpAttributeVisitor::ResolveOmpObject(
                               GetContext().directive)
                               .str()));
                 }
-                if ((GetContext().directive ==
-                        llvm::omp::Directive::OMPD_target_data) &&
-                    (((ompFlag == Symbol::Flag::OmpUseDevicePtr) &&
-                         symbol->test(Symbol::Flag::OmpUseDeviceAddr)) ||
-                        ((ompFlag == Symbol::Flag::OmpUseDeviceAddr) &&
-                            symbol->test(Symbol::Flag::OmpUseDevicePtr)))) {
-                  context_.Say(designator.source,
-                      "Variable '%s' may not "
-                      "appear on both USE_DEVICE_PTR and USE_DEVICE_ADDR "
-                      "clauses on a TARGET DATA construct"_err_en_US,
-                      symbol->name());
+                if (GetContext().directive ==
+                    llvm::omp::Directive::OMPD_target_data) {
+                  checkExclusivelists(symbol, Symbol::Flag::OmpUseDevicePtr,
+                      symbol, Symbol::Flag::OmpUseDeviceAddr);
                 }
-                if (llvm::omp::allDistributeSet.test(GetContext().directive) &&
-                    (((ompFlag == Symbol::Flag::OmpFirstPrivate) &&
-                         symbol->test(Symbol::Flag::OmpLastPrivate)) ||
-                        ((ompFlag == Symbol::Flag::OmpLastPrivate) &&
-                            symbol->test(Symbol::Flag::OmpFirstPrivate)))) {
-                  context_.Say(designator.source,
-                      "Variable '%s' may not "
-                      "appear on both FIRSTPRIVATE and LASTPRIVATE "
-                      "clauses on a DISTRIBUTE construct"_err_en_US,
-                      symbol->name());
+                if (llvm::omp::allDistributeSet.test(GetContext().directive)) {
+                  checkExclusivelists(symbol, Symbol::Flag::OmpFirstPrivate,
+                      symbol, Symbol::Flag::OmpLastPrivate);
+                }
+                if (llvm::omp::allTargetSet.test(GetContext().directive)) {
+                  const auto *hostAssocSym{symbol};
+                  if (const auto *details{
+                          symbol->detailsIf<HostAssocDetails>()}) {
+                    hostAssocSym = &details->symbol();
+                  }
+                  Symbol::Flag dataMappingAttributeFlags[] = {
+                      Symbol::Flag::OmpMapTo, Symbol::Flag::OmpMapFrom,
+                      Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapAlloc,
+                      Symbol::Flag::OmpMapRelease, Symbol::Flag::OmpMapDelete};
+
+                  Symbol::Flag dataSharingAttributeFlags[] = {
+                      Symbol::Flag::OmpPrivate, Symbol::Flag::OmpFirstPrivate,
+                      Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpShared,
+                      Symbol::Flag::OmpLinear};
+
+                  for (Symbol::Flag ompFlag1 : dataMappingAttributeFlags) {
+                    for (Symbol::Flag ompFlag2 : dataSharingAttributeFlags) {
+                      checkExclusivelists(
+                          hostAssocSym, ompFlag1, symbol, ompFlag2);
+                    }
+                  }
                 }
               }
             } else {

diff  --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index 211b7f80b2a6767..2e14b2e8a19559c 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -757,6 +757,51 @@ bool GenericKind::Is(GenericKind::OtherKind x) const {
   return y && *y == x;
 }
 
+std::string Symbol::OmpFlagToClauseName(Symbol::Flag ompFlag) {
+  std::string clauseName;
+  switch (ompFlag) {
+  case Symbol::Flag::OmpShared:
+    clauseName = "SHARED";
+    break;
+  case Symbol::Flag::OmpPrivate:
+    clauseName = "PRIVATE";
+    break;
+  case Symbol::Flag::OmpLinear:
+    clauseName = "LINEAR";
+    break;
+  case Symbol::Flag::OmpFirstPrivate:
+    clauseName = "FIRSTPRIVATE";
+    break;
+  case Symbol::Flag::OmpLastPrivate:
+    clauseName = "LASTPRIVATE";
+    break;
+  case Symbol::Flag::OmpMapTo:
+  case Symbol::Flag::OmpMapFrom:
+  case Symbol::Flag::OmpMapToFrom:
+  case Symbol::Flag::OmpMapAlloc:
+  case Symbol::Flag::OmpMapRelease:
+  case Symbol::Flag::OmpMapDelete:
+    clauseName = "MAP";
+    break;
+  case Symbol::Flag::OmpUseDevicePtr:
+    clauseName = "USE_DEVICE_PTR";
+    break;
+  case Symbol::Flag::OmpUseDeviceAddr:
+    clauseName = "USE_DEVICE_ADDR";
+    break;
+  case Symbol::Flag::OmpCopyIn:
+    clauseName = "COPYIN";
+    break;
+  case Symbol::Flag::OmpCopyPrivate:
+    clauseName = "COPYPRIVATE";
+    break;
+  default:
+    clauseName = "";
+    break;
+  }
+  return clauseName;
+}
+
 bool SymbolOffsetCompare::operator()(
     const SymbolRef &x, const SymbolRef &y) const {
   const Symbol *xCommon{FindCommonBlockContaining(*x)};

diff  --git a/flang/test/Semantics/OpenMP/firstprivate01.f90 b/flang/test/Semantics/OpenMP/firstprivate01.f90
index 166c91165a78de2..0c576a9f07a4251 100644
--- a/flang/test/Semantics/OpenMP/firstprivate01.f90
+++ b/flang/test/Semantics/OpenMP/firstprivate01.f90
@@ -38,27 +38,27 @@ program omp_firstprivate
     a(i) = a(i) + b(i) - i
   end do
   !$omp end teams distribute
-  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct
+  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a TEAMS DISTRIBUTE construct
   !$omp teams distribute firstprivate(a,b) lastprivate(b)
   do i = 1, 10
     a(i) = a(i) + b(i) - i
   end do
   !$omp end teams distribute
-  !ERROR: Variable 'a' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct
-  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct
+  !ERROR: Variable 'a' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a TEAMS DISTRIBUTE construct
+  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a TEAMS DISTRIBUTE construct
   !$omp teams distribute firstprivate(a,b) lastprivate(a,b)
   do i = 1, 10
     a(i) = a(i) + b(i) - i
   end do
   !$omp end teams distribute
-  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct
+  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a TEAMS DISTRIBUTE construct
   !$omp teams distribute lastprivate(a,b) firstprivate(b)
   do i = 1, 10
     a(i) = a(i) + b(i) - i
   end do
   !$omp end teams distribute
-  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct
-  !ERROR: Variable 'a' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct
+  !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a TEAMS DISTRIBUTE construct
+  !ERROR: Variable 'a' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a TEAMS DISTRIBUTE construct
   !$omp teams distribute lastprivate(a,b) firstprivate(b,a)
   do i = 1, 10
     a(i) = a(i) + b(i) - i

diff  --git a/flang/test/Semantics/OpenMP/symbol08.f90 b/flang/test/Semantics/OpenMP/symbol08.f90
index 5c5aa4f24dd2e44..b80c94a9f189ae7 100644
--- a/flang/test/Semantics/OpenMP/symbol08.f90
+++ b/flang/test/Semantics/OpenMP/symbol08.f90
@@ -106,8 +106,8 @@ end subroutine test_taskloop
 ! Rule a); OpenMP 4.5 Examples teams.2.f90
 ! TODO: reduction; data-mapping attributes
 !DEF: /dotprod (Subroutine) Subprogram
-!DEF: /dotprod/b ObjectEntity REAL(4)
-!DEF: /dotprod/c ObjectEntity REAL(4)
+!DEF: /dotprod/b (OmpMapTo) ObjectEntity REAL(4)
+!DEF: /dotprod/c (OmpMapTo) ObjectEntity REAL(4)
 !DEF: /dotprod/n ObjectEntity INTEGER(4)
 !DEF: /dotprod/block_size ObjectEntity INTEGER(4)
 !DEF: /dotprod/num_teams ObjectEntity INTEGER(4)
@@ -119,7 +119,7 @@ subroutine dotprod (b, c, n, block_size, num_teams, block_threads)
  !REF: /dotprod/b
  !REF: /dotprod/n
  !REF: /dotprod/c
- !DEF: /dotprod/sum ObjectEntity REAL(4)
+ !DEF: /dotprod/sum (OmpMapToFrom) ObjectEntity REAL(4)
  real b(n), c(n), sum
  !REF: /dotprod/block_size
  !REF: /dotprod/num_teams

diff  --git a/flang/test/Semantics/OpenMP/target01.f90 b/flang/test/Semantics/OpenMP/target01.f90
new file mode 100644
index 000000000000000..8418381740250b0
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/target01.f90
@@ -0,0 +1,10 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+! OpenMP Version 4.5
+
+integer :: x
+!ERROR: Variable 'x' may not appear on both MAP and PRIVATE clauses on a TARGET construct
+!$omp target map(x) private(x)
+x = x + 1
+!$omp end target
+
+end

diff  --git a/flang/test/Semantics/OpenMP/target02.f90 b/flang/test/Semantics/OpenMP/target02.f90
new file mode 100644
index 000000000000000..06ce1c0875cc975
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/target02.f90
@@ -0,0 +1,17 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+! OpenMP Version 4.5
+
+program p
+integer :: y
+!ERROR: Variable 'y' may not appear on both MAP and FIRSTPRIVATE clauses on a TARGET construct
+!$omp target map(y) firstprivate(y)
+y = y + 1
+!$omp end target
+!ERROR: Variable 'y' may not appear on both MAP and FIRSTPRIVATE clauses on a TARGET SIMD construct
+!$omp target simd map(y) firstprivate(y)
+do i=1,1
+  y = y + 1
+end do
+!$omp end target simd
+
+end program p


        


More information about the flang-commits mailing list