[flang-commits] [flang] [Flang][MIF] Adding support of intrinsics with coarray argument (PR #192944)

via flang-commits flang-commits at lists.llvm.org
Mon Apr 20 04:21:59 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Jean-Didier PAILLEUX (JDPailleux)

<details>
<summary>Changes</summary>

Added support for intrinsics that query the coarray in argument:
- Adding lowering and operation in MIF Dialect for UCOBOUND, LCOBOUND, COSHAPE and IMAGE_INDEX
- Adding support of coarray argument for THIS_IMAGE in MIF Dialect (and the lowering)

---

Patch is 69.85 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/192944.diff


15 Files Affected:

- (modified) flang/include/flang/Optimizer/Builder/IntrinsicCall.h (+7) 
- (modified) flang/include/flang/Optimizer/Dialect/FIROpsSupport.h (+3) 
- (modified) flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td (+124-4) 
- (modified) flang/lib/Lower/ConvertCall.cpp (+51-6) 
- (modified) flang/lib/Optimizer/Builder/IntrinsicCall.cpp (+93-5) 
- (modified) flang/lib/Optimizer/Dialect/MIF/MIFOps.cpp (+117-3) 
- (modified) flang/lib/Optimizer/Transforms/MIFOpConversion.cpp (+252-19) 
- (added) flang/test/Fir/MIF/cobound.mlir (+93) 
- (added) flang/test/Fir/MIF/coshape.mlir (+78) 
- (added) flang/test/Fir/MIF/image_index.mlir (+67) 
- (modified) flang/test/Fir/MIF/this_image.mlir (+56-7) 
- (added) flang/test/Lower/MIF/cobound.f90 (+21) 
- (added) flang/test/Lower/MIF/coshape.f90 (+14) 
- (added) flang/test/Lower/MIF/image_index.f90 (+20) 
- (modified) flang/test/Lower/MIF/this_image.f90 (+8-2) 


``````````diff
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index ca9677a8cb2b1..adf05affecc41 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -176,6 +176,7 @@ struct IntrinsicLibrary {
                                          llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genCmplx(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genConjg(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  fir::ExtendedValue genCoshape(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   void genCpuTime(llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genCshift(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -295,6 +296,8 @@ struct IntrinsicLibrary {
   mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIeeeValue(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIeor(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  fir::ExtendedValue genImageIndex(mlir::Type,
+                                   llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genIndex(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genIparity(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -309,6 +312,8 @@ struct IntrinsicLibrary {
   mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  fir::ExtendedValue genLcobound(mlir::Type,
+                                 llvm::ArrayRef<fir::ExtendedValue>);
   mlir::Value genLeadz(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genLen(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genLenTrim(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -415,6 +420,8 @@ struct IntrinsicLibrary {
                                   llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genTrim(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genUbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  fir::ExtendedValue genUcobound(mlir::Type,
+                                 llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genUnlink(std::optional<mlir::Type> resultType,
                                llvm::ArrayRef<fir::ExtendedValue> args);
   fir::ExtendedValue genUnpack(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
index b014d925592cb..9e168ffe90d0d 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
@@ -136,6 +136,9 @@ static constexpr llvm::StringRef getAccessGroupsAttrName() {
   return "access_groups";
 }
 
+/// Attribute to mark coarray Fortran entities with the CORANK attribute.
+constexpr llvm::StringRef getCorankAttrName() { return "fir.corank"; }
+
 /// Does the function, \p func, have a host-associations tuple argument?
 /// Some internal procedures may have access to host procedure variables.
 bool hasHostAssociationArgument(mlir::func::FuncOp func);
diff --git a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
index 7df274b5697f3..f39ea71e93ffd 100644
--- a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
+++ b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
@@ -102,11 +102,13 @@ def mif_ThisImageOp : mif_Op<"this_image", [AttrSizedOperandSegments]> {
     value 5, `this_image(A)` has the value [5, 0, 0].
   }];
 
-  let arguments = (ins Optional<fir_BoxType>:$coarray,
-      Optional<AnyInteger>:$dim, Optional<AnyRefOrBoxType>:$team);
-  let results = (outs I32:$res);
+  let arguments = (ins Optional<AnyType>:$coarray, Optional<AnyInteger>:$dim,
+      Optional<AnyRefOrBoxType>:$team);
+  let results = (outs AnyType:$res);
 
-  let builders = [OpBuilder<(ins "mlir::Value":$coarray, "mlir::Value":$team)>,
+  let builders = [OpBuilder<(ins "mlir::Value":$coarray, "mlir::Value":$dim,
+                      "mlir::Value":$team)>,
+                  OpBuilder<(ins "mlir::Value":$coarray, "mlir::Value":$team)>,
                   OpBuilder<(ins "mlir::Value":$team)>];
 
   let hasVerifier = 1;
@@ -118,6 +120,124 @@ def mif_ThisImageOp : mif_Op<"this_image", [AttrSizedOperandSegments]> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// Coarray Queries
+//===----------------------------------------------------------------------===//
+
+def mif_ImageIndexOp : mif_Op<"image_index", [AttrSizedOperandSegments]> {
+  let summary = "Image index from cosubscripts.";
+  let description = [{
+    Arguments:
+      - `coarray`: Shall be a coarray of any type.
+      - `sub`: rank-one integer array of size equal to the corank of `coarray`.
+      - `team`: Shall be a scalar of type `team_type` from ISO_FORTRAN_ENV.
+      - `team_number`: It shall identify the initial team or a sibling team 
+        of the current team.
+
+    Usage:
+    - Case(1) : `call image_index(coarray, sub)`
+    - Case(2) : `call image_index(coarray, sub, team)`
+    - Case(3) : `call image_index(coarray, sub, team_number)`
+
+    Result: If the value of `sub` is a valid sequence of cosubscripts for `coarray` in the
+      team specified by `team` or `team_number`, or the current team if neither `team` nor
+      `team_number` appears, the result is the index of the corresponding image in that team.
+      Otherwise, the result is zero.
+  }];
+
+  let arguments = (ins AnyType:$coarray, fir_BoxType:$sub,
+      Optional<AnyRefOrBoxType>:$team, Optional<AnyInteger>:$team_number);
+  let builders = [OpBuilder<(ins "mlir::Value":$coarray, "mlir::Value":$sub,
+      "mlir::Value":$team)>];
+
+  let results = (outs I32);
+
+  let hasVerifier = 1;
+  let assemblyFormat = [{
+    `coarray` $coarray `sub` $sub 
+    ( `team` $team^ )? 
+    ( `team_number` $team_number^ )? 
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
+def mif_LcoboundOp : mif_Op<"lcobound", [NoMemoryEffect]> {
+  let summary = "Returns the lower cobound(s) associated with a coarray.";
+  let description = [{
+    This operation returns the lower cobound(s) associated with a coarray.
+    Arguments: 
+      - `coarray`: Shall be a coarray of any type.
+      - `dim`(optional) : Shall be an integer scalar. Its value shall be in the range of
+          `1 <= DIM <= N`, where `N` is the corank of the coarray.
+    Results:
+      - Case(1): If `dim` is present, the result is an integer scalar equal to
+        the lower cobound for codimension `dim`.
+      - Case(2): `dim` is absent, so the result is an array whose size matches
+        the corank of the indicated coarray.
+  }];
+
+  let arguments = (ins AnyType:$coarray, Optional<AnyInteger>:$dim);
+  let results = (outs AnyType);
+
+  let builders = [OpBuilder<(ins "mlir::Value":$coarray, "mlir::Value":$dim)>,
+                  OpBuilder<(ins "mlir::Value":$coarray)>];
+
+  let hasVerifier = 1;
+  let assemblyFormat = [{
+    `coarray` $coarray 
+    ( `dim` $dim^ )? 
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
+def mif_UcoboundOp : mif_Op<"ucobound", [NoMemoryEffect]> {
+  let summary = "Returns the upper cobound(s) associated with a coarray.";
+  let description = [{
+    This operation returns the upper cobound(s) associated with a coarray.
+    Arguments: 
+      - `coarray`: Shall be a coarray of any type.
+      - `dim`(optional) : Shall be an integer scalar. Its value shall be in the range of
+          `1 <= DIM <= N`, where `N` is the corank of the coarray.
+    Results:
+      - Case(1): If `dim` is present, the result is an integer scalar equal to
+        the upper cobound for codimension `dim`.
+      - Case(2): `dim` is absent, so the result is an array whose size matches
+        the corank of the indicated coarray.
+  }];
+
+  let arguments = (ins AnyType:$coarray, Optional<AnyInteger>:$dim);
+  let results = (outs AnyType);
+
+  let builders = [OpBuilder<(ins "mlir::Value":$coarray, "mlir::Value":$dim)>,
+                  OpBuilder<(ins "mlir::Value":$coarray)>];
+
+  let hasVerifier = 1;
+  let assemblyFormat = [{
+    `coarray` $coarray 
+    ( `dim` $dim^ )? 
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
+def mif_CoshapeOp : mif_Op<"coshape", [NoMemoryEffect]> {
+  let summary = "Return the sizes of codimensions of a coarray.";
+  let description = [{
+    Argument: `coarray`: Shall be a coarray of any type.
+    Result : Is an array whose size matches the corank of the indicated coarray and
+       returns `UCOBOUND - LCOBOUND + 1`.
+  }];
+
+  let arguments = (ins AnyType:$coarray);
+  let builders = [OpBuilder<(ins "mlir::Value":$coarray)>];
+  let results = (outs AnyBoxedArray);
+
+  let hasVerifier = 1;
+  let assemblyFormat = [{
+    `coarray` $coarray 
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // Synchronization
 //===----------------------------------------------------------------------===//
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index ea65a49355330..ada0708931b4e 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -2149,6 +2149,22 @@ static std::optional<hlfir::EntityWithAttributes> genCustomIntrinsicRefCore(
       loc, builder, result, ".tmp.custom_intrinsic_result")}};
 }
 
+static mlir::IntegerAttr
+getCorankFromExpr(fir::FirOpBuilder &builder,
+                  const Fortran::lower::SomeExpr &expr) {
+  mlir::IntegerAttr corankAttr;
+  if (auto dataRef{Fortran::evaluate::ExtractDataRef(expr)}) {
+    const Fortran::semantics::Symbol sym = dataRef->GetLastSymbol();
+    if (const auto *object =
+            sym.GetUltimate()
+                .detailsIf<Fortran::semantics::ObjectEntityDetails>())
+      if (object->coshape().size())
+        corankAttr = builder.getIntegerAttr(builder.getI32Type(),
+                                            object->coshape().size());
+  }
+  return corankAttr;
+}
+
 /// Lower calls to intrinsic procedures with actual arguments that have been
 /// pre-lowered but have not yet been prepared according to the interface.
 static std::optional<hlfir::EntityWithAttributes>
@@ -2172,6 +2188,11 @@ genIntrinsicRefCore(Fortran::lower::PreparedActualArguments &loweredActuals,
   const fir::IntrinsicArgumentLoweringRules *argLowering =
       intrinsicEntry.getArgumentLoweringRules();
   for (auto arg : llvm::enumerate(loweredActuals)) {
+    // Trying to retrieve the corank of a variable if this is a coarray
+    mlir::IntegerAttr corankAttr;
+    if (const Fortran::lower::SomeExpr *expr =
+            callContext.procRef.UnwrapArgExpr(arg.index()))
+      corankAttr = getCorankFromExpr(builder, *expr);
     if (!arg.value()) {
       operands.emplace_back(fir::getAbsentIntrinsicArgument());
       continue;
@@ -2221,6 +2242,9 @@ genIntrinsicRefCore(Fortran::lower::PreparedActualArguments &loweredActuals,
             genOptionalValue(builder, loc, getActualFortranElementType(),
                              getActualCb, isPresent);
         addToCleanups(std::move(cleanup));
+        if (corankAttr)
+          fir::getBase(exv).getDefiningOp()->setAttr(fir::getCorankAttrName(),
+                                                     corankAttr);
         operands.emplace_back(exv);
         continue;
       }
@@ -2228,6 +2252,9 @@ genIntrinsicRefCore(Fortran::lower::PreparedActualArguments &loweredActuals,
         hlfir::Entity actual = arg.value()->getActual(loc, builder);
         auto [exv, cleanup] = genOptionalAddr(builder, loc, actual, isPresent);
         addToCleanups(std::move(cleanup));
+        if (corankAttr)
+          fir::getBase(exv).getDefiningOp()->setAttr(fir::getCorankAttrName(),
+                                                     corankAttr);
         operands.emplace_back(exv);
         continue;
       }
@@ -2235,6 +2262,9 @@ genIntrinsicRefCore(Fortran::lower::PreparedActualArguments &loweredActuals,
         hlfir::Entity actual = arg.value()->getActual(loc, builder);
         auto [exv, cleanup] = genOptionalBox(builder, loc, actual, isPresent);
         addToCleanups(std::move(cleanup));
+        if (corankAttr)
+          fir::getBase(exv).getDefiningOp()->setAttr(fir::getCorankAttrName(),
+                                                     corankAttr);
         operands.emplace_back(exv);
         continue;
       }
@@ -2250,19 +2280,31 @@ genIntrinsicRefCore(Fortran::lower::PreparedActualArguments &loweredActuals,
       llvm_unreachable("bad switch");
     }
 
+    fir::ExtendedValue exv;
     hlfir::Entity actual = arg.value()->getActual(loc, builder);
     switch (argRules.lowerAs) {
     case fir::LowerIntrinsicArgAs::Value:
-      operands.emplace_back(
-          Fortran::lower::convertToValue(loc, converter, actual, stmtCtx));
+      exv = Fortran::lower::convertToValue(loc, converter, actual, stmtCtx);
+      if (corankAttr)
+        fir::getBase(exv).getDefiningOp()->setAttr(fir::getCorankAttrName(),
+                                                   corankAttr);
+      operands.emplace_back(exv);
       continue;
     case fir::LowerIntrinsicArgAs::Addr:
-      operands.emplace_back(Fortran::lower::convertToAddress(
-          loc, converter, actual, stmtCtx, getActualFortranElementType()));
+      exv = Fortran::lower::convertToAddress(loc, converter, actual, stmtCtx,
+                                             getActualFortranElementType());
+      if (corankAttr)
+        fir::getBase(exv).getDefiningOp()->setAttr(fir::getCorankAttrName(),
+                                                   corankAttr);
+      operands.emplace_back(exv);
       continue;
     case fir::LowerIntrinsicArgAs::Box:
-      operands.emplace_back(Fortran::lower::convertToBox(
-          loc, converter, actual, stmtCtx, getActualFortranElementType()));
+      exv = Fortran::lower::convertToBox(loc, converter, actual, stmtCtx,
+                                         getActualFortranElementType());
+      if (corankAttr)
+        fir::getBase(exv).getDefiningOp()->setAttr(fir::getCorankAttrName(),
+                                                   corankAttr);
+      operands.emplace_back(exv);
       continue;
     case fir::LowerIntrinsicArgAs::Inquired:
       if (const Fortran::lower::SomeExpr *expr =
@@ -2977,6 +3019,9 @@ genCustomIntrinsicRef(const Fortran::evaluate::SpecificIntrinsic *intrinsic,
     }
     if (!exv)
       llvm_unreachable("bad switch");
+    if (mlir::IntegerAttr corankAttr = getCorankFromExpr(builder, expr))
+      fir::getBase(*exv).getDefiningOp()->setAttr(fir::getCorankAttrName(),
+                                                  corankAttr);
     actual = extendedValueToHlfirEntity(loc, builder, exv.value(),
                                         "tmp.custom_intrinsic_arg");
     loweredActuals.emplace_back(Fortran::lower::PreparedActualArgument{
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 8f75b94d2f7e7..dd1c0dcd6d069 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -243,6 +243,10 @@ static constexpr IntrinsicHandler handlers[]{
     {"command_argument_count", &I::genCommandArgumentCount},
     {"conjg", &I::genConjg},
     {"cosd", &I::genCosd},
+    {"coshape",
+     &I::genCoshape,
+     {{{"coarray", asAddr}, {"kind", asValue}}},
+     false},
     {"cospi", &I::genCospi},
     {"count",
      &I::genCount,
@@ -499,6 +503,13 @@ static constexpr IntrinsicHandler handlers[]{
     {"ieee_unordered", &I::genIeeeUnordered},
     {"ieee_value", &I::genIeeeValue},
     {"ieor", &I::genIeor},
+    {"image_index",
+     &I::genImageIndex,
+     {{{"coarray", asAddr},
+       {"sub", asBox},
+       {"team", asAddr},
+       {"team_number", asAddr}}},
+     /*isElemental*/ false},
     {"index",
      &I::genIndex,
      {{{"string", asAddr},
@@ -529,6 +540,10 @@ static constexpr IntrinsicHandler handlers[]{
      &I::genLbound,
      {{{"array", asInquired}, {"dim", asValue}, {"kind", asValue}}},
      /*isElemental=*/false},
+    {"lcobound",
+     &I::genLcobound,
+     {{{"coarray", asAddr}, {"dim", asValue}, {"kind", asValue}}},
+     /*isElemental=*/false},
     {"leadz", &I::genLeadz},
     {"len",
      &I::genLen,
@@ -801,8 +816,8 @@ static constexpr IntrinsicHandler handlers[]{
      /*isElemental=*/false},
     {"this_image",
      &I::genThisImage,
-     {{{"coarray", asBox},
-       {"dim", asAddr},
+     {{{"coarray", asAddr},
+       {"dim", asValue},
        {"team", asBox, handleDynamicOptional}}},
      /*isElemental=*/false},
     {"time", &I::genTime, {}, /*isElemental=*/false},
@@ -827,6 +842,10 @@ static constexpr IntrinsicHandler handlers[]{
      &I::genUbound,
      {{{"array", asBox}, {"dim", asValue}, {"kind", asValue}}},
      /*isElemental=*/false},
+    {"ucobound",
+     &I::genUcobound,
+     {{{"coarray", asAddr}, {"dim", asValue}, {"kind", asValue}}},
+     /*isElemental=*/false},
     {"umaskl", &I::genMask<mlir::arith::ShLIOp>},
     {"umaskr", &I::genMask<mlir::arith::ShRUIOp>},
     {"unlink",
@@ -3568,6 +3587,17 @@ mlir::Value IntrinsicLibrary::genCospi(mlir::Type resultType,
   return getRuntimeCallGenerator("cos", ftype)(builder, loc, {arg});
 }
 
+// COSHAPE
+fir::ExtendedValue
+IntrinsicLibrary::genCoshape(mlir::Type,
+                             llvm::ArrayRef<fir::ExtendedValue> args) {
+  converter->checkCoarrayEnabled();
+  assert(args.size() == 2);
+
+  return mif::CoshapeOp::create(builder, loc,
+                                /*coarray*/ fir::getBase(args[0]));
+}
+
 // COUNT
 fir::ExtendedValue
 IntrinsicLibrary::genCount(mlir::Type resultType,
@@ -6243,6 +6273,22 @@ mlir::Value IntrinsicLibrary::genIeor(mlir::Type resultType,
                                                      args[1]);
 }
 
+// IMAGE_INDEX
+fir::ExtendedValue
+IntrinsicLibrary::genImageIndex(mlir::Type resultType,
+                                llvm::ArrayRef<fir::ExtendedValue> args) {
+  converter->checkCoarrayEnabled();
+  assert(args.size() == 2 || args.size() == 3);
+
+  mlir::Value team;
+  if (args.size() > 2) {
+    team = fir::getBase(args[2]);
+  }
+  return mif::ImageIndexOp::create(builder, loc,
+                                   /*coarray*/ fir::getBase(args[0]),
+                                   /*sub*/ fir::getBase(args[1]), team);
+}
+
 // INDEX
 fir::ExtendedValue
 IntrinsicLibrary::genIndex(mlir::Type resultType,
@@ -8257,11 +8303,21 @@ IntrinsicLibrary::genThisImage(mlir::Type resultType,
   converter->checkCoarrayEnabled();
   assert(args.size() >= 1 && args.size() <= 3);
   const bool coarrayIsAbsent = args.size() == 1;
+  const bool dimIsAbsent = args.size() < 3;
   mlir::Value team = fir::getBase(args[args.size() - 1]);
 
-  if (!coarrayIsAbsent)
-    TODO(loc, "this_image with coarray argument.");
-  mlir::Value res = mif::ThisImageOp::create(builder, loc, team);
+  if (!coarrayIsAbsent && dimIsAbsent) {
+    mlir::Value res =
+        mif::ThisImageOp::create(builder, loc, fir::getBase(args[0]), team);
+    return res;
+  }
+  mlir::Value res;
+  if (!dimIsAbsent) {
+    mlir::Value coarray = fir::getBase(args[0]);
+    mlir::Value dim = fir::getBase(args[1]);
+    res = mif::ThisImageOp::create(builder, loc, coarray, dim, team);
+  } else
+    res = mif::ThisImageOp::create(builder, loc, team);
   return builder.createConvert(loc, resultType, res);
 }
 
@@ -8366,6 +8422,22 @@ IntrinsicLibrary::genLbound(mlir::Type resultType,
       fir::runtime::genLboundDim(builder, loc, fir::getBase(box), dim));
 }
 
+// LCOBOUND
+fir::ExtendedValue
+IntrinsicLibrary::genLcobound(mlir::Type resultType,
+                              llvm::ArrayRef<fir::ExtendedValue> args) {
+  converter->checkCoarrayEnabled();
+  assert(args.size() == 2 || args.size() == 3);
+
+  mlir::Value coarray = fir::getBase(args[0]);
+  const bool dimIsAbsent = args.size() == 2 || isStaticallyAbsent(...
[truncated]

``````````

</details>


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


More information about the flang-commits mailing list