[llvm-branch-commits] [Flang][OpenMP] Derived type explicit allocatable member mapping (PR #96266)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Jun 20 18:47:27 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-openmp

Author: None (agozillon)

<details>
<summary>Changes</summary>

This PR is one of 3 in a PR stack, this is the primary change set which seeks
to extend the current derived type explicit member mapping support to
handle descriptor member mapping at arbitrary levels of nesting. The PR
stack seems to do this reasonably (from testing so far) but as you can
create quite complex mappings with derived types (in particular when adding
allocatable derived types or arrays of allocatable derived types) I imagine
there will be hiccups, which I am more than happy to address. There will
also be further extensions to this work to handle the implicit auto-magical
mapping of descriptor members in derived types and a few other changes
planned for the future (with some ideas on optimizing things).

The changes in this PR primarily occur in the OpenMP lowering and
the OMPMapInfoFinalization pass.

In the OpenMP lowering several utility functions were added or extended
to support the generation of appropriate intermediate member mappings
which are currently required when the parent (or multiple parents) of a
mapped member are descriptor types. We need to map the entirety of
these types or do a "deep copy" for lack of a better term, where we map
both the base address and the descriptor as without the copying of both
of these we lack the information in the case of the descriptor to access the
member or attach the pointers data to the pointer and in the latter case we
require the base address to map the chunk of data. Currently we do not
segment descriptor based derived types as we do with regular
non-descriptor derived types, we effectively map their entirety in all
cases at the moment, I hope to address this at some point in the future as
it adds a fair bit of a performance penalty to having nestings of allocatable
derived types as an example. The process of mapping all intermediate
descriptor members in a members path only occurs if a member has
an allocatable or object parent in its symbol path or the member itself
is a member or allocatable. This occurs in the
createParentSymAndGenIntermediateMaps function, which will also
generate the appropriate address for the allocatable member
within the derived type to use as a the varPtr field of the map (for
intermediate allocatable maps and final allocatable mappings). In
this case it's necessary as we can't utilise the usual Fortran::lower
functionality such as gatherDataOperandAddrAndBounds without
causing issues later in the lowering due to extra allocas being spawned
which seem to affect the pointer attachment (at least this is my
current assumption, it results in memory access errors on the device
due to incorrect map information generation). This is similar
to why we do not use the MLIR value generated for this and utilise
the original symbol provided when mapping descriptor types external
to derived types. Hopefully this can be rectified in the future so this
function can be simplified and more closely aligned to the other type
mappings. We also make use of fir::CoordinateOp as opposed to the
HLFIR version as the HLFIR version doesn't support the appropriate
lowering to FIR necessary at the moment, we also cannot use a
single CoordinateOp (similarly to a single GEP) as when we index
through a descriptor operation (BoxType) we encounter issues later
in the lowering, however in either case we need access to intermediate
descriptors so individual CoordinateOp's aid this (although, being
able to compress them into a smaller amount of CoordinateOp's may
simplify the IR and perhaps result in a better end product, something
to consider for the future).

The other large change area was in the OMPMapInfoFinalization pass,
where the pass had to be extended to support the expansion of box
types (or multiple nestings of box types) within derived types, or box
type derived types. This requires expanding each BoxType mapping
from one into two maps and then modifying all of the existing
member indices of the overarching parent mapping to account for
the addition of these new members alongside adjusting the existing
member indices to support the addition of these new maps which
extend the original member indices (as a base address of a box type
is currently considered a member of the box type at a position of
0 as when lowered to LLVM-IR it's a pointer contained at this position
in the descriptor type, however, this means extending mapped children
of this expanded descriptor type to additionally incorporate the new
member index in the correct location in its own index list). I believe
there is a reasonable amount of comments that should aid in
understanding this better, alongside the test alterations for the pass.

