@@ -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
0 commit comments