Skip to content

Commit 63d7c8f

Browse files
committed
Add an implicit map of attach-ptr on a target construct.
1 parent b0170f7 commit 63d7c8f

File tree

4 files changed

+291
-115
lines changed

4 files changed

+291
-115
lines changed

clang/lib/CodeGen/CGOpenMPRuntime.cpp

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9462,7 +9462,10 @@ class MappableExprsHandler {
94629462
/// Populate component lists for non-lambda captured variables from map,
94639463
/// is_device_ptr and has_device_addr clause info.
94649464
void populateComponentListsForNonLambdaCaptureFromClauses(
9465-
const ValueDecl *VD, MapDataArrayTy &DeclComponentLists) const {
9465+
const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9466+
SmallVectorImpl<
9467+
SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9468+
&StorageForImplicitlyAddedComponentLists) const {
94669469
if (VD && LambdasMap.count(VD))
94679470
return;
94689471

@@ -9501,6 +9504,14 @@ class MappableExprsHandler {
95019504
++EI;
95029505
}
95039506
}
9507+
9508+
// For the target construct, if there's a map with a base-pointer that's
9509+
// a member of an implicitly captured struct, of the current class,
9510+
// we need to emit an implicit map on the pointer.
9511+
if (isOpenMPTargetExecutionDirective(CurExecDir->getDirectiveKind()))
9512+
addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9513+
VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9514+
95049515
llvm::stable_sort(DeclComponentLists, [](const MapData &LHS,
95059516
const MapData &RHS) {
95069517
ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
@@ -9517,6 +9528,147 @@ class MappableExprsHandler {
95179528
});
95189529
}
95199530

9531+
/// On a target construct, if there's an implicit map on a struct, or that of
9532+
/// this[:], and an explicit map with a member of that struct/class as the
9533+
/// base-pointer, we need to make sure that base-pointer is implicitly mapped,
9534+
/// to make sure we don't map the full struct/class. For example:
9535+
///
9536+
/// \code
9537+
/// struct S {
9538+
/// int dummy[10000];
9539+
/// int *p;
9540+
/// void f1() {
9541+
/// #pragma omp target map(p[0:1])
9542+
/// (void)this;
9543+
/// }
9544+
/// }; S s;
9545+
///
9546+
/// void f2() {
9547+
/// #pragma omp target map(s.p[0:10])
9548+
/// (void)s;
9549+
/// }
9550+
/// \endcode
9551+
///
9552+
/// Only `this-p` and `s.p` should be mapped in the two cases above.
9553+
//
9554+
// OpenMP 6.0: 7.9.6 map clause, pg 285
9555+
// If a list item with an implicitly determined data-mapping attribute does
9556+
// not have any corresponding storage in the device data environment prior to
9557+
// a task encountering the construct associated with the map clause, and one
9558+
// or more contiguous parts of the original storage are either list items or
9559+
// base pointers to list items that are explicitly mapped on the construct,
9560+
// only those parts of the original storage will have corresponding storage in
9561+
// the device data environment as a result of the map clauses on the
9562+
// construct.
9563+
void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9564+
const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9565+
SmallVectorImpl<
9566+
SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9567+
&ComponentVectorStorage) const {
9568+
bool IsThisCapture = CapturedVD == nullptr;
9569+
9570+
for (const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9571+
OMPClauseMappableExprCommon::MappableExprComponentListRef
9572+
ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9573+
const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9574+
if (!AttachPtrExpr)
9575+
continue;
9576+
9577+
const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9578+
if (!ME)
9579+
continue;
9580+
9581+
const Expr *Base = ME->getBase()->IgnoreParenImpCasts();
9582+
9583+
if (IsThisCapture && !ME->isImplicitCXXThis() && !isa<CXXThisExpr>(Base))
9584+
continue;
9585+
9586+
if (!IsThisCapture && (!isa<DeclRefExpr>(Base) ||
9587+
cast<DeclRefExpr>(Base)->getDecl() != CapturedVD))
9588+
continue;
9589+
9590+
// Check if we have an existing map on either:
9591+
// this[:], s, this->p, or s.p, in which case, we don't need to add
9592+
// an implicit one for the attach-ptr s.p/this->p.
9593+
bool FoundExistingMap = false;
9594+
for (const MapData &ExistingL : DeclComponentLists) {
9595+
OMPClauseMappableExprCommon::MappableExprComponentListRef
9596+
ExistingComponents = std::get<0>(ExistingL);
9597+
9598+
if (ExistingComponents.empty())
9599+
continue;
9600+
9601+
// First check if we have a map like map(this->p) or map(s.p).
9602+
const auto &FirstComponent = ExistingComponents.front();
9603+
const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9604+
9605+
if (!FirstExpr)
9606+
continue;
9607+
9608+
// First check if we have a map like map(this->p) or map(s.p).
9609+
if (AttachPtrExprComparator(this).areEqual(FirstExpr, AttachPtrExpr)) {
9610+
FoundExistingMap = true;
9611+
break;
9612+
}
9613+
9614+
// Check if we have a map like this[0:1]
9615+
if (IsThisCapture) {
9616+
if (const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9617+
if (isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts())) {
9618+
FoundExistingMap = true;
9619+
break;
9620+
}
9621+
}
9622+
continue;
9623+
}
9624+
9625+
// When the attach-ptr is something like `s.p`, check if
9626+
// `s` itself is mapped explicitly.
9627+
if (const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9628+
if (DRE->getDecl() == CapturedVD) {
9629+
FoundExistingMap = true;
9630+
break;
9631+
}
9632+
}
9633+
}
9634+
9635+
if (FoundExistingMap)
9636+
continue;
9637+
9638+
// If no base map is found, we need to create an implicit map for the
9639+
// attach-pointer expr.
9640+
9641+
ComponentVectorStorage.emplace_back();
9642+
auto &AttachPtrComponents = ComponentVectorStorage.back();
9643+
9644+
static const OpenMPMapModifierKind Unknown = OMPC_MAP_MODIFIER_unknown;
9645+
bool SeenAttachPtrComponent = false;
9646+
// For creating a map on the attach-ptr `s.p/this->p`, we copy all
9647+
// components from the component-list which has `s.p/this->p`
9648+
// as the attach-ptr, starting from the component which matches
9649+
// `s.p/this->p`. This way, we'll have component-lists of
9650+
// `s.p` -> `s`, and `this->p` -> `this`.
9651+
for (size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9652+
const auto &Component = ComponentsWithAttachPtr[i];
9653+
const Expr *ComponentExpr = Component.getAssociatedExpression();
9654+
9655+
if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9656+
continue;
9657+
SeenAttachPtrComponent = true;
9658+
9659+
AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9660+
Component.getAssociatedDeclaration(),
9661+
Component.isNonContiguous());
9662+
}
9663+
assert(!AttachPtrComponents.empty() &&
9664+
"Could not populate component-lists for mapping attach-ptr");
9665+
9666+
DeclComponentLists.emplace_back(
9667+
AttachPtrComponents, OMPC_MAP_tofrom, Unknown,
9668+
/*IsImplicit=*/true, /*mapper=*/nullptr, AttachPtrExpr);
9669+
}
9670+
}
9671+
95209672
/// For a capture that has an associated clause, generate the base pointers,
95219673
/// section pointers, sizes, map types, and mappers (all included in
95229674
/// \a CurCaptureVarInfo).
@@ -10325,8 +10477,12 @@ static void genMapInfoForCaptures(
1032510477

1032610478
// Populate component lists for the captured variable from clauses.
1032710479
MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10480+
SmallVector<
10481+
SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>, 4>
10482+
StorageForImplicitlyAddedComponentLists;
1032810483
MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10329-
CapturedVD, DeclComponentLists);
10484+
CapturedVD, DeclComponentLists,
10485+
StorageForImplicitlyAddedComponentLists);
1033010486

1033110487
// Map clauses on a target construct must either have a base pointer, or a
1033210488
// base-variable. So, if we don't have a base-pointer, that means that it

clang/test/OpenMP/target_map_codegen_20.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@
7474
// CK21-NOUSE: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 3, i64 16384]
7575

7676
// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
77-
// CK21: [[SIZE02:@.+]] = private {{.*}}constant [2 x i64] [i64 500, i64 {{4|8}}]
78-
// CK21-USE: [[MTYPE02:@.+]] = private unnamed_addr constant [2 x i64] [i64 34, i64 16384]
77+
// CK21-USE: [[SIZE02:@.+]] = private {{.*}}constant [3 x i64] [i64 {{4|8}}, i64 500, i64 {{4|8}}]
78+
// CK21-NOUSE: [[SIZE02:@.+]] = private {{.*}}constant [2 x i64] [i64 500, i64 {{4|8}}]
79+
// CK21-USE: [[MTYPE02:@.+]] = private {{.*}}constant [3 x i64] [i64 547, i64 2, i64 16384]
7980
// CK21-NOUSE: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 2, i64 16384]
8081

8182
// CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
@@ -168,7 +169,8 @@ struct CC {
168169

169170
// Region 02
170171

171-
// &B[0], &B[X], 2 * sizeof(T), (FROM) / (FROM | PARAM)
172+
// [&this[0], &this[0].B, sizeof(B), PARAM | ALLOC | IMPLICIT]
173+
// &B[0], &B[X], 2 * sizeof(T), FROM
172174
// &B, &B[X], sizeof(T*), ATTACH
173175

174176
// CK21-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
@@ -181,18 +183,29 @@ struct CC {
181183

182184
// CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
183185
// CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
184-
// CK21-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
185-
// CK21-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
186+
// CK21-USE-DAG: store ptr [[THIS:%.+]], ptr [[BP0]]
187+
// CK21-USE-DAG: store ptr [[B:%.+]], ptr [[P0]]
188+
// CK21-USE-DAG: [[B:%B]] = getelementptr inbounds {{.*}}[[THIS]], i{{.*}} 0, i{{.*}} 2
189+
190+
// CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
191+
// CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
192+
// CK21-USE-DAG: store ptr [[VAR0:%.+]], ptr [[BP1]]
193+
// CK21-USE-DAG: store ptr [[SEC0:%.+]], ptr [[P1]]
194+
// CK21-NOUSE-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
195+
// CK21-NOUSE-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
196+
186197
// CK21-DAG: [[VAR0]] = load ptr, ptr [[VAR00:%[^,]+]]
187198
// CK21-DAG: [[VAR00]] = getelementptr inbounds nuw %struct.CC, ptr [[THIS:%.+]], i{{.*}} 0, i{{.*}} 2
188199
// CK21-DAG: [[SEC0]] = getelementptr inbounds nuw float, ptr [[SEC00:%.+]], i{{.*}} 123
189200
// CK21-DAG: [[SEC00]] = load ptr, ptr [[SEC000:%[^,]+]]
190201
// CK21-DAG: [[SEC000]] = getelementptr inbounds nuw %struct.CC, ptr [[THIS]], i{{.*}} 0, i{{.*}} 2
191202

192-
// CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
193-
// CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
194-
// CK21-DAG: store ptr [[VAR00]], ptr [[BP1]]
195-
// CK21-DAG: store ptr [[SEC0]], ptr [[P1]]
203+
// CK21-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
204+
// CK21-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
205+
// CK21-USE-DAG: store ptr [[VAR00:%.+]], ptr [[BP2]]
206+
// CK21-USE-DAG: store ptr [[SEC0:%.+]], ptr [[P2]]
207+
// CK21-NOUSE-DAG: store ptr [[VAR00]], ptr [[BP1]]
208+
// CK21-NOUSE-DAG: store ptr [[SEC0]], ptr [[P1]]
196209

197210
// CK21-USE: call void [[CALL02:@.+]](ptr {{[^,]+}})
198211
// CK21-NOUSE: call void [[CALL02:@.+]]()

0 commit comments

Comments
 (0)