A subset of the changes were also aimed at making some of the utilities
for packing and unpacking the DenseIntElementsAttr
containing the member indices shareable across the lowering and
OMPMapInfoFinalization, this required moving some functions to the
Lower/Support/Utils.h header, and transforming the lowering structure
containing the member index data into something more similar to the
version used in OMPMapInfoFinalization. There we also some other
attempts at tidying things up in relation to the member index data
generation in the lowering, some of which required creating a logical
operator for the OpenMP ID class so it can be utilised as a map key
(it simply utilises the symbol address for the moment as ordering
isn't particularly important).

Otherwise I have added a set of new tests encompassing some of
the mappings currently supported by this PR (unfortunately as
you can have arbitrary nestings of all shapes and types it's not
very feasible to cover them all).


---

Patch is 237.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/96266.diff


13 Files Affected:

- (modified) flang/include/flang/Lower/Support/Utils.h (+49-1) 
- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.cpp (+26-9) 
- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.h (+31-13) 
- (modified) flang/lib/Lower/OpenMP/Clauses.h (+11) 
- (modified) flang/lib/Lower/OpenMP/Utils.cpp (+180-108) 
- (modified) flang/lib/Lower/OpenMP/Utils.h (+31-15) 
- (modified) flang/lib/Optimizer/Transforms/OMPMapInfoFinalization.cpp (+249-64) 
- (modified) flang/test/Fir/convert-to-llvm-openmp-and-fir.fir (+172) 
- (modified) flang/test/Integration/OpenMP/map-types-and-sizes.f90 (+341-26) 
- (added) flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 (+166) 
- (modified) flang/test/Lower/OpenMP/derived-type-map.f90 (+8-8) 
- (modified) flang/test/Lower/OpenMP/map-component-ref.f90 (+1-1) 
- (modified) flang/test/Transforms/omp-map-info-finalization.fir (+183) 


``````````diff
diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 1cc74521e22d8..8fce3bc4ce842 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -14,6 +14,7 @@
 #define FORTRAN_LOWER_SUPPORT_UTILS_H
 
 #include "flang/Common/indirection.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Parser/char-block.h"
 #include "flang/Semantics/tools.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
@@ -21,7 +22,7 @@
 #include "mlir/IR/BuiltinAttributes.h"
 #include "llvm/ADT/StringRef.h"
 #include <cstdint>
-
+#include <numeric>
 namespace Fortran::lower {
 using SomeExpr = Fortran::evaluate::Expr<Fortran::evaluate::SomeType>;
 } // end namespace Fortran::lower
@@ -671,4 +672,51 @@ static inline bool isEqual(const Fortran::lower::SomeExpr *x,
 }
 } // end namespace Fortran::lower
 
+// OpenMP utility functions used in locations outside of the
+// OpenMP lowering.
+namespace Fortran::lower::omp {
+
+[[maybe_unused]] static void fillMemberIndices(
+    llvm::SmallVector<llvm::SmallVector<int>> &memberPlacementData) {
+  size_t largestIndicesSize =
+      std::max_element(memberPlacementData.begin(), memberPlacementData.end(),
+                       [](auto a, auto b) { return a.size() < b.size(); })
+          ->size();
+
+  // DenseElementsAttr expects a rectangular shape for the data, so all
+  // index lists have to be of the same length, this emplaces -1 as filler.
+  for (auto &v : memberPlacementData) {
+    if (v.size() < largestIndicesSize) {
+      auto *prevEnd = v.end();
+      v.resize(largestIndicesSize);
+      std::fill(prevEnd, v.end(), -1);
+    }
+  }
+}
+
+/// Helper function that will effectively repackage the modified
+/// memberPlacementData into a DenseIntElementsAttr so
+/// that it can be placed into the appropriate MapInfoOp
+[[maybe_unused]] static mlir::DenseIntElementsAttr
+createDenseElementsAttrFromIndices(
+    llvm::SmallVector<llvm::SmallVector<int>> &memberPlacementData,
+    fir::FirOpBuilder &builder) {
+  llvm::SmallVector<int> indicesFlattened =
+      std::accumulate(memberPlacementData.begin(), memberPlacementData.end(),
+                      llvm::SmallVector<int>(),
+                      [](llvm::SmallVector<int> &x, llvm::SmallVector<int> &y) {
+                        x.insert(x.end(), y.begin(), y.end());
+                        return x;
+                      });
+
+  return mlir::DenseIntElementsAttr::get(
+      mlir::VectorType::get(
+          {static_cast<int64_t>(memberPlacementData.size()),
+           static_cast<int64_t>(memberPlacementData[0].size())},
+          mlir::IntegerType::get(builder.getContext(), 32)),
+      llvm::ArrayRef<int32_t>(indicesFlattened));
+}
+
+} // end namespace Fortran::lower::omp
+
 #endif // FORTRAN_LOWER_SUPPORT_UTILS_H
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 27eea2b133b3c..afb3489d6f2b0 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -14,9 +14,11 @@
 #include "Clauses.h"
 
 #include "flang/Lower/PFTBuilder.h"
