================ @@ -88,6 +91,196 @@ void gatherFuncAndVarSyms( symbolAndClause.emplace_back(clause, *object.id()); } +mlir::omp::MapInfoOp +createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name, + llvm::ArrayRef<mlir::Value> bounds, + llvm::ArrayRef<mlir::Value> members, + mlir::DenseIntElementsAttr membersIndex, uint64_t mapType, + mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, + bool partialMap) { + if (auto boxTy = baseAddr.getType().dyn_cast<fir::BaseBoxType>()) { + baseAddr = builder.create<fir::BoxAddrOp>(loc, baseAddr); + retTy = baseAddr.getType(); + } + + mlir::TypeAttr varType = mlir::TypeAttr::get( + llvm::cast<mlir::omp::PointerLikeType>(retTy).getElementType()); + + mlir::omp::MapInfoOp op = builder.create<mlir::omp::MapInfoOp>( + loc, retTy, baseAddr, varType, varPtrPtr, members, membersIndex, bounds, + builder.getIntegerAttr(builder.getIntegerType(64, false), mapType), + builder.getAttr<mlir::omp::VariableCaptureKindAttr>(mapCaptureType), + builder.getStringAttr(name), builder.getBoolAttr(partialMap)); + + return op; +} + +static 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"); + for (auto [placement, name] : llvm::enumerate(derived->componentNames())) + if (name == componentSym->name()) + return placement; + return -1; +} + +static std::optional<Object> +getComponentObject(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::holds_alternative<evaluate::Component>(ref->u)) + return object; + + auto baseObj = getBaseObject(object.value(), semaCtx); + if (!baseObj) + return std::nullopt; + + return getComponentObject(baseObj.value(), semaCtx); +} + +void generateMemberPlacementIndices( + const Object &object, llvm::SmallVectorImpl<int> &indices, + Fortran::semantics::SemanticsContext &semaCtx) { + auto compObj = getComponentObject(object, semaCtx); + while (compObj) { + indices.push_back(getComponentPlacementInParent(compObj->id())); + compObj = + getComponentObject(getBaseObject(compObj.value(), semaCtx), semaCtx); + } + + indices = llvm::SmallVector<int>{llvm::reverse(indices)}; +} + +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); + } + } +} + +static mlir::DenseIntElementsAttr createDenseElementsAttrFromIndices( + llvm::SmallVectorImpl<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(shape, + mlir::IntegerType::get(builder.getContext(), 32)), + indicesFlattened); +} + +void insertChildMapInfoIntoParent( + Fortran::lower::AbstractConverter &converter, + std::map<const Fortran::semantics::Symbol *, + llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices, + llvm::SmallVectorImpl<mlir::Value> &mapOperands, + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &mapSyms, + llvm::SmallVectorImpl<mlir::Type> *mapSymTypes, + llvm::SmallVectorImpl<mlir::Location> *mapSymLocs) { + for (auto indices : parentMemberIndices) { + bool parentExists = false; + size_t parentIdx; + for (parentIdx = 0; parentIdx < mapSyms.size(); ++parentIdx) { + if (mapSyms[parentIdx] == indices.first) { + parentExists = true; + break; + } + } + + if (parentExists) { + auto mapOp = llvm::cast<mlir::omp::MapInfoOp>( + mapOperands[parentIdx].getDefiningOp()); + + // NOTE: To maintain appropriate SSA ordering, we move the parent map + // which will now have references to its children after the last + // of its members to be generated. This is necessary when a user + // has defined a series of parent and children maps where the parent + // precedes the children. An alternative, may be to do + // delayed generation of map info operations from the clauses and + // organize them first before generation. + mapOp->moveAfter(indices.second.back().memberMap); + + for (auto memberIndicesData : indices.second) + mapOp.getMembersMutable().append( + memberIndicesData.memberMap.getResult()); + + mapOp.setMembersIndexAttr(createDenseElementsAttrFromIndices( + indices.second, converter.getFirOpBuilder())); + } else { + // NOTE: We take the map type of the first child, this may not + // be the correct thing to do, however, we shall see. For the moment + // it allows this to work with enter and exit without causing MLIR + // verification issues. The more appropriate thing may be to take + // the "main" map type clause from the directive being used. + uint64_t mapType = indices.second[0].memberMap.getMapType().value_or(0); + + // create parent to emplace and bind members + auto origSymbol = converter.getSymbolAddress(*indices.first); ---------------- jsjodin wrote:
Nit: I think explicit types should be used if the type isn't specified on the rhs. https://github.com/llvm/llvm-project/pull/82853 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits