[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