Skip to content

Commit 54f183e

Browse files
committed
[OpenACC] Prototype OpenMP extension: hold map type modifier
The `hold` map type modifier is an original OpenMP extension for the sake of supporting OpenACC's two reference counters for tracking device allocations. In future commits, `hold` will be used where OpenACC's structured reference counter is required (for data and compute constructs), and it will be omitted where OpenACC's dynamic reference counter is required (for enter data and exit data directives). Currently, `hold` is not thoroughly tested outside of translations from OpenACC to OpenMP, so it is not yet recommended for general use in OpenMP code. This commit introduces some testing at the OpenMP level, but missing testing includes at least Clang codegen and `PTR_AND_OBJ` map entries (see todos in commit).
1 parent e659264 commit 54f183e

File tree

15 files changed

+564
-44
lines changed

15 files changed

+564
-44
lines changed

clang/include/clang/AST/OpenMPClause.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5395,7 +5395,7 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
53955395
OpenMPMapModifierKind MapTypeModifiers[NumberOfOMPMapClauseModifiers] = {
53965396
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
53975397
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
5398-
OMPC_MAP_MODIFIER_unknown};
5398+
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
53995399

54005400
/// Location of map-type-modifiers for the 'map' clause.
54015401
SourceLocation MapTypeModifiersLoc[NumberOfOMPMapClauseModifiers];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10139,6 +10139,8 @@ def err_omp_map_shared_storage : Error<
1013910139
"variable already marked as mapped in current construct">;
1014010140
def err_omp_invalid_map_type_for_directive : Error<
1014110141
"%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">;
10142+
def err_omp_invalid_map_type_modifier_for_directive : Error<
10143+
"map type modifier '%0' is not allowed for '#pragma omp %1'">;
1014210144
def err_omp_no_clause_for_directive : Error<
1014310145
"expected at least one %0 clause for '#pragma omp %1'">;
1014410146
def err_omp_threadprivate_in_clause : Error<

clang/include/clang/Basic/OpenMPKinds.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ OPENMP_MAP_MODIFIER_KIND(present)
126126
// TODO: Currently, it is not well tested outside of translations from OpenACC
127127
// to OpenMP, so it is not yet recommended for general use in OpenMP code.
128128
OPENMP_MAP_MODIFIER_KIND(no_alloc)
129+
// This is an OpenMP extension for the sake of OpenACC support.
130+
// TODO: Currently, it is not well tested outside of translations from OpenACC
131+
// to OpenMP, so it is not yet recommended for general use in OpenMP code.
132+
OPENMP_MAP_MODIFIER_KIND(hold)
129133

130134
// Modifiers for 'to' or 'from' clause.
131135
OPENMP_MOTION_MODIFIER_KIND(mapper)

