[llvm-branch-commits] [flang] [Flang][OpenMP][MLIR] Initial derived type member map support (PR #82853)

Sergio Afonso via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue May 7 08:22:32 PDT 2024


================
@@ -88,6 +91,175 @@ void gatherFuncAndVarSyms(
     symbolAndClause.emplace_back(clause, *object.id());
 }
 
+int getComponentPlacementInParent(
+    const Fortran::semantics::Symbol *componentSym) {
+  const auto *derived =
+      componentSym->owner()
+          .derivedTypeSpec()
+          ->typeSymbol()
+          .detailsIf<Fortran::semantics::DerivedTypeDetails>();
+  assert(derived &&
+         "expected derived type details when processing component symbol");
+  int placement = 0;
+  for (auto t : derived->componentNames()) {
+    if (t == componentSym->name())
+      return placement;
+    placement++;
+  }
+  return -1;
+}
+
+std::optional<Object>
+getCompObjOrNull(std::optional<Object> object,
+                 Fortran::semantics::SemanticsContext &semaCtx) {
+  if (!object)
+    return std::nullopt;
+
+  auto ref = evaluate::ExtractDataRef(*object.value().ref());
+  if (!ref)
+    return std::nullopt;
+
+  if (std::get_if<evaluate::Component>(&ref->u))
+    return object;
+
+  auto baseObj = getBaseObject(object.value(), semaCtx);
+  if (!baseObj)
+    return std::nullopt;
+
+  return getCompObjOrNull(baseObj.value(), semaCtx);
+}
+
+llvm::SmallVector<int>
+generateMemberPlacementIndices(const Object &object,
+                               Fortran::semantics::SemanticsContext &semaCtx) {
+  std::list<int> indices;
+  auto compObj = getCompObjOrNull(object, semaCtx);
+  while (compObj) {
+    indices.push_front(getComponentPlacementInParent(compObj->id()));
+    compObj =
+        getCompObjOrNull(getBaseObject(compObj.value(), semaCtx), semaCtx);
+  }
+
+  return llvm::SmallVector<int>{std::begin(indices), std::end(indices)};
+}
+
+static void calculateShapeAndFillIndices(
+    llvm::SmallVectorImpl<int64_t> &shape,
+    llvm::SmallVector<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 implaces -1 as filler
+  // values
+  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);
+    }
+}
+
+mlir::DenseIntElementsAttr createDenseElementsAttrFromIndices(
+    llvm::SmallVector<OmpMapMemberIndicesData> &memberPlacementData,
+    fir::FirOpBuilder &builder) {
+  llvm::SmallVector<int64_t> shape;
+  calculateShapeAndFillIndices(shape, memberPlacementData);
+
+  llvm::SmallVector<int> indicesFlattened = std::accumulate(
+      memberPlacementData.begin(), memberPlacementData.end(),
+      llvm::SmallVector<int>(),
+      [](llvm::SmallVector<int> &x, OmpMapMemberIndicesData &y) {
+        x.insert(x.end(), y.memberPlacementIndices.begin(),
+                 y.memberPlacementIndices.end());
+        return x;
+      });
+
+  return mlir::DenseIntElementsAttr::get(
+      mlir::VectorType::get(llvm::ArrayRef<int64_t>(shape),
+                            mlir::IntegerType::get(builder.getContext(), 32)),
+      llvm::ArrayRef<int32_t>(indicesFlattened));
+}
+
+void insertChildMapInfoIntoParent(
+    Fortran::lower::AbstractConverter &converter,
+    std::map<const Fortran::semantics::Symbol *,
+             llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
+    llvm::SmallVectorImpl<mlir::Value> &mapOperands,
+    llvm::SmallVectorImpl<mlir::Type> *mapSymTypes,
+    llvm::SmallVectorImpl<mlir::Location> *mapSymLocs,
+    llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *mapSymbols) {
+  for (auto indices : parentMemberIndices) {
+    bool parentExists = false;
+    size_t parentIdx;
+    for (parentIdx = 0; parentIdx < mapSymbols->size(); ++parentIdx)
+      if ((*mapSymbols)[parentIdx] == indices.first) {
+        parentExists = true;
+        break;
+      }
+
+    if (parentExists) {
+      auto mapOp = mlir::dyn_cast<mlir::omp::MapInfoOp>(
----------------
skatrak wrote:

That's a good point. If you have a more informative message for this case, I'm fine with you putting that in a separate assert.

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


More information about the llvm-branch-commits mailing list