[flang-commits] [flang] 278d49f - [flang][MIF] Adding common features related to coarray (#215576)
via flang-commits
flang-commits at lists.llvm.org
Thu Aug 13 00:01:35 PDT 2026
Author: Jean-Didier PAILLEUX
Date: 2026-08-13T09:01:30+02:00
New Revision: 278d49f46cac1997bd4b8236b80d744d96fb3220
URL: https://github.com/llvm/llvm-project/commit/278d49f46cac1997bd4b8236b80d744d96fb3220
DIFF: https://github.com/llvm/llvm-project/commit/278d49f46cac1997bd4b8236b80d744d96fb3220.diff
LOG: [flang][MIF] Adding common features related to coarray (#215576)
These features are included in PRs #212777 and #210283.
They add utilities for constructing a cosubscripts vector from a
`CoarrayRef`, a function for retrieving the index image in the initial
team, and the lowering for an `hlfir.designate` of a `CoarrayRef`, which
is treated the same way as an `ArrayRef`.
---------
Co-authored-by: Dan Bonachea <dobonachea at lbl.gov>
Added:
Modified:
flang/include/flang/Lower/MultiImageFortran.h
flang/lib/Lower/Bridge.cpp
flang/lib/Lower/ConvertExprToHLFIR.cpp
flang/lib/Lower/MultiImageFortran.cpp
flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Lower/MultiImageFortran.h b/flang/include/flang/Lower/MultiImageFortran.h
index c9b9e9f17cf39..1f247ee46c3a9 100644
--- a/flang/include/flang/Lower/MultiImageFortran.h
+++ b/flang/include/flang/Lower/MultiImageFortran.h
@@ -63,6 +63,10 @@ void genFormTeamStatement(AbstractConverter &, pft::Evaluation &eval,
// COARRAY utils
//===----------------------------------------------------------------------===//
+mlir::SmallVector<mlir::Value>
+getCosubscripts(AbstractConverter &converter, mlir::Location loc,
+ const evaluate::CoarrayRef &expr);
+
mlir::Value genLowerCoBounds(AbstractConverter &converter, mlir::Location loc,
const semantics::Symbol &sym);
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index d8ccedc4675cc..bff6b51e50e18 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -821,6 +821,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
Fortran::lower::StatementContext &context,
mlir::Location *locPtr = nullptr) override final {
mlir::Location loc = locPtr ? *locPtr : toLocation();
+ auto coarrayRef = Fortran::evaluate::ExtractCoarrayRef(expr);
+ if (coarrayRef.has_value())
+ TODO(loc, "coarray: genExprAddr of coarray reference.");
return Fortran::lower::convertExprToAddress(loc, *this, expr, localSymbols,
context);
}
@@ -830,6 +833,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
Fortran::lower::StatementContext &context,
mlir::Location *locPtr = nullptr) override final {
mlir::Location loc = locPtr ? *locPtr : toLocation();
+ auto coarrayRef = Fortran::evaluate::ExtractCoarrayRef(expr);
+ if (coarrayRef.has_value())
+ TODO(loc, "coarray: genExprValue of coarray reference.");
return Fortran::lower::convertExprToValue(loc, *this, expr, localSymbols,
context);
}
@@ -837,6 +843,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
fir::ExtendedValue
genExprBox(mlir::Location loc, const Fortran::lower::SomeExpr &expr,
Fortran::lower::StatementContext &stmtCtx) override final {
+ auto coarrayRef = Fortran::evaluate::ExtractCoarrayRef(expr);
+ if (coarrayRef.has_value())
+ TODO(loc, "coarray: genExprBox of coarray reference.");
return Fortran::lower::convertExprToBox(loc, *this, expr, localSymbols,
stmtCtx);
}
@@ -5501,6 +5510,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
if (hasCUDAImplicitTransfer && !isInDeviceContext)
implicitTemps = genCUDAImplicitDataTransfer(builder, loc, assign);
+ if (Fortran::evaluate::ExtractCoarrayRef(assign.lhs) ||
+ Fortran::evaluate::ExtractCoarrayRef(assign.rhs))
+ TODO(loc, "coarray: assignment");
+
// Gather some information about the assignment that will impact how it is
// lowered.
const bool lhsIsWholeAllocatable =
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index f8ac40337aaae..24c990141be55 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -402,11 +402,116 @@ class HlfirDesignatorBuilder {
fir::FortranVariableOpInterface
gen(const Fortran::evaluate::CoarrayRef &coarrayRef) {
- TODO(getLoc(), "coarray: lowering a reference to a coarray object");
+ PartInfo partInfo;
+ mlir::Type resultType = visit(coarrayRef, partInfo);
+ return genDesignate(resultType, partInfo, coarrayRef);
}
- mlir::Type visit(const Fortran::evaluate::CoarrayRef &, PartInfo &) {
- TODO(getLoc(), "coarray: lowering a reference to a coarray object");
+ mlir::Type visit(const Fortran::evaluate::CoarrayRef &coarrayRef,
+ PartInfo &partInfo) {
+ // Coarray is a data entity with corank > 0 that must be scalar
+ // or array.
+ mlir::Type baseType = visit(coarrayRef.base().GetLastSymbol(), partInfo);
+ if (auto seqType = mlir::dyn_cast<fir::SequenceType>(baseType)) {
+ fir::FirOpBuilder &builder = getBuilder();
+ mlir::Location loc = getLoc();
+ mlir::Type idxTy = builder.getIndexType();
+ llvm::SmallVector<std::pair<mlir::Value, mlir::Value>> bounds;
+ auto getBaseBounds = [&](unsigned i) {
+ if (bounds.empty()) {
+ bounds = hlfir::genBounds(loc, builder, partInfo.base.value());
+ assert(!bounds.empty() &&
+ "failed to compute implicit array section bounds");
+ }
+ return bounds[i];
+ };
+
+ auto frontEndResultShape = Fortran::evaluate::GetShape(
+ converter.getFoldingContext(), coarrayRef);
+ auto tryGettingExtentFromFrontEnd = [&](unsigned dim)
+ -> std::pair<mlir::Value, fir::SequenceType::Extent> {
+ // Use constant extent if possible. The main advantage to do this now
+ // is to get the best FIR array types as possible while lowering.
+ if (frontEndResultShape)
+ if (auto maybeI64 =
+ Fortran::evaluate::ToInt64(frontEndResultShape->at(dim)))
+ return {builder.createIntegerConstant(loc, idxTy, *maybeI64),
+ *maybeI64};
+ return {mlir::Value{}, fir::SequenceType::getUnknownExtent()};
+ };
+
+ llvm::SmallVector<mlir::Value> resultExtents;
+ fir::SequenceType::Shape resultTypeShape;
+ bool sawVectorSubscripts = false;
+ if (auto *arrayRef{
+ std::get_if<Fortran::evaluate::ArrayRef>(&coarrayRef.base().u)}) {
+ for (auto subscript : llvm::enumerate(arrayRef->subscript())) {
+ if (const auto *triplet = std::get_if<Fortran::evaluate::Triplet>(
+ &subscript.value().u)) {
+ mlir::Value lb, ub;
+ if (const auto &lbExpr = triplet->lower())
+ lb = genSubscript(*lbExpr);
+ else
+ lb = getBaseBounds(subscript.index()).first;
+ if (const auto &ubExpr = triplet->upper())
+ ub = genSubscript(*ubExpr);
+ else
+ ub = getBaseBounds(subscript.index()).second;
+ lb = builder.createConvert(loc, idxTy, lb);
+ ub = builder.createConvert(loc, idxTy, ub);
+ mlir::Value stride = genSubscript(triplet->stride());
+ stride = builder.createConvert(loc, idxTy, stride);
+ auto [extentValue, shapeExtent] =
+ tryGettingExtentFromFrontEnd(resultExtents.size());
+ resultTypeShape.push_back(shapeExtent);
+ if (!extentValue)
+ extentValue =
+ builder.genExtentFromTriplet(loc, lb, ub, stride, idxTy);
+ resultExtents.push_back(extentValue);
+ partInfo.subscripts.emplace_back(
+ hlfir::DesignateOp::Triplet{lb, ub, stride});
+ } else {
+ const auto &expr =
+ std::get<Fortran::evaluate::IndirectSubscriptIntegerExpr>(
+ subscript.value().u)
+ .value();
+ hlfir::Entity subscript = genSubscript(expr);
+ partInfo.subscripts.push_back(subscript);
+ if (expr.Rank() > 0) {
+ sawVectorSubscripts = true;
+ auto [extentValue, shapeExtent] =
+ tryGettingExtentFromFrontEnd(resultExtents.size());
+ resultTypeShape.push_back(shapeExtent);
+ if (!extentValue)
+ extentValue =
+ hlfir::genExtent(loc, builder, subscript, /*dim=*/0);
+ resultExtents.push_back(extentValue);
+ }
+ }
+ }
+ }
+ assert(resultExtents.size() == resultTypeShape.size() &&
+ "inconsistent hlfir.designate shape");
+
+ // For vector subscripts, create an hlfir.elemental_addr and continue
+ // lowering the designator inside it as if it was addressing an element of
+ // the vector subscripts.
+ if (sawVectorSubscripts)
+ TODO(loc, "coarray: with vector subscripts.");
+
+ mlir::Type resultType = seqType.getEleTy();
+ if (!resultTypeShape.empty()) {
+ // Ranked array section. The result shape comes from the array section
+ // subscripts.
+ resultType = fir::SequenceType::get(resultTypeShape, resultType);
+ assert(!partInfo.resultShape &&
+ "Fortran designator can only have one ranked part");
+ partInfo.resultShape = builder.genShape(loc, resultExtents);
+ }
+ return resultType;
+ } else {
+ return baseType;
+ }
}
fir::FortranVariableOpInterface
diff --git a/flang/lib/Lower/MultiImageFortran.cpp b/flang/lib/Lower/MultiImageFortran.cpp
index 12149a537ec29..931bc5e66b3cf 100644
--- a/flang/lib/Lower/MultiImageFortran.cpp
+++ b/flang/lib/Lower/MultiImageFortran.cpp
@@ -263,6 +263,34 @@ void Fortran::lower::genFormTeamStatement(
// COARRAY utils
//===----------------------------------------------------------------------===//
+/// Generates a vector of cosubscripts from CoarrayRef
+mlir::SmallVector<mlir::Value>
+Fortran::lower::getCosubscripts(Fortran::lower::AbstractConverter &converter,
+ mlir::Location loc,
+ const Fortran::evaluate::CoarrayRef &expr) {
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ Fortran::lower::StatementContext stmtCtx;
+ mlir::SmallVector<mlir::Value> cosubscripts;
+
+ // Creation of the cosubscripts vector
+ mlir::Type i64Ty = builder.getI64Type();
+ unsigned corank = expr.cosubscript().size();
+ for (unsigned dim = 0; dim < corank; ++dim) {
+ auto cosub = ToInt64(expr.cosubscript()[dim]);
+ mlir::Value idx;
+ if (cosub.has_value())
+ idx = builder.createIntegerConstant(loc, i64Ty, cosub.value());
+ else {
+ auto s = ignoreEvConvert(expr.cosubscript()[dim]);
+ idx = builder.createConvert(
+ loc, i64Ty, fir::getBase(converter.genExprValue(loc, s, stmtCtx)));
+ }
+
+ cosubscripts.push_back(idx);
+ }
+ return cosubscripts;
+}
+
mlir::Value
Fortran::lower::genLowerCoBounds(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
diff --git a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
index fb3c794c0cd9e..1a392c0b16a9a 100644
--- a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
+++ b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
@@ -346,6 +346,65 @@ mlir::Value genTerminationOperationWrapper(fir::FirOpBuilder &builder,
return fir::AddrOfOp::create(builder, loc, funcType, symbolRef);
}
+// Generates the image index relative to the initial team, regardless of which
+// team is selected. Generates a call to the `prif_initial_team_index` function
+// (analogous to `prif_image_index`) if `cosubcripts` contains at least one
+// value; otherwise, it takes `this_image` from the initial team.
+[[maybe_unused]] static mlir::Value
+getInitialTeamIndex(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value coarrayHandle,
+ llvm::SmallVector<mlir::Value> cosubscripts) {
+ mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());
+ mlir::Type i32Ty = builder.getI32Type();
+ mlir::Type i64Ty = builder.getI64Type();
+ mlir::Type boxArrTy = genBoxedSequenceType(i64Ty);
+ mlir::Value index = builder.createTemporary(loc, i32Ty);
+
+ // If there are no subscripts, the current image index is used.
+ if (cosubscripts.size() == 0) {
+ mlir::Value res = builder.createTemporary(loc, i32Ty);
+ // In iso_fortran_env.f90, INITIAL_TEAM is -2
+ mlir::Value initialTeam =
+ builder.createIntegerConstant(loc, builder.getI32Type(), -2);
+ mlir::Value team = mif::GetTeamOp::create(
+ builder, loc, builder.getRefType(builder.getNoneType()), initialTeam);
+ mlir::Value thisImage = mif::ThisImageOp::create(builder, loc, team);
+ fir::StoreOp::create(builder, loc, thisImage, res);
+ return res;
+ }
+
+ mlir::FunctionType ftype = mlir::FunctionType::get(
+ builder.getContext(),
+ /*inputs*/
+ {boxTy, boxArrTy, builder.getRefType(i32Ty), builder.getRefType(i32Ty)},
+ /*results*/ {});
+ mlir::func::FuncOp funcOp =
+ builder.createFunction(loc, getPRIFProcName("initial_team_index"), ftype);
+
+ // Creation of sub
+ unsigned corank = cosubscripts.size();
+ mlir::Type indexType = builder.getIndexType();
+ mlir::Type arrayType = fir::SequenceType::get(
+ {static_cast<fir::SequenceType::Extent>(corank)}, i64Ty);
+ mlir::Value sub = builder.createTemporary(loc, arrayType);
+ mlir::Type addrType = builder.getRefType(i64Ty);
+ for (unsigned i = 0; i < corank; ++i) {
+ mlir::Value cs = builder.createConvert(loc, i64Ty, cosubscripts[i]);
+ auto cs_index = builder.createIntegerConstant(loc, indexType, i);
+ auto addr =
+ fir::CoordinateOp::create(builder, loc, addrType, sub, cs_index);
+ fir::StoreOp::create(builder, loc, cs, addr);
+ }
+ sub = builder.createBox(loc, sub);
+
+ mlir::Value stat =
+ fir::AbsentOp::create(builder, loc, getPRIFStatType(builder));
+ llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+ builder, loc, ftype, coarrayHandle, sub, index, stat);
+ fir::CallOp::create(builder, loc, funcOp, args);
+ return index;
+}
+
/// Convert mif.init operation to runtime call of 'prif_init'
struct MIFInitOpConversion : public mlir::OpRewritePattern<mif::InitOp> {
using OpRewritePattern::OpRewritePattern;
More information about the flang-commits
mailing list