Skip to content

Commit 86fa018

Browse files
authored
[Flang][OpenMP] Initial defaultmap(none) implementation (llvm#166715)
This PR adds defaultmap(none) behaviour to Flang, where we emit a semantic error if variables within the target construct do not have an associated data attribute. Similar to the way default behaves, as described by the OpenMP specification.
1 parent b7ceda3 commit 86fa018

File tree

5 files changed

+191
-16
lines changed

5 files changed

+191
-16
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,9 +1008,7 @@ getImplicitMapTypeAndKind(fir::FirOpBuilder &firOpBuilder,
10081008
mlir::omp::VariableCaptureKind::ByRef);
10091009
break;
10101010
case DefMap::ImplicitBehavior::Firstprivate:
1011-
case DefMap::ImplicitBehavior::None:
1012-
TODO(loc, "Firstprivate and None are currently unsupported defaultmap "
1013-
"behaviour");
1011+
TODO(loc, "Firstprivate is currently unsupported defaultmap behaviour");
10141012
break;
10151013
case DefMap::ImplicitBehavior::From:
10161014
return std::make_pair(mapFlag |= mlir::omp::ClauseMapFlags::from,
@@ -1032,8 +1030,9 @@ getImplicitMapTypeAndKind(fir::FirOpBuilder &firOpBuilder,
10321030
mlir::omp::VariableCaptureKind::ByRef);
10331031
break;
10341032
case DefMap::ImplicitBehavior::Default:
1033+
case DefMap::ImplicitBehavior::None:
10351034
llvm_unreachable(
1036-
"Implicit None Behaviour Should Have Been Handled Earlier");
1035+
"Implicit None and Default behaviour should have been handled earlier");
10371036
break;
10381037
}
10391038

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2965,6 +2965,67 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) {
29652965
}
29662966
}
29672967

2968+
static bool IsOpenMPPointer(const Symbol &symbol) {
2969+
if (IsPointer(symbol) || IsBuiltinCPtr(symbol))
2970+
return true;
2971+
return false;
2972+
}
2973+
2974+
static bool IsOpenMPAggregate(const Symbol &symbol) {
2975+
if (IsAllocatable(symbol) || IsOpenMPPointer(symbol))
2976+
return false;
2977+
2978+
const auto *type{symbol.GetType()};
2979+
// OpenMP categorizes Fortran characters as aggregates.
2980+
if (type->category() == Fortran::semantics::DeclTypeSpec::Category::Character)
2981+
return true;
2982+
2983+
if (const auto *det{symbol.GetUltimate()
2984+
.detailsIf<Fortran::semantics::ObjectEntityDetails>()})
2985+
if (det->IsArray())
2986+
return true;
2987+
2988+
if (type->AsDerived())
2989+
return true;
2990+
2991+
if (IsDeferredShape(symbol) || IsAssumedRank(symbol) ||
2992+
IsAssumedShape(symbol))
2993+
return true;
2994+
return false;
2995+
}
2996+
2997+
static bool IsOpenMPScalar(const Symbol &symbol) {
2998+
if (IsOpenMPAggregate(symbol) || IsOpenMPPointer(symbol) ||
2999+
IsAllocatable(symbol))
3000+
return false;
3001+
const auto *type{symbol.GetType()};
3002+
if ((!symbol.GetShape() || symbol.GetShape()->empty()) &&
3003+
(type->category() ==
3004+
Fortran::semantics::DeclTypeSpec::Category::Numeric ||
3005+
type->category() ==
3006+
Fortran::semantics::DeclTypeSpec::Category::Logical))
3007+
return true;
3008+
return false;
3009+
}
3010+
3011+
static bool DefaultMapCategoryMatchesSymbol(
3012+
parser::OmpVariableCategory::Value category, const Symbol &symbol) {
3013+
using VarCat = parser::OmpVariableCategory::Value;
3014+
switch (category) {
3015+
case VarCat::Scalar:
3016+
return IsOpenMPScalar(symbol);
3017+
case VarCat::Allocatable:
3018+
return IsAllocatable(symbol);
3019+
case VarCat::Aggregate:
3020+
return IsOpenMPAggregate(symbol);
3021+
case VarCat::Pointer:
3022+
return IsOpenMPPointer(symbol);
3023+
case VarCat::All:
3024+
return true;
3025+
}
3026+
return false;
3027+
}
3028+
29683029
// For OpenMP constructs, check all the data-refs within the constructs
29693030
// and adjust the symbol for each Name if necessary
29703031
void OmpAttributeVisitor::Post(const parser::Name &name) {
@@ -3000,6 +3061,36 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
30003061
}
30013062
}
30023063

