Skip to content

Commit 71d763b

Browse files
committed
[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
1 parent 8fd56ea commit 71d763b

File tree

5 files changed

+215
-16
lines changed

5 files changed

+215
-16
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 101 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,22 @@ bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) {
170170
return false;
171171
}
172172

173+
void OmpStructureChecker::CheckMultipleOccurrence(
174+
semantics::UnorderedSymbolSet &listVars,
175+
const std::list<parser::Name> &nameList, const parser::CharBlock &item,
176+
const std::string &clauseName) {
177+
for (auto const &var : nameList) {
178+
if (llvm::is_contained(listVars, *(var.symbol))) {
179+
context_.Say(item,
180+
"List item '%s' present at multiple %s clauses"_err_en_US,
181+
var.ToString(), clauseName);
182+
}
183+
listVars.insert(*(var.symbol));
184+
}
185+
}
186+
173187
void OmpStructureChecker::CheckMultListItems() {
174188
semantics::UnorderedSymbolSet listVars;
175-
auto checkMultipleOcurrence = [&](const std::list<parser::Name> &nameList,
176-
const parser::CharBlock &item,
177-
const std::string &clauseName) {
178-
for (auto const &var : nameList) {
179-
if (llvm::is_contained(listVars, *(var.symbol))) {
180-
context_.Say(item,
181-
"List item '%s' present at multiple %s clauses"_err_en_US,
182-
var.ToString(), clauseName);
183-
}
184-
listVars.insert(*(var.symbol));
185-
}
186-
};
187189

188190
// Aligned clause
189191
auto alignedClauses{FindClauses(llvm::omp::Clause::OMPC_aligned)};
@@ -216,7 +218,8 @@ void OmpStructureChecker::CheckMultListItems() {
216218
}
217219
}
218220
}
219-
checkMultipleOcurrence(alignedNameList, itr->second->source, "ALIGNED");
221+
CheckMultipleOccurrence(
222+
listVars, alignedNameList, itr->second->source, "ALIGNED");
220223
}
221224

222225
// Nontemporal clause
@@ -226,7 +229,8 @@ void OmpStructureChecker::CheckMultListItems() {
226229
const auto &nontempClause{
227230
std::get<parser::OmpClause::Nontemporal>(itr->second->u)};
228231
const auto &nontempNameList{nontempClause.v};
229-
checkMultipleOcurrence(nontempNameList, itr->second->source, "NONTEMPORAL");
232+
CheckMultipleOccurrence(
233+
listVars, nontempNameList, itr->second->source, "NONTEMPORAL");
230234
}
231235
}
232236

@@ -2000,10 +2004,8 @@ CHECK_SIMPLE_CLAUSE(UnifiedSharedMemory, OMPC_unified_shared_memory)
20002004
CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform)
20012005
CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown)
20022006
CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied)
2003-
CHECK_SIMPLE_CLAUSE(UseDevicePtr, OMPC_use_device_ptr)
20042007
CHECK_SIMPLE_CLAUSE(UsesAllocators, OMPC_uses_allocators)
20052008
CHECK_SIMPLE_CLAUSE(Update, OMPC_update)
2006-
CHECK_SIMPLE_CLAUSE(UseDeviceAddr, OMPC_use_device_addr)
20072009
CHECK_SIMPLE_CLAUSE(Write, OMPC_write)
20082010
CHECK_SIMPLE_CLAUSE(Init, OMPC_init)
20092011
CHECK_SIMPLE_CLAUSE(Use, OMPC_use)
@@ -2618,6 +2620,89 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
26182620
currSymbols, llvm::omp::Clause::OMPC_copyin);
26192621
}
26202622

