[flang-commits] [flang] 71d763b - [OpenMP] [Semantics] [Flang] Adding more semantic checks for USE_DEVICE_PTR and USE_DEVICE_ADDR clauses.

Raghu Maddhipatla via flang-commits flang-commits at lists.llvm.org
Thu Aug 3 22:19:41 PDT 2023


Author: Raghu Maddhipatla
Date: 2023-08-04T00:19:36-05:00
New Revision: 71d763b88d6107ab6d9d47ed6382c4fefa514cc4

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

LOG: [OpenMP] [Semantics] [Flang] Adding more semantic checks for USE_DEVICE_PTR and USE_DEVICE_ADDR clauses.

The following restrictions for USE_DEVICE_PTR and USE_DEVICE_ADDR clauses on OMP TARGET DATA directive are implemented in this patch.

  - A list item may not be specified more than once in use_device_ptr clauses that appear on the directive.
  - A list item may not be specified more than once in use_device_addr clauses that appear on the directive.
  - A list item may not be specified in both a use_device_addr clause and a use_device_ptr clause on the directive.
  - A list item that appears in a use_device_ptr or use_device_addr clause must not be a structure element.
  - A list item that appears in a use_device_ptr must be of type C_PTR.

Reviewed By: kiranchandramohan

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

Added: 
    flang/test/Semantics/OpenMP/use_device_addr1.f90
    flang/test/Semantics/OpenMP/use_device_ptr1.f90

Modified: 
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/lib/Semantics/resolve-directives.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index b26f3e23f9ec73..fb67cb41953c73 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -170,20 +170,22 @@ bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) {
   return false;
 }
 
+void OmpStructureChecker::CheckMultipleOccurrence(
+    semantics::UnorderedSymbolSet &listVars,
+    const std::list<parser::Name> &nameList, const parser::CharBlock &item,
+    const std::string &clauseName) {
+  for (auto const &var : nameList) {
+    if (llvm::is_contained(listVars, *(var.symbol))) {
+      context_.Say(item,
+          "List item '%s' present at multiple %s clauses"_err_en_US,
+          var.ToString(), clauseName);
+    }
+    listVars.insert(*(var.symbol));
+  }
+}
+
 void OmpStructureChecker::CheckMultListItems() {
   semantics::UnorderedSymbolSet listVars;
-  auto checkMultipleOcurrence = [&](const std::list<parser::Name> &nameList,
-                                    const parser::CharBlock &item,
-                                    const std::string &clauseName) {
-    for (auto const &var : nameList) {
-      if (llvm::is_contained(listVars, *(var.symbol))) {
-        context_.Say(item,
-            "List item '%s' present at multiple %s clauses"_err_en_US,
-            var.ToString(), clauseName);
-      }
-      listVars.insert(*(var.symbol));
-    }
-  };
 
   // Aligned clause
   auto alignedClauses{FindClauses(llvm::omp::Clause::OMPC_aligned)};
@@ -216,7 +218,8 @@ void OmpStructureChecker::CheckMultListItems() {
         }
       }
     }
-    checkMultipleOcurrence(alignedNameList, itr->second->source, "ALIGNED");
+    CheckMultipleOccurrence(
+        listVars, alignedNameList, itr->second->source, "ALIGNED");
   }
 
   // Nontemporal clause
@@ -226,7 +229,8 @@ void OmpStructureChecker::CheckMultListItems() {
     const auto &nontempClause{
         std::get<parser::OmpClause::Nontemporal>(itr->second->u)};
     const auto &nontempNameList{nontempClause.v};
-    checkMultipleOcurrence(nontempNameList, itr->second->source, "NONTEMPORAL");
+    CheckMultipleOccurrence(
+        listVars, nontempNameList, itr->second->source, "NONTEMPORAL");
   }
 }
 
@@ -2000,10 +2004,8 @@ CHECK_SIMPLE_CLAUSE(UnifiedSharedMemory, OMPC_unified_shared_memory)
 CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform)
 CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown)
 CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied)
-CHECK_SIMPLE_CLAUSE(UseDevicePtr, OMPC_use_device_ptr)
 CHECK_SIMPLE_CLAUSE(UsesAllocators, OMPC_uses_allocators)
 CHECK_SIMPLE_CLAUSE(Update, OMPC_update)
-CHECK_SIMPLE_CLAUSE(UseDeviceAddr, OMPC_use_device_addr)
 CHECK_SIMPLE_CLAUSE(Write, OMPC_write)
 CHECK_SIMPLE_CLAUSE(Init, OMPC_init)
 CHECK_SIMPLE_CLAUSE(Use, OMPC_use)
@@ -2618,6 +2620,89 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
       currSymbols, llvm::omp::Clause::OMPC_copyin);
 }
 
+void OmpStructureChecker::CheckStructureElement(
+    const parser::OmpObjectList &ompObjectList,
+    const llvm::omp::Clause clause) {
+  for (const auto &ompObject : ompObjectList.v) {
+    common::visit(
+        common::visitors{
+            [&](const parser::Designator &designator) {
+              if (const auto *dataRef{
+                      std::get_if<parser::DataRef>(&designator.u)}) {
+                if (parser::Unwrap<parser::StructureComponent>(ompObject)) {
+                  context_.Say(GetContext().clauseSource,
+                      "A variable that is part of another variable "
+                      "(structure element) cannot appear on the %s "
+                      "%s clause"_err_en_US,
+                      ContextDirectiveAsFortran(),
+                      parser::ToUpperCaseLetters(getClauseName(clause).str()));
+                }
+              }
+            },
+            [&](const parser::Name &name) {},
+        },
+        ompObject.u);
+  }
+  return;
+}
+
+void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
+  CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_ptr);
+  CheckAllowed(llvm::omp::Clause::OMPC_use_device_ptr);
+  SymbolSourceMap currSymbols;
+  GetSymbolsInObjectList(x.v, currSymbols);
+  semantics::UnorderedSymbolSet listVars;
+  auto useDevicePtrClauses{FindClauses(llvm::omp::Clause::OMPC_use_device_ptr)};
+  for (auto itr = useDevicePtrClauses.first; itr != useDevicePtrClauses.second;
+       ++itr) {
+    const auto &useDevicePtrClause{
+        std::get<parser::OmpClause::UseDevicePtr>(itr->second->u)};
+    const auto &useDevicePtrList{useDevicePtrClause.v};
+    std::list<parser::Name> useDevicePtrNameList;
+    for (const auto &ompObject : useDevicePtrList.v) {
+      if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
+        if (name->symbol) {
+          if (!(IsBuiltinCPtr(*(name->symbol)))) {
+            context_.Say(itr->second->source,
+                "'%s' in USE_DEVICE_PTR clause must be of type C_PTR"_err_en_US,
+                name->ToString());
+          } else {
+            useDevicePtrNameList.push_back(*name);
+          }
+        }
+      }
+    }
+    CheckMultipleOccurrence(
+        listVars, useDevicePtrNameList, itr->second->source, "USE_DEVICE_PTR");
+  }
+}
+
+void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
+  CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_addr);
+  CheckAllowed(llvm::omp::Clause::OMPC_use_device_addr);
+  SymbolSourceMap currSymbols;
+  GetSymbolsInObjectList(x.v, currSymbols);
+  semantics::UnorderedSymbolSet listVars;
+  auto useDeviceAddrClauses{
+      FindClauses(llvm::omp::Clause::OMPC_use_device_addr)};
+  for (auto itr = useDeviceAddrClauses.first;
+       itr != useDeviceAddrClauses.second; ++itr) {
+    const auto &useDeviceAddrClause{
+        std::get<parser::OmpClause::UseDeviceAddr>(itr->second->u)};
+    const auto &useDeviceAddrList{useDeviceAddrClause.v};
+    std::list<parser::Name> useDeviceAddrNameList;
+    for (const auto &ompObject : useDeviceAddrList.v) {
+      if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
+        if (name->symbol) {
+          useDeviceAddrNameList.push_back(*name);
+        }
+      }
+    }
+    CheckMultipleOccurrence(listVars, useDeviceAddrNameList,
+        itr->second->source, "USE_DEVICE_ADDR");
+  }
+}
+
 llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) {
   return llvm::omp::getOpenMPClauseName(clause);
 }

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 195b0c2326f548..d41d60755edbc1 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -195,7 +195,12 @@ class OmpStructureChecker
   }
 
 private:
+  void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
+      const std::list<parser::Name> &nameList, const parser::CharBlock &item,
+      const std::string &clauseName);
   void CheckMultListItems();