3064+
// TODO: handle case where default and defaultmap are present on the same
3065+
// construct and conflict, defaultmap should supersede default if they
3066+
// conflict.
3067+
if (!GetContext().defaultMap.empty()) {
3068+
// Checked before implicit data sharing attributes as this rule ignores
3069+
// them and expects explicit predetermined/specified attributes to be in
3070+
// place for the types specified.
3071+
if (Symbol * found{currScope().FindSymbol(name.source)}) {
3072+
// If the variable has declare target applied to it (enter or link) it
3073+
// is exempt from defaultmap(none) restrictions
3074+
if (!symbol->GetUltimate().test(Symbol::Flag::OmpDeclareTarget)) {
3075+
auto &dMap = GetContext().defaultMap;
3076+
for (auto defaults : dMap) {
3077+
if (defaults.second ==
3078+
parser::OmpDefaultmapClause::ImplicitBehavior::None) {
3079+
if (DefaultMapCategoryMatchesSymbol(defaults.first, *found)) {
3080+
if (!IsObjectWithDSA(*symbol)) {
3081+
context_.Say(name.source,
3082+
"The DEFAULTMAP(NONE) clause requires that '%s' must be "
3083+
"listed in a "
3084+
"data-sharing attribute, data-mapping attribute, or is_device_ptr clause"_err_en_US,
3085+
symbol->name());
3086+
}
3087+
}
3088+
}
3089+
}
3090+
}
3091+
}
3092+
}
3093+
30033094
if (Symbol * found{currScope().FindSymbol(name.source)}) {
30043095
if (found->GetUltimate().test(semantics::Symbol::Flag::OmpThreadprivate))
30053096
return;

flang/test/Lower/OpenMP/Todo/defaultmap-clause-firstprivate.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ subroutine f00
66
! NOTE: This is implemented for scalars as it is the default behaviour, so we utilise
77
! a different data type.
88
integer, allocatable :: i
9-
!CHECK: not yet implemented: Firstprivate and None are currently unsupported defaultmap behaviour
9+
!CHECK: not yet implemented: Firstprivate is currently unsupported defaultmap behaviour
1010
!$omp target defaultmap(firstprivate)
1111
i = 10
1212
!$omp end target

flang/test/Lower/OpenMP/Todo/defaultmap-clause-none.f90

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51
2+
3+
subroutine defaultmap_all_none_no_errors
4+
implicit none
5+
real :: array(10)
6+
integer, pointer :: ptr(:)
7+
real, allocatable :: alloca
8+
integer :: index
9+
10+
!$omp target defaultmap(none) map(to: index, alloca) map(tofrom: array, ptr)
11+
do index = 1, 10
12+
ptr(index) = array(index) + alloca
13+
end do
14+
!$omp end target
15+
end subroutine defaultmap_all_none_no_errors
16+
17+
subroutine defaultmap_all_none
18+
implicit none
19+
real :: array(10)
20+
integer, pointer :: ptr(:)
21+
real, allocatable :: alloca
22+
integer :: index
23+
!$omp target defaultmap(none)
24+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
25+
do index = 1, 10
26+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'ptr' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
27+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
28+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'array' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
29+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
30+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'alloca' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
31+
ptr(index) = array(index) + alloca
32+
end do
33+
!$omp end target
34+
end subroutine defaultmap_all_none
35+
36+
subroutine defaultmap_scalar_none
37+
implicit none
38+
real :: array(10)
39+
integer, pointer :: ptr(:)
40+
real, allocatable :: alloca
41+
integer :: index
42+
43+
!$omp target defaultmap(none: scalar)
44+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
45+
do index = 1, 10
46+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
47+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'index' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
48+
ptr(index) = array(index) + alloca
49+
end do
50+
!$omp end target
51+
end subroutine defaultmap_scalar_none
52+
53+
subroutine defaultmap_pointer_none
54+
implicit none
55+
real :: array(10)
56+
integer, pointer :: ptr(:)
57+
real, allocatable :: alloca
58+
integer :: index
59+
60+
!$omp target defaultmap(none: pointer)
61+
do index = 1, 10
62+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'ptr' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
63+
ptr(index) = array(index) + alloca
64+
end do
65+
!$omp end target
66+
end subroutine defaultmap_pointer_none
67+
68+
subroutine defaultmap_allocatable_none
69+
implicit none
70+
real :: array(10)
71+
integer, pointer :: ptr(:)
72+
real, allocatable :: alloca
73+
integer :: index
74+
75+
!$omp target defaultmap(none: allocatable)
76+
do index = 1, 10
77+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'alloca' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
78+
ptr(index) = array(index) + alloca
79+
end do
80+
!$omp end target
81+
end subroutine defaultmap_allocatable_none
82+
83+
subroutine defaultmap_aggregate_none
84+
implicit none
85+
real :: array(10)
86+
integer, pointer :: ptr(:)
87+
real, allocatable :: alloca
88+
integer :: index
89+
90+
!$omp target defaultmap(none: aggregate)
91+
do index = 1, 10
92+
!ERROR: The DEFAULTMAP(NONE) clause requires that 'array' must be listed in a data-sharing attribute, data-mapping attribute, or is_device_ptr clause
93+
ptr(index) = array(index) + alloca
94+
end do
95+
!$omp end target
96+
end subroutine defaultmap_aggregate_none

0 commit comments

Comments
 (0)