2623+
void OmpStructureChecker::CheckStructureElement(
2624+
const parser::OmpObjectList &ompObjectList,
2625+
const llvm::omp::Clause clause) {
2626+
for (const auto &ompObject : ompObjectList.v) {
2627+
common::visit(
2628+
common::visitors{
2629+
[&](const parser::Designator &designator) {
2630+
if (const auto *dataRef{
2631+
std::get_if<parser::DataRef>(&designator.u)}) {
2632+
if (parser::Unwrap<parser::StructureComponent>(ompObject)) {
2633+
context_.Say(GetContext().clauseSource,
2634+
"A variable that is part of another variable "
2635+
"(structure element) cannot appear on the %s "
2636+
"%s clause"_err_en_US,
2637+
ContextDirectiveAsFortran(),
2638+
parser::ToUpperCaseLetters(getClauseName(clause).str()));
2639+
}
2640+
}
2641+
},
2642+
[&](const parser::Name &name) {},
2643+
},
2644+
ompObject.u);
2645+
}
2646+
return;
2647+
}
2648+
2649+
void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
2650+
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_ptr);
2651+
CheckAllowed(llvm::omp::Clause::OMPC_use_device_ptr);
2652+
SymbolSourceMap currSymbols;
2653+
GetSymbolsInObjectList(x.v, currSymbols);
2654+
semantics::UnorderedSymbolSet listVars;
2655+
auto useDevicePtrClauses{FindClauses(llvm::omp::Clause::OMPC_use_device_ptr)};
2656+
for (auto itr = useDevicePtrClauses.first; itr != useDevicePtrClauses.second;
2657+
++itr) {
2658+
const auto &useDevicePtrClause{
2659+
std::get<parser::OmpClause::UseDevicePtr>(itr->second->u)};
2660+
const auto &useDevicePtrList{useDevicePtrClause.v};
2661+
std::list<parser::Name> useDevicePtrNameList;
2662+
for (const auto &ompObject : useDevicePtrList.v) {
2663+
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
2664+
if (name->symbol) {
2665+
if (!(IsBuiltinCPtr(*(name->symbol)))) {
2666+
context_.Say(itr->second->source,
2667+
"'%s' in USE_DEVICE_PTR clause must be of type C_PTR"_err_en_US,
2668+
name->ToString());
2669+
} else {
2670+
useDevicePtrNameList.push_back(*name);
2671+
}
2672+
}
2673+
}
2674+
}
2675+
CheckMultipleOccurrence(
2676+
listVars, useDevicePtrNameList, itr->second->source, "USE_DEVICE_PTR");
2677+
}
2678+
}
2679+
2680+
void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
2681+
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_addr);
2682+
CheckAllowed(llvm::omp::Clause::OMPC_use_device_addr);
2683+
SymbolSourceMap currSymbols;
2684+
GetSymbolsInObjectList(x.v, currSymbols);
2685+
semantics::UnorderedSymbolSet listVars;
2686+
auto useDeviceAddrClauses{
2687+
FindClauses(llvm::omp::Clause::OMPC_use_device_addr)};
2688+
for (auto itr = useDeviceAddrClauses.first;
2689+
itr != useDeviceAddrClauses.second; ++itr) {
2690+
const auto &useDeviceAddrClause{
2691+
std::get<parser::OmpClause::UseDeviceAddr>(itr->second->u)};
2692+
const auto &useDeviceAddrList{useDeviceAddrClause.v};
2693+
std::list<parser::Name> useDeviceAddrNameList;
2694+
for (const auto &ompObject : useDeviceAddrList.v) {
2695+
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
2696+
if (name->symbol) {
2697+
useDeviceAddrNameList.push_back(*name);
2698+
}
2699+
}
2700+
}
2701+
CheckMultipleOccurrence(listVars, useDeviceAddrNameList,
2702+
itr->second->source, "USE_DEVICE_ADDR");
2703+
}
2704+
}
2705+
26212706
llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) {
26222707
return llvm::omp::getOpenMPClauseName(clause);
26232708
}

flang/lib/Semantics/check-omp-structure.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,12 @@ class OmpStructureChecker
195195
}
196196

