Skip to content

Commit b2470f4

Browse files
committed
Fix 'from' + 'delete', and multiple 'always,from' entries.
1 parent 8f58397 commit b2470f4

File tree

4 files changed

+97
-8
lines changed

4 files changed

+97
-8
lines changed

offload/include/OpenMP/Mapping.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,14 @@ struct StateInfoTy {
499499
/// occur due to the ref-count not being zero.
500500
llvm::SmallSet<void *, 32> DeferredFromPtrs;
501501

502+
/// Host pointers for which we have attempted a FROM transfer at some point
503+
/// during targetDataEnd. Used to avoid duplicate transfers.
504+
llvm::SmallSet<void *, 32> TransferredFromPtrs;
505+
506+
/// Host pointers for which a DELETE entry was encountered, causing their
507+
/// ref-count to have gone down to zero.
508+
llvm::SmallSet<void *, 32> MarkedForDeletionPtrs;
509+
502510
StateInfoTy() = default;
503511

504512
// Delete copy constructor and copy assignment operator to prevent copying

offload/libomptarget/omptarget.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,7 @@ int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
10861086
HstPtrBegin, DataSize, UpdateRef, HasHoldModifier, !IsImplicit,
10871087
ForceDelete, /*FromDataEnd=*/true);
10881088
void *TgtPtrBegin = TPR.TargetPointer;
1089+
10891090
if (!TPR.isPresent() && !TPR.isHostPointer() &&
10901091
(DataSize || HasPresentModifier)) {
10911092
DP("Mapping does not exist (%s)\n",
@@ -1125,6 +1126,11 @@ int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
11251126
if (!TPR.isPresent())
11261127
continue;
11271128

1129+
// Track force-deleted pointers so we can use this information if we
1130+
// encounter FROM entries for the same pointer later on.
1131+
if (ForceDelete && TPR.Flags.IsLast)
1132+
StateInfo->MarkedForDeletionPtrs.insert(HstPtrBegin);
1133+
11281134
// Move data back to the host
11291135
const bool HasAlways = ArgTypes[I] & OMP_TGT_MAPTYPE_ALWAYS;
11301136
const bool HasFrom = ArgTypes[I] & OMP_TGT_MAPTYPE_FROM;
@@ -1141,15 +1147,40 @@ int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
11411147
return true;
11421148
};
11431149

1150+
// Lambda to check if this pointer was previously marked for deletion.
1151+
// Such a pointer would have had "IsLast" set to true when its DELETE entry
1152+
// was processed. So, the flag wouldn't be set for any FROM entries seen
1153+
// later on.
1154+
auto WasPreviouslyMarkedForDeletion = [&]() -> bool {
1155+
if (!StateInfo->MarkedForDeletionPtrs.contains(HstPtrBegin))
1156+
return false;
1157+
DP("Pointer HstPtr=" DPxMOD " was previously marked for deletion\n",
1158+
DPxPTR(HstPtrBegin));
1159+
return true;
1160+
};
1161+
1162+
bool FromCopyBackAlreadyDone =
1163+
StateInfo->TransferredFromPtrs.contains(HstPtrBegin);
11441164
bool IsMapFromOnNonHostNonZeroData =
11451165
HasFrom && !TPR.Flags.IsHostPointer && DataSize != 0;
1146-
bool IsLastOrHasAlways = TPR.Flags.IsLast || HasAlways;
1166+
bool IsLastOrHasAlwaysOrWasForceDeleted =
1167+
TPR.Flags.IsLast || HasAlways || WasPreviouslyMarkedForDeletion();
1168+
1169+
if (!FromCopyBackAlreadyDone &&
1170+
((IsMapFromOnNonHostNonZeroData &&
1171+
IsLastOrHasAlwaysOrWasForceDeleted) ||
1172+
// Even if are not looking at an entry with FROM map-type, if there
1173+
// were any previously deferred FROM transfers for this pointer, we
1174+
// should do them when the ref-count goes down to zero.
1175+
(TPR.Flags.IsLast && HasDeferredMapFrom()))) {
1176+
// Track that we're doing a FROM transfer for this pointer
1177+
// NOTE: If we don't care about the case of multiple different maps with
1178+
// from, always, or multiple map(from)s seen after a map(delete), e.g.
1179+
// ... map(always, from: x) map(always, from: x)
1180+
// ... map(delete: x) map(from: x) map(from: x)
1181+
// Then we can forego tacking TransferredFromPtrs.
1182+
StateInfo->TransferredFromPtrs.insert(HstPtrBegin);
11471183

1148-
if ((IsMapFromOnNonHostNonZeroData && IsLastOrHasAlways) ||
1149-
// Even if are not looking at an entry with FROM map-type, if there were
1150-
// any previously deferred FROM transfers for this pointer, we should
1151-
// do them when the ref-count goes down to zero.
1152-
(TPR.Flags.IsLast && HasDeferredMapFrom())) {
11531184
DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n",
11541185
DataSize, DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin));
11551186
TIMESCOPE_WITH_DETAILS_AND_IDENT(
@@ -1179,8 +1210,8 @@ int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
11791210
OFFLOAD_SUCCESS)
11801211
return OFFLOAD_FAIL;
11811212
}
1182-
} else if (IsMapFromOnNonHostNonZeroData && !IsLastOrHasAlways &&
1183-
!IsMemberOf) {
1213+
} else if (!FromCopyBackAlreadyDone && IsMapFromOnNonHostNonZeroData &&
1214+
!IsLastOrHasAlwaysOrWasForceDeleted && !IsMemberOf) {
11841215
// We can have cases like the following:
11851216
// map(alloc: p[0:1]) map(from: p[0:1])
11861217
//
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %libomptarget-compile-generic
2+
// RUN: env LIBOMPTARGET_DEBUG=1 %libomptarget-run-generic 2>&1 \
3+
// RUN: | %fcheck-generic -check-prefix=DEBUG -check-prefix=CHECK
4+
// REQUIRES: libomptarget-debug
5+
6+
// There should only be one "from" data-transfer, despite the two duplicate
7+
// maps.
8+
9+
#include <stdio.h>
10+
11+
int main() {
12+
int x = 111;
13+
#pragma omp target data map(alloc : x)
14+
{
15+
#pragma omp target enter data map(alloc : x) map(to : x)
16+
{
17+
#pragma omp target map(present, alloc : x)
18+
{
19+
printf("%d\n", x); // CHECK-NOT: 111
20+
x = 222;
21+
}
22+
}
23+
#pragma omp target exit data map(always, from : x) map(always, from : x)
24+
// DEBUG: omptarget --> Moving 4 bytes (tgt:0x{{.*}}) -> (hst:0x{{.*}})
25+
// DEBUG-NOT: omptarget --> Moving 4 bytes
26+
}
27+
28+
printf("%d\n", x); // CHECK: 222
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %libomptarget-compile-run-and-check-generic
2+
3+
#include <stdio.h>
4+
5+
int main() {
6+
int x = 111;
7+
#pragma omp target data map(alloc : x)
8+
{
9+
#pragma omp target enter data map(alloc : x) map(to : x)
10+
{
11+
#pragma omp target map(present, alloc : x)
12+
{
13+
printf("%d\n", x); // CHECK-NOT: 111
14+
x = 222;
15+
}
16+
}
17+
#pragma omp target exit data map(from : x) map(delete : x)
18+
}
19+
20+
printf("%d\n", x); // CHECK: 222
21+
}

0 commit comments

Comments
 (0)