+#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
 #include "flang/Parser/tools.h"
 #include "flang/Semantics/tools.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
+#include <cstddef>
 
 namespace Fortran {
 namespace lower {
@@ -888,9 +890,7 @@ bool ClauseProcessor::processMap(
   llvm::SmallVector<const semantics::Symbol *> localMapSyms;
   llvm::SmallVectorImpl<const semantics::Symbol *> *ptrMapSyms =
       mapSyms ? mapSyms : &localMapSyms;
-  std::map<const semantics::Symbol *,
-           llvm::SmallVector<OmpMapMemberIndicesData>>
-      parentMemberIndices;
+  std::map<omp::Object, OmpMapMemberIndicesData> parentMemberIndices;
 
   bool clauseFound = findRepeatableClause<omp::clause::Map>(
       [&](const omp::clause::Map &clause, const parser::CharBlock &source) {
@@ -940,6 +940,7 @@ bool ClauseProcessor::processMap(
         for (const omp::Object &object : std::get<omp::ObjectList>(clause.t)) {
           llvm::SmallVector<mlir::Value> bounds;
           std::stringstream asFortran;
+          std::optional<omp::Object> parentObj;
 
           lower::AddrAndBoundsInfo info =
               lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
@@ -953,6 +954,22 @@ bool ClauseProcessor::processMap(
           if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
             symAddr = origSymbol;
 
+          if (object.sym()->owner().IsDerivedType()) {
+            omp::ObjectList objectList = gatherObjects(object, semaCtx);
+            parentObj = objectList[0];
+            parentMemberIndices.insert({parentObj.value(), {}});
+            if (Fortran::semantics::IsAllocatableOrObjectPointer(
+                    object.sym()) ||
+                memberHasAllocatableParent(object, semaCtx)) {
+              llvm::SmallVector<int> indices =
+                  generateMemberPlacementIndices(object, semaCtx);
+              symAddr = createParentSymAndGenIntermediateMaps(
+                  clauseLocation, converter, objectList, indices,
+                  parentMemberIndices[parentObj.value()], asFortran.str(),
+                  mapTypeBits);
+            }
+          }
+
           // Explicit map captures are captured ByRef by default,
           // optimisation passes may alter this to ByCopy or other capture
           // types to optimise
@@ -968,9 +985,9 @@ bool ClauseProcessor::processMap(
                   mapTypeBits),
               mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
 
-          if (object.sym()->owner().IsDerivedType()) {
-            addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
-                                        semaCtx);
+          if (parentObj.has_value()) {
+            addChildIndexAndMapToParent(
+                object, parentMemberIndices[parentObj.value()], mapOp, semaCtx);
           } else {
             result.mapVars.push_back(mapOp);
             ptrMapSyms->push_back(object.sym());
@@ -982,9 +999,9 @@ bool ClauseProcessor::processMap(
         }
       });
 
-  insertChildMapInfoIntoParent(converter, parentMemberIndices, result.mapVars,
-                               *ptrMapSyms, mapSymTypes, mapSymLocs);
-
+  insertChildMapInfoIntoParent(converter, semaCtx, parentMemberIndices,
+                               result.mapVars, mapSymTypes, mapSymLocs,
+                               ptrMapSyms);
   return clauseFound;
 }
 
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index 5c9ab8baf82dd..d254773678881 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -180,9 +180,7 @@ class ClauseProcessor {
 template <typename T>
 bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
                                            mlir::omp::MapClauseOps &result) {
-  std::map<const semantics::Symbol *,
-           llvm::SmallVector<OmpMapMemberIndicesData>>
-      parentMemberIndices;
+  std::map<omp::Object, OmpMapMemberIndicesData> parentMemberIndices;
   llvm::SmallVector<const semantics::Symbol *> mapSymbols;
 
   bool clauseFound = findRepeatableClause<T>(
@@ -203,10 +201,11 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
         for (const omp::Object &object : objects) {
           llvm::SmallVector<mlir::Value> bounds;
           std::stringstream asFortran;
+          std::optional<omp::Object> parentObj;
 
-          lower::AddrAndBoundsInfo info =
-              lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
-                                                    mlir::omp::MapBoundsType>(
+          Fortran::lower::AddrAndBoundsInfo info =
+              Fortran::lower::gatherDataOperandAddrAndBounds<
+                  mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>(
                   converter, firOpBuilder, semaCtx, stmtCtx, *object.sym(),
                   object.ref(), clauseLocation, asFortran, bounds,
                   treatIndexAsSection);
@@ -216,11 +215,30 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
           if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
             symAddr = origSymbol;
 
+          if (object.sym()->owner().IsDerivedType()) {
+            omp::ObjectList objectList = gatherObjects(object, semaCtx);
+            parentObj = objectList[0];
+            parentMemberIndices.insert({parentObj.value(), {}});
+            if (Fortran::semantics::IsAllocatableOrObjectPointer(
+                    object.sym()) ||
+                memberHasAllocatableParent(object, semaCtx)) {
+              llvm::SmallVector<int> indices =
+                  generateMemberPlacementIndices(object, semaCtx);
+              symAddr = createParentSymAndGenIntermediateMaps(
+                  clauseLocation, converter, objectList, indices,
+                  parentMemberIndices[parentObj.value()], asFortran.str(),
+                  mapTypeBits);
+            }
+          }
+
           // Explicit map captures are captured ByRef by default,
           // optimisation passes may alter this to ByCopy or other capture
           // types to optimise
+          auto location = mlir::NameLoc::get(
+              mlir::StringAttr::get(firOpBuilder.getContext(), asFortran.str()),
+              symAddr.getLoc());
           mlir::omp::MapInfoOp mapOp = createMapInfoOp(
-              firOpBuilder, clauseLocation, symAddr,
+              firOpBuilder, location, symAddr,
               /*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
               /*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{},
               static_cast<
@@ -228,9 +246,9 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
                   mapTypeBits),
               mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
 
-          if (object.sym()->owner().IsDerivedType()) {
-            addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
-                                        semaCtx);
+          if (parentObj.has_value()) {
+            addChildIndexAndMapToParent(
+                object, parentMemberIndices[parentObj.value()], mapOp, semaCtx);
           } else {
             result.mapVars.push_back(mapOp);
             mapSymbols.push_back(object.sym());
@@ -238,9 +256,9 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
         }
       });
 
-  insertChildMapInfoIntoParent(converter, parentMemberIndices, result.mapVars,
-                               mapSymbols,
-                               /*mapSymTypes=*/nullptr, /*mapSymLocs=*/nullptr);
+  insertChildMapInfoIntoParent(
+      converter, semaCtx, parentMemberIndices, result.mapVars,
+      /*mapSymTypes=*/nullptr, /*mapSymLocs=*/nullptr, &mapSymbols);
   return clauseFound;
 }
 
diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h
index 98fb5dcf7722e..5270bb3307420 100644
--- a/flang/lib/Lower/OpenMP/Clauses.h
+++ b/flang/lib/Lower/OpenMP/Clauses.h
@@ -55,6 +55,13 @@ struct IdTyTemplate {
     return designator == other.designator;
   }
 
+  // defining an "ordering" which allows types derived from this to be
+  // utilised in maps and other containers that require comparison
+  // operators for ordering
+  bool operator<(const IdTyTemplate &other) const {
+    return symbol < other.symbol;
+  }
+
   operator bool() const { return symbol != nullptr; }
 };
 
@@ -76,6 +83,10 @@ struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
   Fortran::semantics::Symbol *sym() const { return identity.symbol; }
   const std::optional<ExprTy> &ref() const { return identity.designator; }
 
+  bool operator<(const ObjectT<IdTy, ExprTy> &other) const {
+    return identity < other.identity;
+  }
+
   IdTy identity;
 };
 } // namespace tomp::type
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index 8aeef175ad2d2..3b08f1204fd2e 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -11,18 +11,20 @@
 //===----------------------------------------------------------------------===//
 
 #include "Utils.h"
+#include "Clauses.h"
+#include "DirectivesCommon.h"
 
 #include "Clauses.h"
 #include <flang/Lower/AbstractConverter.h>
 #include <flang/Lower/ConvertType.h>
 #include <flang/Lower/PFTBuilder.h>
+#include <flang/Lower/Support/Utils.h>
 #include <flang/Optimizer/Builder/FIRBuilder.h>
 #include <flang/Parser/parse-tree.h>
 #include <flang/Parser/tools.h>
 #include <flang/Semantics/tools.h>
 #include <llvm/Support/CommandLine.h>
 
-#include <algorithm>
 #include <numeric>
 
 llvm::cl::opt<bool> treatIndexAsSection(
@@ -141,6 +143,110 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc,
   return op;
 }
 
+omp::ObjectList gatherObjects(omp::Object obj,
+                              semantics::SemanticsContext &semaCtx) {
+  omp::ObjectList objList;
+  std::optional<omp::Object> baseObj = getBaseObject(obj, semaCtx);
+  while (baseObj.has_value()) {
+    objList.push_back(baseObj.value());
+    baseObj = getBaseObject(baseObj.value(), semaCtx);
+  }
+  return omp::ObjectList{llvm::reverse(objList)};
+}
+
+bool duplicateMemberMapInfo(OmpMapMemberIndicesData &parentMembers,
+                            llvm::SmallVectorImpl<int> &memberIndices) {
+  // A variation of std:equal that supports non-equal length index lists for our
+  // specific use-case, if one is larger than the other, we use -1, the default
+  // filler element in place of the smaller vector, this prevents UB from over
+  // indexing and removes the need for us to do any filling of intermediate
+  // index lists we'll discard.
+  auto isEqual = [](auto first1, auto last1, auto first2, auto last2) {
+    int v1, v2;
+    for (; first1 != last1; ++first1, ++first2) {
+      v1 = (first1 == last1) ? -1 : *first1;
+      v2 = (first2 == last2) ? -1 : *first2;
+
+      if (!(v1 == v2))
+        return false;
+    }
+    return true;
+  };
+
+  for (auto memberData : parentMembers.memberPlacementIndices)
+    if (isEqual(memberData.begin(), memberData.end(), memberIndices.begin(),
+                memberIndices.end()))
+      return true;
+  return false;
+}
+
+// When mapping members of derived types, there is a chance that one of the
+// members along the way to a mapped member is an descriptor. In which case
+// we have to make sure we generate a map for those along the way otherwise
+// we will be missing a chunk of data required to actually map the member
+// type to device. This function effectively generates these maps and the
+// appropriate data accesses required to generate these maps. It will avoid
+// creating duplicate maps, as duplicates are just as bad as unmapped
+// descriptor data in a lot of cases for the runtime (and unnecessary
+// data movement should be avoided where possible)
+mlir::Value createParentSymAndGenIntermediateMaps(
+    mlir::Location clauseLocation, Fortran::lower::AbstractConverter &converter,
+    omp::ObjectList &objectList, llvm::SmallVector<int> &indices,
+    OmpMapMemberIndicesData &parentMemberIndices, std::string asFortran,
+    llvm::omp::OpenMPOffloadMappingFlags mapTypeBits) {
+  fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+  Fortran::lower::AddrAndBoundsInfo parentBaseAddr =
+      Fortran::lower::getDataOperandBaseAddr(
+          converter, firOpBuilder, *objectList[0].sym(), clauseLocation);
+  mlir::Value curValue = parentBaseAddr.addr;
+
+  for (size_t i = 0; i < objectList.size(); ++i) {
+    mlir::Type unwrappedTy =
+        fir::unwrapSequenceType(fir::unwrapPassByRefType(curValue.getType()));
+    if (fir::RecordType recordType =
+            mlir::dyn_cast_or_null<fir::RecordType>(unwrappedTy)) {
+      mlir::Value idxConst = firOpBuilder.createIntegerConstant(
+          clauseLocation, firOpBuilder.getIndexType(), indices[i]);
+      mlir::Type memberTy = recordType.getTypeList().at(indices[i]).second;
+      curValue = firOpBuilder.create<fir::CoordinateOp>(
+          clauseLocation, firOpBuilder.getRefType(memberTy), curValue,
+          idxConst);
+
+      if ((i != indices.size() - 1) && fir::isTypeWithDescriptor(memberTy)) {
+        llvm::SmallVector<int> intermIndices = indices;
+        std::fill(std::next(intermIndices.begin(), i + 1), intermIndices.end(),
+                  -1);
+        if (!duplicateMemberMapInfo(parentMemberIndices, intermIndices)) {
+          // TODO: Perhaps generate bounds for these intermediate maps, as it
+          // may be required for cases such as:
+          //    dtype(1)%second(3)%array
+          // where second is an allocatable (and dtype may be an allocatable as
+          // well, although in this case I am not sure the fortran syntax would
+          // be legal)
+          mlir::omp::MapInfoOp mapOp = createMapInfoOp(
+              firOpBuilder, clauseLocation, curValue,
+              /*varPtrPtr=*/mlir::Value{}, asFortran,
+              /*bounds=*/llvm::SmallVector<mlir::Value>{},
+              /*members=*/{},
+              /*membersIndex=*/mlir::DenseIntElementsAttr{},
+              static_cast<
+                  std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
+                  mapTypeBits),
+              mlir::omp::VariableCaptureKind::ByRef, curValue.getType());
+
+          parentMemberIndices.memberPlacementIndices.push_back(intermIndices);
+          parentMemberIndices.memberMap.push_back(mapOp);
+        }
+
+        if (i != indices.size() - 1)
+          curValue = firOpBuilder.create<fir::LoadOp>(clauseLocation, curValue);
+      }
+    }
+  }
+
+  return curValue;
+}
+
 static int
 getComponentPlacementInParent(const semantics::Symbol *componentSym) {
   const auto *derived = componentSym->owner()
@@ -189,85 +295,60 @@ generateMemberPlacementIndices(const Object &object,
   indices = llvm::SmallVector<int>{llvm::reverse(indices)};
 }
 
-void addChildIndexAndMapToParent(
-    const omp::Object &object,
-    std::map<const semantics::Symbol *,
-             llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
-    mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx) {
-  std::optional<evaluate::DataRef> dataRef = ExtractDataRef(object.ref());
-  assert(dataRef.has_value() &&
-         "DataRef could not be extracted during mapping of derived type "
-         "cannot proceed");
-  const semantics::Symbol *parentSym = &dataRef->GetFirstSymbol();
-  assert(parentSym && "Could not find parent symbol during lower of "
-                      "a component member in OpenMP map clause");
+void addChildIndexAndMapToParent(const omp::Object &object,
+                                 OmpMapMemberIndicesData &parentMemberIndices,
+                                 mlir::omp::MapInfoOp &mapOp,
+                                 semantics::SemanticsContext &semaCtx) {
   llvm::SmallVector<int> indices;
   generateMemberPlacementIndices(object, indices, semaCtx);
-  parentMemberIndices[parentSym].push_back({indices, mapOp});
+  parentMemberIndices.memberPlacementIndices.push_back(indices);
+  parentMemberIndices.memberMap.push_back(mapOp);
 }
 
-static void calculateShapeAndFillIndices(
-    llvm::SmallVectorImpl<int64_t> &shape,
-    llvm::SmallVectorImpl<OmpMapMemberIndicesData> &memberPlacementData) {
-  shape.push_back(memberPlacementData.size());
-  size_t largestIndicesSize =
-      std::max_element(memberPlacementData.begin(), memberPlacementData.end(),
-                       [](auto a, auto b) {
-                         return a.memberPlacementIndices.size() <
-                                b.memberPlacementIndices.size();
-                       })
-          ->memberPlacementIndices.size();
-  shape.push_back(largestIndicesSize);
-
-  // DenseElementsAttr expects a rectangular shape for the data, so all
-  // index lists have to be of the same length, this emplaces -1 as filler.
-  for (auto &v : memberPlacementData) {
-    if (v.memberPlacementIndices.size() < largestIndicesSize) {
-      auto *prevEnd = v.memberPlacementIndices.end();
-      v.memberPlacementIndices.resize(largestIndicesSize);
-      std::fill(prevEnd, v.memberPlacementIndices.end(), -1);
...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/96266


More information about the llvm-branch-commits mailing list