197197
private:
198+
void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
199+
const std::list<parser::Name> &nameList, const parser::CharBlock &item,
200+
const std::string &clauseName);
198201
void CheckMultListItems();
202+
void CheckStructureElement(const parser::OmpObjectList &ompObjectList,
203+
const llvm::omp::Clause clause);
199204
bool HasInvalidWorksharingNesting(
200205
const parser::CharBlock &, const OmpDirectiveSet &);
201206
bool IsCloselyNestedRegion(const OmpDirectiveSet &set);

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,18 @@ void OmpAttributeVisitor::ResolveOmpObject(
18291829
GetContext().directive)
18301830
.str()));
18311831
}
1832+
if ((GetContext().directive ==
1833+
llvm::omp::Directive::OMPD_target_data) &&
1834+
(((ompFlag == Symbol::Flag::OmpUseDevicePtr) &&
1835+
symbol->test(Symbol::Flag::OmpUseDeviceAddr)) ||
1836+
((ompFlag == Symbol::Flag::OmpUseDeviceAddr) &&
1837+
symbol->test(Symbol::Flag::OmpUseDevicePtr)))) {
1838+
context_.Say(designator.source,
1839+
"Variable '%s' may not "
1840+
"appear on both USE_DEVICE_PTR and USE_DEVICE_ADDR "
1841+
"clauses on a TARGET DATA construct"_err_en_US,
1842+
symbol->name());
1843+
}
18321844
}
18331845
} else {
18341846
// Array sections to be changed to substrings as needed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
2+
! OpenMP Version 5.0
3+
! 2.10.1 use_device_ptr clause
4+
! List item in USE_DEVICE_ADDR clause must not be structure element.
5+
! Same list item can not be present multiple times or in multipe
6+
! USE_DEVICE_ADDR clauses.
7+
8+
subroutine omp_target_data
9+
integer :: a(1024)
10+
integer, target :: b(1024)
11+
type my_type
12+
integer :: my_b(1024)
13+
end type my_type
14+
15+
type(my_type) :: my_var
16+
a = 1
17+
18+
!ERROR: A variable that is part of another variable (structure element) cannot appear on the TARGET DATA USE_DEVICE_ADDR clause
19+
!$omp target data map(tofrom: a) use_device_addr(my_var%my_b)
20+
my_var%my_b = a
21+
!$omp end target data
22+
23+
!ERROR: List item 'b' present at multiple USE_DEVICE_ADDR clauses
24+
!$omp target data map(tofrom: a) use_device_addr(b,b)
25+
b = a
26+
!$omp end target data
27+
28+
!ERROR: List item 'b' present at multiple USE_DEVICE_ADDR clauses
29+
!$omp target data map(tofrom: a) use_device_addr(b) use_device_addr(b)
30+
b = a
31+
!$omp end target data
32+
33+
end subroutine omp_target_data
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
2+
! OpenMP Version 5.0
3+
! 2.10.1 use_device_ptr clause
4+
! List item in USE_DEVICE_PTR clause must not be structure element.
5+
! List item in USE_DEVICE_PTR clause must be of type C_PTR.
6+
! List items that appear in a use_device_ptr clause can not appear in
7+
! use_device_addr clause.
8+
! Same list item can not be present multiple times or in multipe
9+
! USE_DEVICE_PTR clauses.
10+
11+
subroutine omp_target_data
12+
use iso_c_binding
13+
integer :: a(1024)
14+
type(C_PTR) :: b
15+
integer, pointer :: arrayB
16+
type my_type
17+
type(C_PTR) :: my_cptr
18+
end type my_type
19+
20+
type(my_type) :: my_var
21+
a = 1
22+
23+
!ERROR: A variable that is part of another variable (structure element) cannot appear on the TARGET DATA USE_DEVICE_PTR clause
24+
!$omp target data map(tofrom: a, arrayB) use_device_ptr(my_var%my_cptr)
25+
allocate(arrayB)
26+
call c_f_pointer(my_var%my_cptr, arrayB)
27+
a = arrayB
28+
!$omp end target data
29+
30+
!ERROR: 'a' in USE_DEVICE_PTR clause must be of type C_PTR
31+
!$omp target data map(tofrom: a) use_device_ptr(a)
32+
a = 2
33+
!$omp end target data
34+
35+
!ERROR: List item 'b' present at multiple USE_DEVICE_PTR clauses
36+
!$omp target data map(tofrom: a, arrayB) use_device_ptr(b) use_device_ptr(b)
37+
allocate(arrayB)
38+
call c_f_pointer(b, arrayB)
39+
a = arrayB
40+
!$omp end target data
41+
42+
!ERROR: List item 'b' present at multiple USE_DEVICE_PTR clauses
43+
!$omp target data map(tofrom: a, arrayB) use_device_ptr(b,b)
44+
allocate(arrayB)
45+
call c_f_pointer(b, arrayB)
46+
a = arrayB
47+
!$omp end target data
48+
49+
!ERROR: Variable 'b' may not appear on both USE_DEVICE_PTR and USE_DEVICE_ADDR clauses on a TARGET DATA construct
50+
!$omp target data map(tofrom: a, arrayB) use_device_addr(b) use_device_ptr(b)
51+
allocate(arrayB)
52+
call c_f_pointer(b, arrayB)
53+
a = arrayB
54+
!$omp end target data
55+
56+
!ERROR: Variable 'b' may not appear on both USE_DEVICE_PTR and USE_DEVICE_ADDR clauses on a TARGET DATA construct
57+
!$omp target data map(tofrom: a, arrayB) use_device_ptr(b) use_device_addr(b)
58+
allocate(arrayB)
59+
call c_f_pointer(b, arrayB)
60+
a = arrayB
61+
!$omp end target data
62+
63+
end subroutine omp_target_data
64+

0 commit comments

Comments
 (0)