[flang-commits] [flang] [flang][Multi-Image] Moving Mutli-image lowering to PRIF into the MIF dialect (PR #161179)

via flang-commits flang-commits at lists.llvm.org
Wed Oct 8 00:58:51 PDT 2025


================
@@ -0,0 +1,263 @@
+//===-- MIFOps.td - MIF operation definitions --------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Definition of the MIF dialect operations
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_DIALECT_MIF_MIF_OPS
+#define FORTRAN_DIALECT_MIF_MIF_OPS
+
+include "flang/Optimizer/Dialect/MIF/MIFDialect.td"
+include "flang/Optimizer/Dialect/FIRTypes.td"
+include "flang/Optimizer/Dialect/FIRAttr.td"
+
+class mif_Op<string mnemonic, list<Trait> traits>
+    : Op<MIFDialect, mnemonic, traits>;
+
+//===----------------------------------------------------------------------===//
+// Initialization and Finalization
+//===----------------------------------------------------------------------===//
+
+def mif_InitOp : mif_Op<"init", []> {
+  let summary = "Initialize the parallel environment";
+  let description = [{This operation will initialize the parallel environment}];
+
+  let results = (outs I32:$stat);
+  let assemblyFormat = "`->` type($stat) attr-dict";
+}
+
+//===----------------------------------------------------------------------===//
+// Image Queries
+//===----------------------------------------------------------------------===//
+
+def mif_NumImagesOp : mif_Op<"num_images", [AttrSizedOperandSegments]> {
+  let summary = "Query the number of images in the specified or current team";
+  let description = [{
+    This operation query the number of images in the specified or current
+    team and can be called with 3 differents way :
+    - `num_images()`
+    - `num_images(team)`
+    - `num_images(team_number)`
+
+    Arguments:
+    - `team` : Shall be a scalar of type `team_type` from the `ISO_FORTRAN_ENV`
+            module with a value that identifies the current or ancestor team.
+    - `team_number` :  Shall be an integer scalar. It shall identify the
+            initial team or a sibling team of the current team.
+
+    Result Value: The number of images in the specified team, or in the current
+    team if no team is specified.
+  }];
+
+  let arguments = (ins Optional<AnyInteger>:$team_number,
+                       Optional<AnyRefOrBoxType>:$team);
+  let results = (outs I32:$res);
+
+  let builders = [OpBuilder<(ins CArg<"mlir::Value", "{}">:$teamArg)>];
+
+  let hasVerifier = 1;
+  let assemblyFormat = [{
+    ( `team_number` $team_number^ )? 
+    ( `team` $team^ )? 
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
+def mif_ThisImageOp : mif_Op<"this_image", [AttrSizedOperandSegments]> {
+  let summary = "Determine the image index of the current image";
+  let description = [{
+    Arguments:
+    - `coarray` :  Shall be a coarray of any type.
+    - `dim` : Shall be an integer scalar. Its value shall be in the range of
+          1 <= DIM <= N, where N is the corank of the coarray.
+    - `team`(optional) : Shall be a scalar of type `team_type` from
+          ISO_FORTRAN_ENV. If the `coarray` is present, it shall be
+          established in that team.
+
+    Results:
+    - Case(1) : The result of `this_image([team])` is a scalar with a value
+          equal to the index of the image in the current or specified team.
+    - Case(2) : The result of `this_image(coarray [,team])` is the sequence of
+          cosubscript values for `coarray`.
+    - Case(3) : The result of `this_image(coarray, dim [,team])` is the value of
+          cosubscript `dim` in the sequence of cosubscript values for `coarray`.
+
+    Example:
+    ```fortran
+      REAL :: A[10, 0:9, 0:*]
+    ```
+    If we take a look on the example and we are on image 5, `this_image` has the
+    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 builders = [OpBuilder<(ins "mlir::Value":$coarray, "mlir::Value":$team)>,
+                  OpBuilder<(ins "mlir::Value":$team)>];
+
+  let hasVerifier = 1;
+  let assemblyFormat = [{
+    ( `coarray` $coarray^ )? 
+    ( `team` $team^ )? 
+    ( `dim` $dim^ )? 
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+// Synchronization
+//===----------------------------------------------------------------------===//
+
+def mif_SyncAllOp : mif_Op<"sync_all", [AttrSizedOperandSegments,
+                                        MemoryEffects<[MemWrite]>]> {
----------------
jeanPerier wrote:

It is a good point that a sync operation will not only write but also read something from the runtime state.
`FullEffect` seems to imply all the memory resource is being read/written. It is not the case here, and if anything, I would imagine this is an indication that allows doing more optimizations (like deleting the first write in write after write). It is not used on any of the FIR operations.

The safest approach is to not implement the side effect interface at all, this will prevent any dialect independent optimizations involving memory. My understanding is that this is semantically equivalent to specifying `MemoryEffects<[MemRead,MemWrite,MemAlloc,MemFree]>`, with the exception that the latter imply that the operation has no memory conflict with an operation that would have MemoryEffects on something else than the DefaultRessource.

For now I would advise starting by not implementing the side effect interface at all without some deeper design and testing phase.

I checked the [MPI dialect](https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/MPI/IR/MPIOps.td) and it does not implement side effect interfaces outside of few invariant operations that they consider Pure.

Later, there is maybe a case from ensuring some optimizations like load to store forwarding of local scalars that are not involved in any multi image statements is still possible (my understanding is that an operation that either does not implement the side effect interface or has generic write effect will prevent such optimization if it is between the load and store, even if the operation does not take the address, or an alias of the address as an argument). We should likely have a discussion with the MPI dialect contributors when trying to specify side effects in a finer way.

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


More information about the flang-commits mailing list