[flang] [llvm] [Flang] Adding lowering for the allocation and deallocation of coarrays (PR #182110)
Dan Bonachea via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 5 21:01:45 PST 2026
================
@@ -47,6 +54,239 @@ static mlir::Type getPRIFErrmsgType(fir::FirOpBuilder &builder) {
builder.getContext(), 1, fir::CharacterType::unknownLen()));
}
+static mlir::Type
+genBoxedSequenceType(mlir::Type eleTy,
+ std::optional<int64_t> rank = std::nullopt) {
+ if (rank.has_value())
+ return fir::BoxType::get(fir::SequenceType::get({rank.value()}, eleTy));
+ return fir::BoxType::get(
+ fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, eleTy));
+}
+
+static mlir::Type getCoarrayHandleType(fir::FirOpBuilder &builder,
+ mlir::Location loc) {
+ // Defining the coarray handle type
+ std::string handleDTName =
+ fir::NameUniquer::doType({"prif"}, {}, 0, "prif_coarray_handle", {});
+ fir::RecordType handleTy =
+ fir::RecordType::get(builder.getContext(), handleDTName);
+ mlir::Type infoTy =
+ fir::BoxType::get(fir::PointerType::get(builder.getNoneType()));
+ handleTy.finalize({}, {{"info", infoTy}});
+
+ // Checking if the type information was generated
+ fir::TypeInfoOp dt;
+ fir::RecordType parentType{};
+ mlir::OpBuilder::InsertPoint insertPointIfCreated;
+ std::tie(dt, insertPointIfCreated) =
+ builder.createTypeInfoOp(loc, handleTy, parentType);
+ if (insertPointIfCreated.isSet()) {
+ // fir.type_info wasn't built in a previous call.
+ dt->setAttr(dt.getNoInitAttrName(), builder.getUnitAttr());
+ dt->setAttr(dt.getNoDestroyAttrName(), builder.getUnitAttr());
+ dt->setAttr(dt.getNoFinalAttrName(), builder.getUnitAttr());
+ builder.restoreInsertionPoint(insertPointIfCreated);
+ // Create global op
+ // FIXME: replace handleTy by the Derived type that describe handleTy
+ std::string globalName =
+ fir::NameUniquer::getTypeDescriptorName(handleDTName);
+ auto linkage = builder.createLinkOnceODRLinkage();
+ builder.createGlobal(loc, handleTy, globalName, linkage);
+ }
+ return handleTy;
+}
+
+mlir::Value getCoarrayHandle(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value coarray) {
+ mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());
+ std::string uniqName = mif::getFullUniqName(coarray);
+ if (!uniqName.empty()) {
+ std::string globalName = uniqName + coarrayHandleSuffix.str();
+ mlir::SymbolRefAttr symAttr =
+ mlir::SymbolRefAttr::get(builder.getContext(), globalName);
+ mlir::Value coarrayHandle =
+ fir::AddrOfOp::create(builder, loc, builder.getRefType(boxTy), symAttr);
+ return fir::LoadOp::create(builder, loc, coarrayHandle);
+ }
+ mlir::emitError(coarray.getLoc(),
+ "Unable to locate the coarray handle for this argument.");
+ return mlir::Value{};
+}
+
+// Function to generate the PRIF runtime function call to retrieve
+// the number of images in the current team
+static mlir::Value getNumImages(fir::FirOpBuilder &builder,
+ mlir::Location loc) {
+ mlir::Type i32Ty = builder.getI32Type();
+ mlir::Value result = builder.createTemporary(loc, i32Ty);
+ mlir::FunctionType ftype = mlir::FunctionType::get(
+ builder.getContext(),
+ /*inputs*/ {builder.getRefType(i32Ty)}, /*results*/ {});
+ mlir::func::FuncOp funcOp =
+ builder.createFunction(loc, getPRIFProcName("num_images"), ftype);
+ llvm::SmallVector<mlir::Value> args =
+ fir::runtime::createArguments(builder, loc, ftype, result);
+ fir::CallOp::create(builder, loc, funcOp, args);
+ return fir::LoadOp::create(builder, loc, result);
+}
+
+static std::pair<mlir::Value, mlir::Value>
+genCoBounds(fir::FirOpBuilder &builder, mlir::Location loc,
+ mif::AllocCoarrayOp op) {
+ mlir::Value ucobounds, lcobounds;
+ mlir::DenseI64ArrayAttr lcbsAttr = op.getLcoboundsAttr();
+ mlir::DenseI64ArrayAttr ucbsAttr = op.getUcoboundsAttr();
+
+ size_t corank = lcbsAttr.size();
+ mlir::Type i64Ty = builder.getI64Type();
+ mlir::Type addrType = builder.getRefType(i64Ty);
+ mlir::Type arrayType = fir::SequenceType::get(
+ {static_cast<fir::SequenceType::Extent>(corank)}, i64Ty);
+ lcobounds = builder.createTemporary(loc, arrayType);
+ ucobounds = builder.createTemporary(loc, arrayType);
+
+ for (size_t i = 0; i < corank; i++) {
+ auto index = builder.createIntegerConstant(loc, builder.getIndexType(), i);
+ // Lower cobounds
+ auto lcovalue = builder.createIntegerConstant(loc, i64Ty, lcbsAttr[i]);
+ auto lcoaddr =
+ fir::CoordinateOp::create(builder, loc, addrType, lcobounds, index);
+ fir::StoreOp::create(builder, loc, lcovalue, lcoaddr);
+
+ // Upper cobounds
+ auto ucovalue = builder.createIntegerConstant(loc, i64Ty, ucbsAttr[i]);
+ auto ucoaddr =
+ fir::CoordinateOp::create(builder, loc, addrType, ucobounds, index);
+ fir::StoreOp::create(builder, loc, ucovalue, ucoaddr);
+ }
+
+ lcobounds = builder.createBox(loc, lcobounds);
+ ucobounds = builder.createBox(loc, ucobounds);
+
+ // Computing last ucobound
+ mlir::func::FuncOp func =
+ fir::runtime::getRuntimeFunc<mkRTKey(ComputeLastUcobound)>(loc, builder);
+ mlir::Value numImages = getNumImages(builder, loc);
+ llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+ builder, loc, func.getFunctionType(), numImages, lcobounds, ucobounds);
+ fir::CallOp::create(builder, loc, func, args);
----------------
bonachea wrote:
As mentioned in my previous comment in [flang-rt/lib/runtime/coarray.cpp](https://github.com/llvm/llvm-project/pull/182110/changes#diff-1de7f58af2d00b2528cead47a3eb5829a87227ce8c3c6eaaeb4928fcd65cf93c), the final element of `ucobounds` can now be removed (so it has `corank-1` elements), and then this block of code can be deleted, along with the definition of `ComputeLastUcobound`.
https://github.com/llvm/llvm-project/pull/182110
More information about the llvm-commits
mailing list