clang/lib/CodeGen/CGOpenMPRuntime.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7012,6 +7012,16 @@ class MappableExprsHandler {
70127012
// OpenACC to OpenMP, so it is not yet recommended for general use in
70137013
// OpenMP code.
70147014
OMP_MAP_NO_ALLOC = 0x2000,
7015+
// Increment and decrement a separate reference counter so that the data
7016+
// cannot be deallocated within the associated region. Thus, this flag is
7017+
// intended to be used on target and target data directives. It is not
7018+
// intended to be used on target enter/exit data directives because they are
7019+
// inherently dynamic not structured.
7020+
// This is an OpenMP extension for the sake of OpenACC support.
7021+
// TODO: Currently, it is not well tested outside of translations from
7022+
// OpenACC to OpenMP, so it is not yet recommended for general use in
7023+
// OpenMP code.
7024+
OMP_MAP_HOLD = 0x4000,
70157025
/// The 16 MSBs of the flags indicate whether the entry is member of some
70167026
/// struct/class.
70177027
OMP_MAP_MEMBER_OF = 0xffff000000000000,
@@ -7295,6 +7305,8 @@ class MappableExprsHandler {
72957305
if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_no_alloc)
72967306
!= MapModifiers.end())
72977307
Bits |= OMP_MAP_NO_ALLOC;
7308+
if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_hold) != MapModifiers.end())
7309+
Bits |= OMP_MAP_HOLD;
72987310
if (llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present)
72997311
!= MotionModifiers.end())
73007312
Bits |= OMP_MAP_PRESENT;

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3127,7 +3127,8 @@ bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
31273127
if (TypeModifier == OMPC_MAP_MODIFIER_always ||
31283128
TypeModifier == OMPC_MAP_MODIFIER_close ||
31293129
TypeModifier == OMPC_MAP_MODIFIER_present ||
3130-
TypeModifier == OMPC_MAP_MODIFIER_no_alloc) {
3130+
TypeModifier == OMPC_MAP_MODIFIER_no_alloc ||
3131+
TypeModifier == OMPC_MAP_MODIFIER_hold) {
31313132
Data.MapTypeModifiers.push_back(TypeModifier);
31323133
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
31333134
ConsumeToken();

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17460,6 +17460,10 @@ static void checkMappableExpressionList(
1746017460
bool UpdateUMIt = false;
1746117461
Expr *UnresolvedMapper = nullptr;
1746217462

17463+
bool HasHoldModifier =
17464+
Modifiers.end() !=
17465+
std::find(Modifiers.begin(), Modifiers.end(), OMPC_MAP_MODIFIER_hold);
17466+
1746317467
// Keep track of the mappable components and base declarations in this clause.
1746417468
// Each entry in the list is going to have a list of components associated. We
1746517469
// record each set of the components so that we can build the clause later on.
@@ -17659,6 +17663,19 @@ static void checkMappableExpressionList(
1765917663
continue;
1766017664
}
1766117665

17666+
// The 'hold' modifier is specifically intended to be used on a target or
17667+
// target data directive to prevent data from being deallocated during the
17668+
// associated region. It is not useful on a target enter data or target
17669+
// exit data directive because they are inherently dynamic not structured.
17670+
if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
17671+
HasHoldModifier) {
17672+
SemaRef.Diag(StartLoc,
17673+
diag::err_omp_invalid_map_type_modifier_for_directive)
17674+
<< getOpenMPSimpleClauseTypeName(OMPC_map, OMPC_MAP_MODIFIER_hold)
17675+
<< getOpenMPDirectiveName(DKind);
17676+
continue;
17677+
}
17678+
1766217679
// target, target data
1766317680
// OpenMP 5.0 [2.12.2, Restrictions, p. 163]
1766417681
// OpenMP 5.0 [2.12.5, Restrictions, p. 174]
@@ -17734,7 +17751,7 @@ OMPClause *Sema::ActOnOpenMPMapClause(
1773417751
OpenMPMapModifierKind Modifiers[] = {
1773517752
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
1773617753
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
17737-
OMPC_MAP_MODIFIER_unknown};
17754+
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
1773817755
SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
1773917756

1774017757
// Process map-type-modifiers, flag errors for duplicate modifiers.

clang/test/OpenMP/target_enter_data_map_messages.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,10 @@ int main(int argc, char **argv) {
2525
#pragma omp target enter data map(release: r) // expected-error {{map type 'release' is not allowed for '#pragma omp target enter data'}}
2626
#pragma omp target enter data map(delete: r) // expected-error {{map type 'delete' is not allowed for '#pragma omp target enter data'}}
2727

28+
// expected-error@+1 {{map type modifier 'hold' is not allowed for '#pragma omp target enter data'}}
29+
#pragma omp target enter data map(hold, alloc: r)
30+
// expected-error@+1 {{map type modifier 'hold' is not allowed for '#pragma omp target enter data'}}
31+
#pragma omp target enter data map(hold, to: r)
32+
2833
return 0;
2934
}

clang/test/OpenMP/target_exit_data_map_messages.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,12 @@ int main(int argc, char **argv) {
1818
#pragma omp target exit data map(always, alloc: r) // expected-error {{map type 'alloc' is not allowed for '#pragma omp target exit data'}}
1919
#pragma omp target exit data map(to: r) // expected-error {{map type 'to' is not allowed for '#pragma omp target exit data'}}
2020

21+
// expected-error@+1 {{map type modifier 'hold' is not allowed for '#pragma omp target exit data'}}
22+
#pragma omp target exit data map(hold, from: r)
23+
// expected-error@+1 {{map type modifier 'hold' is not allowed for '#pragma omp target exit data'}}
24+
#pragma omp target exit data map(hold, release: r)
25+
// expected-error@+1 {{map type modifier 'hold' is not allowed for '#pragma omp target exit data'}}
26+
#pragma omp target exit data map(hold, delete: r)
27+
2128
return 0;
2229
}

openmp/libomptarget/include/omptarget.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ enum tgt_map_type {
5656
// TODO: Currently, it is not well tested outside of translations from OpenACC
5757
// to OpenMP, so it is not yet recommended for general use in OpenMP code.
5858
OMP_TGT_MAPTYPE_NO_ALLOC = 0x2000,
59+
// use a separate reference counter so that the data cannot be deallocated
60+
// within the structured region
61+
// This is an OpenMP extension for the sake of OpenACC support.
62+
// TODO: Currently, it is not well tested outside of translations from OpenACC
63+
// to OpenMP, so it is not yet recommended for general use in OpenMP code.
64+
OMP_TGT_MAPTYPE_HOLD = 0x4000,
5965
// member of struct, member given by [16 MSBs] - 1
6066
OMP_TGT_MAPTYPE_MEMBER_OF = 0xffff000000000000
6167
};

openmp/libomptarget/src/api.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ EXTERN int omp_target_is_present(void *ptr, int device_num) {
112112
DeviceTy& Device = Devices[device_num];
113113
bool IsLast; // not used
114114
bool IsHostPtr;
115-
void *TgtPtr = Device.getTgtPtrBegin(ptr, 0, IsLast, false, IsHostPtr);
115+
void *TgtPtr = Device.getTgtPtrBegin(ptr, 0, IsLast, /*UpdateRefCount=*/false,
116+
/*UseHoldRefCount=*/false, IsHostPtr);
116117
int rc = (TgtPtr != NULL);
117118
// Under unified memory the host pointer can be returned by the
118119
// getTgtPtrBegin() function which means that there is no device

openmp/libomptarget/src/device.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ int DeviceTy::associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size) {
4747
(uintptr_t) HstPtrBegin /*HstPtrBegin*/,
4848
(uintptr_t) HstPtrBegin + Size /*HstPtrEnd*/,
4949
(uintptr_t) TgtPtrBegin /*TgtPtrBegin*/,
50+
false /*UseHoldRefCount*/,
5051
true /*IsRefCountINF*/);
5152

5253
DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD ", HstEnd="
@@ -163,7 +164,8 @@ void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
163164
int64_t Size, bool &IsNew, bool &IsHostPtr,
164165
bool IsImplicit, bool UpdateRefCount,
165166
bool HasCloseModifier, bool HasPresentModifier,
166-
bool HasNoAllocModifier) {
167+
bool HasNoAllocModifier,
168+
bool HasHoldModifier) {
167169
void *rc = NULL;
168170
IsHostPtr = false;
169171
IsNew = false;
@@ -180,7 +182,7 @@ void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
180182
IsNew = false;
181183

182184
if (UpdateRefCount)
183-
HT.incRefCount();
185+
HT.incRefCount(HasHoldModifier);
184186

185187
uintptr_t tp = HT.TgtPtrBegin + ((uintptr_t)HstPtrBegin - HT.HstPtrBegin);
186188
DP("Mapping exists%s with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD ", "
@@ -270,7 +272,8 @@ void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
270272
DPxPTR((uintptr_t)HstPtrBegin + Size), DPxPTR(tp));
271273
HostDataToTargetMap.emplace(
272274
HostDataToTargetTy((uintptr_t)HstPtrBase, (uintptr_t)HstPtrBegin,
273-
(uintptr_t)HstPtrBegin + Size, tp));
275+
(uintptr_t)HstPtrBegin + Size, tp, HasHoldModifier,
276+
/*IsINF=*/false));
274277
rc = (void *)tp;
275278
}
276279

