Skip to content

Commit 5d72174

Browse files
committed
[WIP][Offload] Introduce ATTACH map-type support for pointer attachment.
This patch introduces libomptarget support for the ATTACH map-type, which can be used to implement OpenMP conditional compliant pointer attachment, based on whether the pointer/pointee is newly mapped on a given construct. For example, for the following: ```c int *p; #pragma omp target enter data map(p[1:10]) ``` The following maps can be emitted by clang: ``` (A) &p[0], &p[1], 10 * sizeof(p[1]), TO | FROM &p, &p[1], sizeof(p), ATTACH ``` Without this map-type, the two possible maps emitted by clang: ``` (B) &p[0], &p[1], 10 * sizeof(p[1]), TO | FROM (C) &p, &p[1], 10 * sizeof(p[1]), TO | FROM | PTR_AND_OBJ ```` (B) does not perform any pointer attachment, while (C) also maps the pointer p, which are both incorrect. In terms of implementation, maps with the ATTACH map-type are handled after all other maps have been processed, as it requires knowledge of which new allocations happened as part of the construct. As per OpenMP 5.0, an attachment should happen only when either the pointer or the pointee was newly mapped while handling the construct. Maps with ATTACH map-type-bit do not increase/decrease the ref-count. With OpenMP 6.1, `attach(always/never)` can be used to force/prevent attachment. For `attach(always)`, the compiler will insert the ALWAYS map-type, which would let libomptarget bypass the check about one of the pointer/pointee being new. With `attach(never)`, the ATTACH map will not be emitted at all. The size argument of the ATTACH map-type can specify values greater than `sizeof(void*)` which can be used to support pointer attachment on Fortran descriptors. Note that this also requires shadow-pointer tracking to also support them. That has not been implemented in this patch. This was worked upon in coordination with Ravi Narayanaswamy, who has since retired. Happy retirement, Ravi!
1 parent 1c22382 commit 5d72174

File tree

4 files changed

+438
-36
lines changed

4 files changed

+438
-36
lines changed

offload/include/OpenMP/Mapping.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,12 +417,42 @@ struct MapperComponentsTy {
417417
typedef void (*MapperFuncPtrTy)(void *, void *, void *, int64_t, int64_t,
418418
void *);
419419

420+
/// Structure to store information about a single ATTACH map entry.
421+
struct AttachMapInfo {
422+
void *PointerBase;
423+
void *PointeeBegin;
424+
int64_t PointerSize;
425+
int64_t MapType;
426+
map_var_info_t Pointername;
427+
428+
AttachMapInfo(void *PointerBase, void *PointeeBegin, int64_t Size,
429+
int64_t Type, map_var_info_t Name)
430+
: PointerBase(PointerBase), PointeeBegin(PointeeBegin), PointerSize(Size),
431+
MapType(Type), Pointername(Name) {}
432+
};
433+
434+
/// Structure to track ATTACH entries and new allocations across recursive calls
435+
/// (for handling mappers) to targetDataBegin for a given construct.
436+
struct AttachInfoTy {
437+
/// ATTACH map entries for deferred processing.
438+
llvm::SmallVector<AttachMapInfo> AttachEntries;
439+
440+
/// Key: host pointer, Value: allocation size.
441+
llvm::DenseMap<void *, int64_t> NewAllocations;
442+
443+
AttachInfoTy() = default;
444+
445+
// Delete copy constructor and copy assignment operator to prevent copying
446+
AttachInfoTy(const AttachInfoTy &) = delete;
447+
AttachInfoTy &operator=(const AttachInfoTy &) = delete;
448+
};
449+
420450
// Function pointer type for targetData* functions (targetDataBegin,
421451
// targetDataEnd and targetDataUpdate).
422452
typedef int (*TargetDataFuncPtrTy)(ident_t *, DeviceTy &, int32_t, void **,
423453
void **, int64_t *, int64_t *,
424454
map_var_info_t *, void **, AsyncInfoTy &,
425-
bool);
455+
AttachInfoTy *, bool);
426456

427457
void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device,
428458
bool toStdOut = false);
@@ -431,20 +461,26 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
431461
void **ArgsBase, void **Args, int64_t *ArgSizes,
432462
int64_t *ArgTypes, map_var_info_t *ArgNames,
433463
void **ArgMappers, AsyncInfoTy &AsyncInfo,
464+
AttachInfoTy *AttachInfo = nullptr,
434465
bool FromMapper = false);
435466

436467
int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
437468
void **ArgBases, void **Args, int64_t *ArgSizes,
438469
int64_t *ArgTypes, map_var_info_t *ArgNames,
439470
void **ArgMappers, AsyncInfoTy &AsyncInfo,
440-
bool FromMapper = false);
471+
AttachInfoTy *AttachInfo = nullptr, bool FromMapper = false);
441472

442473
int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
443474
void **ArgsBase, void **Args, int64_t *ArgSizes,
444475
int64_t *ArgTypes, map_var_info_t *ArgNames,
445476
void **ArgMappers, AsyncInfoTy &AsyncInfo,
477+
AttachInfoTy *AttachInfo = nullptr,
446478
bool FromMapper = false);
447479

480+
// Process deferred ATTACH map entries collected during targetDataBegin.
481+
int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
482+
AsyncInfoTy &AsyncInfo);
483+
448484
struct MappingInfoTy {
449485
MappingInfoTy(DeviceTy &Device) : Device(Device) {}
450486

offload/include/omptarget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ enum tgt_map_type {
8080
// the structured region
8181
// This is an OpenMP extension for the sake of OpenACC support.
8282
OMP_TGT_MAPTYPE_OMPX_HOLD = 0x2000,
83+
// Attach pointer and pointee, after processing all other maps.
84+
// Applicable to map-entering directives. Does not change ref-count.
85+
OMP_TGT_MAPTYPE_ATTACH = 0x4000,
8386
// descriptor for non-contiguous target-update
8487
OMP_TGT_MAPTYPE_NON_CONTIG = 0x100000000000,
8588
// member of struct, member given by [16 MSBs] - 1

offload/libomptarget/interface.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,28 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
165165
OMPT_GET_RETURN_ADDRESS);)
166166

167167
int Rc = OFFLOAD_SUCCESS;
168+
169+
// Only allocate AttachInfo for targetDataBegin
170+
AttachInfoTy *AttachInfo = nullptr;
171+
if (TargetDataFunction == targetDataBegin) {
172+
AttachInfo = new AttachInfoTy();
173+
}
174+
168175
Rc = TargetDataFunction(Loc, *DeviceOrErr, ArgNum, ArgsBase, Args, ArgSizes,
169176
ArgTypes, ArgNames, ArgMappers, AsyncInfo,
170-
false /*FromMapper=*/);
177+
AttachInfo, false /*FromMapper=*/);
171178

172-
if (Rc == OFFLOAD_SUCCESS)
173-
Rc = AsyncInfo.synchronize();
179+
if (Rc == OFFLOAD_SUCCESS) {
180+
// Process deferred ATTACH entries BEFORE synchronization
181+
if (AttachInfo && !AttachInfo->AttachEntries.empty())
182+
Rc = processAttachEntries(*DeviceOrErr, *AttachInfo, AsyncInfo);
183+
184+
if (Rc == OFFLOAD_SUCCESS)
185+
Rc = AsyncInfo.synchronize();
186+
}
187+
188+
if (AttachInfo)
189+
delete AttachInfo;
174190

175191
handleTargetOutcome(Rc == OFFLOAD_SUCCESS, Loc);
176192
}

0 commit comments

Comments
 (0)