[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