@@ -282,8 +285,8 @@ void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
282285
// Return the target pointer begin (where the data will be moved).
283286
// Decrement the reference counter if called from targetDataEnd.
284287
void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
285-
bool UpdateRefCount, bool &IsHostPtr,
286-
bool MustContain) {
288+
bool UpdateRefCount, bool UseHoldRefCount,
289+
bool &IsHostPtr, bool MustContain) {
287290
void *rc = NULL;
288291
IsHostPtr = false;
289292
IsLast = false;
@@ -293,10 +296,10 @@ void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
293296
if (lr.Flags.IsContained ||
294297
(!MustContain && (lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter))) {
295298
auto &HT = *lr.Entry;
296-
IsLast = HT.getRefCount() == 1;
299+
IsLast = HT.getRefCount() == 1 && HT.getRefCount(UseHoldRefCount) == 1;
297300

298-
if (!IsLast && UpdateRefCount)
299-
HT.decRefCount();
301+
if (!IsLast && UpdateRefCount && HT.getRefCount(UseHoldRefCount) > 0)
302+
HT.decRefCount(UseHoldRefCount);
300303

301304
uintptr_t tp = HT.TgtPtrBegin + ((uintptr_t)HstPtrBegin - HT.HstPtrBegin);
302305
DP("Mapping exists with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD ", "
@@ -333,7 +336,7 @@ void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size) {
333336
}
334337

335338
int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete,
336-
bool HasCloseModifier) {
339+
bool HasCloseModifier, bool HasHoldModifier) {
337340
if (RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && !HasCloseModifier)
338341
return OFFLOAD_SUCCESS;
339342
// Check if the pointer is contained in any sub-nodes.
@@ -344,7 +347,7 @@ int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete,
344347
auto &HT = *lr.Entry;
345348
if (ForceDelete)
346349
HT.resetRefCount();
347-
if (HT.decRefCount() == 0) {
350+
if (HT.decRefCount(HasHoldModifier) == 0) {
348351
DP("Deleting tgt data " DPxMOD " of size %" PRId64 "\n",
349352
DPxPTR(HT.TgtPtrBegin), Size);
350353
#if OMPT_SUPPORT

openmp/libomptarget/src/device.h

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,44 +40,69 @@ struct HostDataToTargetTy {
4040

4141
private:
4242
/// use mutable to allow modification via std::set iterator which is const.
43+
///@{
4344
mutable uint64_t RefCount;
45+
mutable uint64_t HoldRefCount;
46+
///@}
4447
static const uint64_t INFRefCount = ~(uint64_t)0;
4548

4649
public:
4750
HostDataToTargetTy(uintptr_t BP, uintptr_t B, uintptr_t E, uintptr_t TB,
48-
bool IsINF = false)
49-
: HstPtrBase(BP), HstPtrBegin(B), HstPtrEnd(E),
50-
TgtPtrBegin(TB), RefCount(IsINF ? INFRefCount : 1) {}
51+
bool UseHoldRefCount, bool IsINF)
52+
: HstPtrBase(BP), HstPtrBegin(B), HstPtrEnd(E), TgtPtrBegin(TB),
53+
RefCount(IsINF ? INFRefCount : !UseHoldRefCount),
54+
HoldRefCount(UseHoldRefCount) {}
5155

56+
/// Get the total reference count.
5257
uint64_t getRefCount() const {
53-
return RefCount;
58+
if (RefCount == INFRefCount)
59+
return RefCount;
60+
return RefCount + HoldRefCount;
5461
}
5562

63+
/// Get a specific reference count.
64+
uint64_t getRefCount(bool UseHoldRefCount) const {
65+
return UseHoldRefCount ? HoldRefCount : RefCount;
66+
}
67+
68+
/// Reset the dynamic reference count only and return the total reference
69+
/// count.
5670
uint64_t resetRefCount() const {
5771
if (RefCount != INFRefCount)
5872
RefCount = 1;
5973

60-
return RefCount;
74+
return getRefCount();
6175
}
6276

63-
uint64_t incRefCount() const {
64-
if (RefCount != INFRefCount) {
77+
/// Increment the specified reference count and return the total reference
78+
/// count.
79+
uint64_t incRefCount(bool UseHoldRefCount) const {
80+
if (UseHoldRefCount) {
81+
++HoldRefCount;
82+
assert(HoldRefCount < INFRefCount && "hold refcount overflow");
83+
} else if (RefCount != INFRefCount) {
6584
++RefCount;
6685
assert(RefCount < INFRefCount && "refcount overflow");
6786
}
6887

69-
return RefCount;
88+
return getRefCount();
7089
}
7190

72-
uint64_t decRefCount() const {
73-
if (RefCount != INFRefCount) {
91+
/// Decrement the specified reference count and return the total reference
92+
/// count.
93+
uint64_t decRefCount(bool UseHoldRefCount) const {
94+
if (UseHoldRefCount) {
95+
assert(HoldRefCount > 0 && "hold refcount underflow");
96+
--HoldRefCount;
97+
} else if (RefCount != INFRefCount) {
7498
assert(RefCount > 0 && "refcount underflow");
7599
--RefCount;
76100
}
77101

78-
return RefCount;
102+
return getRefCount();
79103
}
80104

105+
/// Is the dynamic (and thus total) reference count infinite?
81106
bool isRefCountInf() const {
82107
return RefCount == INFRefCount;
83108
}
@@ -196,13 +221,14 @@ struct DeviceTy {
196221
void *getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase, int64_t Size,
197222
bool &IsNew, bool &IsHostPtr, bool IsImplicit,
198223
bool UpdateRefCount, bool HasCloseModifier,
199-
bool HasPresentModifier, bool HasNoAllocModifier);
224+
bool HasPresentModifier, bool HasNoAllocModifier,
225+
bool HasHoldModifier);
200226
void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size);
201227
void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
202-
bool UpdateRefCount, bool &IsHostPtr,
203-
bool MustContain = false);
228+
bool UpdateRefCount, bool UseHoldRefCount,
229+
bool &IsHostPtr, bool MustContain = false);
204230
int deallocTgtPtr(void *TgtPtrBegin, int64_t Size, bool ForceDelete,
205-
bool HasCloseModifier = false);
231+
bool HasCloseModifier, bool HasHoldModifier);
206232
int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
207233
int disassociatePtr(void *HstPtrBegin);
208234

0 commit comments

Comments
 (0)