+  void CheckStructureElement(const parser::OmpObjectList &ompObjectList,
+      const llvm::omp::Clause clause);
   bool HasInvalidWorksharingNesting(
       const parser::CharBlock &, const OmpDirectiveSet &);
   bool IsCloselyNestedRegion(const OmpDirectiveSet &set);

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 747f1e414eb21f..25c398ce1e7036 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1829,6 +1829,18 @@ 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());
+                }
               }
             } else {
               // Array sections to be changed to substrings as needed

diff  --git a/flang/test/Semantics/OpenMP/use_device_addr1.f90 b/flang/test/Semantics/OpenMP/use_device_addr1.f90
new file mode 100644
index 00000000000000..867e324b68ad95
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/use_device_addr1.f90
@@ -0,0 +1,33 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+! OpenMP Version 5.0
+! 2.10.1 use_device_ptr clause
+! List item in USE_DEVICE_ADDR clause must not be structure element.
+! Same list item can not be present multiple times or in multipe
+! USE_DEVICE_ADDR clauses.
+
+subroutine omp_target_data
+   integer :: a(1024)
+   integer, target :: b(1024)
+   type my_type
+    integer :: my_b(1024)
+   end type my_type
+
+   type(my_type) :: my_var
+   a = 1
+
+   !ERROR: A variable that is part of another variable (structure element) cannot appear on the TARGET DATA USE_DEVICE_ADDR clause
+   !$omp target data map(tofrom: a) use_device_addr(my_var%my_b)
+      my_var%my_b = a
+   !$omp end target data
+
+   !ERROR: List item 'b' present at multiple USE_DEVICE_ADDR clauses
+   !$omp target data map(tofrom: a) use_device_addr(b,b)
+      b = a
+   !$omp end target data
+
+   !ERROR: List item 'b' present at multiple USE_DEVICE_ADDR clauses
+   !$omp target data map(tofrom: a) use_device_addr(b) use_device_addr(b)
+      b = a
+   !$omp end target data
+
+end subroutine omp_target_data

diff  --git a/flang/test/Semantics/OpenMP/use_device_ptr1.f90 b/flang/test/Semantics/OpenMP/use_device_ptr1.f90
new file mode 100644
index 00000000000000..af89698a5c5a99
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/use_device_ptr1.f90
@@ -0,0 +1,64 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+! OpenMP Version 5.0
+! 2.10.1 use_device_ptr clause
+! List item in USE_DEVICE_PTR clause must not be structure element.
+! List item in USE_DEVICE_PTR clause must be of type C_PTR.
+! List items that appear in a use_device_ptr clause can not appear in
+! use_device_addr clause.
+! Same list item can not be present multiple times or in multipe
+! USE_DEVICE_PTR clauses.
+
+subroutine omp_target_data
+   use iso_c_binding
+   integer :: a(1024)
+   type(C_PTR) :: b
+   integer, pointer :: arrayB
+   type my_type
+    type(C_PTR) :: my_cptr
+   end type my_type
+
+   type(my_type) :: my_var
+   a = 1
+
+   !ERROR: A variable that is part of another variable (structure element) cannot appear on the TARGET DATA USE_DEVICE_PTR clause
+   !$omp target data map(tofrom: a, arrayB) use_device_ptr(my_var%my_cptr)
+      allocate(arrayB)
+      call c_f_pointer(my_var%my_cptr, arrayB)
+      a = arrayB
+   !$omp end target data
+
+   !ERROR: 'a' in USE_DEVICE_PTR clause must be of type C_PTR
+   !$omp target data map(tofrom: a) use_device_ptr(a)
+      a = 2
+   !$omp end target data
+
+   !ERROR: List item 'b' present at multiple USE_DEVICE_PTR clauses
+   !$omp target data map(tofrom: a, arrayB) use_device_ptr(b) use_device_ptr(b)
+      allocate(arrayB)
+      call c_f_pointer(b, arrayB)
+      a = arrayB
+   !$omp end target data
+
+   !ERROR: List item 'b' present at multiple USE_DEVICE_PTR clauses
+   !$omp target data map(tofrom: a, arrayB) use_device_ptr(b,b)
+      allocate(arrayB)
+      call c_f_pointer(b, arrayB)
+      a = arrayB
+   !$omp end target data
+
+   !ERROR: Variable 'b' may not appear on both USE_DEVICE_PTR and USE_DEVICE_ADDR clauses on a TARGET DATA construct
+   !$omp target data map(tofrom: a, arrayB) use_device_addr(b) use_device_ptr(b)
+      allocate(arrayB)
+      call c_f_pointer(b, arrayB)
+      a = arrayB
+   !$omp end target data
+
+   !ERROR: Variable 'b' may not appear on both USE_DEVICE_PTR and USE_DEVICE_ADDR clauses on a TARGET DATA construct
+   !$omp target data map(tofrom: a, arrayB) use_device_ptr(b) use_device_addr(b)
+      allocate(arrayB)
+      call c_f_pointer(b, arrayB)
+      a = arrayB
+   !$omp end target data
+
+end subroutine omp_target_data
+


        


More information about the flang-commits mailing list