[flang-commits] [flang] [llvm] [flang][MIF] Adding lowering for EVENT POST/WAIT statements (PR #210283)

Jean-Didier PAILLEUX via flang-commits flang-commits at lists.llvm.org
Fri Jul 17 02:33:58 PDT 2026


https://github.com/JDPailleux created https://github.com/llvm/llvm-project/pull/210283

Adding lowering for EVENT WAIT / POST statements using the MIF dialect, as well as lowering of CoarrayRef for hlfir.designate.

>From d1f3534cf76565d5201e3b3179b2b7a6ce0e23ad Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Thu, 16 Jul 2026 13:46:28 +0200
Subject: [PATCH 1/2] [flang] Lower CoarrayRef to hlfir.designate

---
 flang/lib/Lower/ConvertExprToHLFIR.cpp | 112 ++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 3 deletions(-)

diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 6f718a8eb5926..494b608012fce 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -402,11 +402,117 @@ 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)
+        return createVectorSubscriptElementAddrOp(partInfo, baseType,
+                                                  resultExtents);
+
+      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

>From 97d536a7be31b582c4de42bcc0b5183645b34f36 Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Mon, 20 Apr 2026 14:15:08 +0200
Subject: [PATCH 2/2] [flang][MIF] Adding lowering for EVENT POST/WAIT
 statements

---
 flang-rt/lib/runtime/__fortran_builtins.f90   |   4 +-
 flang/include/flang/Lower/MultiImageFortran.h |  13 +
 flang/include/flang/Lower/Runtime.h           |   4 -
 .../flang/Optimizer/Dialect/MIF/MIFOps.td     |  52 ++++
 flang/lib/Lower/ConvertExprToHLFIR.cpp        |   5 +-
 flang/lib/Lower/MultiImageFortran.cpp         | 115 +++++++
 flang/lib/Lower/Runtime.cpp                   |  18 --
 flang/lib/Optimizer/Builder/MIFCommon.cpp     |   4 +
 .../Optimizer/Transforms/MIFOpConversion.cpp  | 281 +++++++++++++++++-
 flang/test/Fir/MIF/events.mlir                |  45 +++
 flang/test/Lower/MIF/events.f90               |  56 ++++
 11 files changed, 559 insertions(+), 38 deletions(-)
 create mode 100644 flang/test/Fir/MIF/events.mlir
 create mode 100644 flang/test/Lower/MIF/events.f90

diff --git a/flang-rt/lib/runtime/__fortran_builtins.f90 b/flang-rt/lib/runtime/__fortran_builtins.f90
index 840ad33eb2674..246c04cf1676b 100644
--- a/flang-rt/lib/runtime/__fortran_builtins.f90
+++ b/flang-rt/lib/runtime/__fortran_builtins.f90
@@ -52,7 +52,9 @@
   end type
 
   type, public :: __builtin_event_type
-    integer(kind=int64), private :: __count = -1
+    integer(kind=int64), private :: & ! 64-bytes of opaque zero-initialized data
+       __m1 = 0, __m2 = 0, __m3 = 0, __m4 = 0, &
+       __m5 = 0, __m6 = 0, __m7 = 0, __m8 = 0
   end type
 
   type, public :: __builtin_notify_type
diff --git a/flang/include/flang/Lower/MultiImageFortran.h b/flang/include/flang/Lower/MultiImageFortran.h
index c9b9e9f17cf39..f8658d665f062 100644
--- a/flang/include/flang/Lower/MultiImageFortran.h
+++ b/flang/include/flang/Lower/MultiImageFortran.h
@@ -34,6 +34,10 @@ namespace pft {
 struct Evaluation;
 } // namespace pft
 
+mlir::SmallVector<mlir::Value>
+getCosubscripts(AbstractConverter &converter, mlir::Location loc,
+                const Fortran::evaluate::CoarrayRef &expr);
+
 //===----------------------------------------------------------------------===//
 // Synchronization statements
 //===----------------------------------------------------------------------===//
@@ -81,6 +85,15 @@ void genAllocateNonAllocatableSaveCoarray(AbstractConverter &converter,
                                           const semantics::Symbol &sym,
                                           mlir::Value addr);
 
+//===----------------------------------------------------------------------===//
+// EVENT and NOTIFY statements
+//===----------------------------------------------------------------------===//
+
+void genNotifyWaitStatement(AbstractConverter &,
+                            const parser::NotifyWaitStmt &);
+void genEventPostStatement(AbstractConverter &, const parser::EventPostStmt &);
+void genEventWaitStatement(AbstractConverter &, const parser::EventWaitStmt &);
+
 //===----------------------------------------------------------------------===//
 // COARRAY expressions
 //===----------------------------------------------------------------------===//
diff --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Lower/Runtime.h
index 514345d9a89f1..fa139546d8675 100644
--- a/flang/include/flang/Lower/Runtime.h
+++ b/flang/include/flang/Lower/Runtime.h
@@ -48,10 +48,6 @@ class AbstractConverter;
 
 // Lowering of Fortran statement related runtime (other than IO and maths)
 
-void genNotifyWaitStatement(AbstractConverter &,
-                            const parser::NotifyWaitStmt &);
-void genEventPostStatement(AbstractConverter &, const parser::EventPostStmt &);
-void genEventWaitStatement(AbstractConverter &, const parser::EventWaitStmt &);
 void genLockStatement(AbstractConverter &, const parser::LockStmt &);
 void genFailImageStatement(AbstractConverter &);
 void genStopStatement(AbstractConverter &, const parser::StopStmt &);
diff --git a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
index 337a9eab0b087..769331ea6fae4 100644
--- a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
+++ b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
@@ -592,4 +592,56 @@ def mif_DeallocCoarrayOp
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// Events 
+//===----------------------------------------------------------------------===//
+
+def mif_EventPostOp : mif_Op<"event_post", [AttrSizedOperandSegments,
+                                            MemoryEffects<[MemWrite]>]> {
+  let summary = "Posts an event.";
+  let description = [{
+    This is a post-event operation.
+    Arguments: 
+      - `image_num`: Shall be an integer that correspond to the image index of 
+        the event variable.
+      - `event_var`: Shall be a coarray or be part of a coarray of 
+        type EVENT_TYPE from the intrinsic module ISO_FORTRAN_ENV.
+  }];
+
+  let arguments = (ins AnyRefOrBoxType:$event,
+      Variadic<AnyInteger>:$cosubscripts,
+      Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat,
+      Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg);
+
+  let assemblyFormat = [{
+    $event (`[` $cosubscripts^ `]` )? 
+    (`stat` $stat^ )?  (`errmsg` $errmsg^ )?
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
+def mif_EventWaitOp : mif_Op<"event_wait", [AttrSizedOperandSegments,
+                                            MemoryEffects<[MemWrite]>]> {
+  let summary = "Waits until an event is posted.";
+  let description = [{
+    Arguments: 
+      - `event`: Shall be a reference of type EVENT_TYPE from the intrinsic
+        module ISO_FORTRAN_ENV.
+      - `until_count`(optional) : Shall be an integer scalar and indicate the count of 
+        the given event variable to be waited for.
+  }];
+
+  let arguments = (ins fir_ReferenceType:$event,
+      Optional<AnyIntegerType>:$until_count,
+      Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat,
+      Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg);
+
+  let assemblyFormat = [{
+    $event 
+    (`until_count` $until_count^ )?
+    (`stat` $stat^ )?  (`errmsg` $errmsg^ )?
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
 #endif // FORTRAN_DIALECT_MIF_MIF_OPS
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 494b608012fce..4ecba1524867c 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -2477,8 +2477,11 @@ fir::ExtendedValue Fortran::lower::convertExprToBox(
     Fortran::lower::StatementContext &stmtCtx) {
   hlfir::EntityWithAttributes loweredExpr =
       HlfirBuilder(loc, converter, symMap, stmtCtx).gen(expr);
+  unsigned corank = 0;
+  if (auto coarray{evaluate::ExtractCoarrayRef(expr)})
+    corank = coarray->GetLastSymbol().Corank();
   return convertToBox(loc, converter, loweredExpr, stmtCtx,
-                      converter.genType(expr));
+                      converter.genType(expr), corank);
 }
 
 fir::ExtendedValue Fortran::lower::convertToAddress(
diff --git a/flang/lib/Lower/MultiImageFortran.cpp b/flang/lib/Lower/MultiImageFortran.cpp
index 66ffca0b850dd..c27d3905e21bc 100644
--- a/flang/lib/Lower/MultiImageFortran.cpp
+++ b/flang/lib/Lower/MultiImageFortran.cpp
@@ -21,6 +21,33 @@
 #include "flang/Semantics/expression.h"
 #include "mlir/IR/IRMapping.h"
 
+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 image = ToInt64(expr.cosubscript()[dim]);
+    mlir::Value idx;
+    if (image.has_value())
+      idx = builder.createIntegerConstant(loc, i64Ty, image.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;
+}
+
 //===----------------------------------------------------------------------===//
 // Synchronization statements
 //===----------------------------------------------------------------------===//
@@ -492,3 +519,91 @@ fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genValue(
     const Fortran::evaluate::CoarrayRef &expr) {
   TODO(converter.getCurrentLocation(), "coarray: coarray value");
 }
+
+//===----------------------------------------------------------------------===//
+// EVENT and NOTIFY statements
+//===----------------------------------------------------------------------===//
+
+void Fortran::lower::genNotifyWaitStatement(
+    Fortran::lower::AbstractConverter &converter,
+    const Fortran::parser::NotifyWaitStmt &) {
+  TODO(converter.getCurrentLocation(), "coarray: NOTIFY WAIT runtime");
+}
+
+void Fortran::lower::genEventPostStatement(
+    Fortran::lower::AbstractConverter &converter,
+    const Fortran::parser::EventPostStmt &stmt) {
+  converter.checkCoarrayEnabled();
+  mlir::Location loc = converter.getCurrentLocation();
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  Fortran::lower::StatementContext stmtCtx;
+
+  // Handle STAT and ERRMSG values
+  const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
+      std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
+  auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);
+
+  // Handle EVENT-VAR and IMAGE_NUMBER
+  auto eventExpr = Fortran::semantics::GetExpr(
+      std::get<Fortran::parser::EventVariable>(stmt.t));
+  mlir::Value eventAddr =
+      fir::getBase(converter.genExprBox(loc, *eventExpr, stmtCtx));
+  llvm::SmallVector<mlir::Value> cosubscripts;
+  if (auto coref{evaluate::ExtractCoarrayRef(eventExpr)}) {
+    cosubscripts =
+        Fortran::lower::getCosubscripts(converter, loc, coref.value());
+  }
+
+  mif::EventPostOp::create(builder, loc, eventAddr, cosubscripts, statAddr,
+                           errMsgAddr);
+}
+
+void Fortran::lower::genEventWaitStatement(
+    Fortran::lower::AbstractConverter &converter,
+    const Fortran::parser::EventWaitStmt &stmt) {
+  converter.checkCoarrayEnabled();
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  mlir::Location loc = converter.getCurrentLocation();
+  Fortran::lower::StatementContext stmtCtx;
+
+  // Handle STAT ,ERRMSG and UNTIL_COUNT
+  mlir::Value statAddr, errMsgAddr, untilCount;
+  const auto &eventSpecList =
+      std::get<std::list<Fortran::parser::EventWaitSpec>>(stmt.t);
+  for (const Fortran::parser::EventWaitSpec &eventSpec : eventSpecList) {
+    std::visit(
+        Fortran::common::visitors{
+            [&](const Fortran::parser::StatOrErrmsg &statOrErr) {
+              std::visit(
+                  Fortran::common::visitors{
+                      [&](const Fortran::parser::StatVariable &statVar) {
+                        statAddr = fir::getBase(converter.genExprAddr(
+                            loc, Fortran::semantics::GetExpr(statVar),
+                            stmtCtx));
+                      },
+                      [&](const Fortran::parser::MsgVariable &errMsgVar) {
+                        errMsgAddr = fir::getBase(converter.genExprAddr(
+                            loc, Fortran::semantics::GetExpr(errMsgVar),
+                            stmtCtx));
+                      },
+                  },
+                  statOrErr.u);
+            },
+            [&](const Fortran::parser::ScalarIntExpr &untilCountVar) {
+              untilCount = fir::getBase(converter.genExprValue(
+                  loc, Fortran::semantics::GetExpr(untilCountVar), stmtCtx));
+            },
+        },
+        eventSpec.u);
+  }
+
+  // Handle EVENT-VAR
+  mlir::Value eventVarAddr = fir::getBase(converter.genExprAddr(
+      loc,
+      Fortran::semantics::GetExpr(
+          std::get<Fortran::parser::EventVariable>(stmt.t)),
+      stmtCtx));
+
+  mif::EventWaitOp::create(builder, loc, eventVarAddr, untilCount, statAddr,
+                           errMsgAddr);
+}
diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp
index ca1a1aca89606..ae27711b96532 100644
--- a/flang/lib/Lower/Runtime.cpp
+++ b/flang/lib/Lower/Runtime.cpp
@@ -132,24 +132,6 @@ void Fortran::lower::genFailImageStatement(
   genUnreachable(builder, loc);
 }
 
-void Fortran::lower::genNotifyWaitStatement(
-    Fortran::lower::AbstractConverter &converter,
-    const Fortran::parser::NotifyWaitStmt &) {
-  TODO(converter.getCurrentLocation(), "coarray: NOTIFY WAIT runtime");
-}
-
-void Fortran::lower::genEventPostStatement(
-    Fortran::lower::AbstractConverter &converter,
-    const Fortran::parser::EventPostStmt &) {
-  TODO(converter.getCurrentLocation(), "coarray: EVENT POST runtime");
-}
-
-void Fortran::lower::genEventWaitStatement(
-    Fortran::lower::AbstractConverter &converter,
-    const Fortran::parser::EventWaitStmt &) {
-  TODO(converter.getCurrentLocation(), "coarray: EVENT WAIT runtime");
-}
-
 void Fortran::lower::genLockStatement(
     Fortran::lower::AbstractConverter &converter,
     const Fortran::parser::LockStmt &) {
diff --git a/flang/lib/Optimizer/Builder/MIFCommon.cpp b/flang/lib/Optimizer/Builder/MIFCommon.cpp
index 56225cda34fdb..e959259d8f813 100644
--- a/flang/lib/Optimizer/Builder/MIFCommon.cpp
+++ b/flang/lib/Optimizer/Builder/MIFCommon.cpp
@@ -33,6 +33,10 @@ std::string mif::getFullUniqName(mlir::Value addr) {
     return getFullUniqName(rb.getBox());
   else if (auto eb = mlir::dyn_cast<fir::EmboxOp>(op))
     return getFullUniqName(eb.getMemref());
+  else if (auto ac = mlir::dyn_cast<fir::ArrayCoorOp>(op))
+    return getFullUniqName(ac.getMemref());
+  else if (auto c = mlir::dyn_cast<fir::CoordinateOp>(op))
+    return getFullUniqName(c.getRef());
   else if (auto ebc = mlir::dyn_cast<fir::EmboxCharOp>(op))
     return getFullUniqName(ebc.getMemref());
   else if (auto c = mlir::dyn_cast<fir::CoordinateOp>(op)) {
diff --git a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
index 77dfb5ac957ea..0e7057a3d908a 100644
--- a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
+++ b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
@@ -143,6 +143,8 @@ std::int64_t getCorank(mlir::Value coarray) {
 
 static int computeElementByteSize(mlir::Location loc, mlir::Type type,
                                   fir::KindMapping &kindMap,
+                                  mlir::DataLayout *dl,
+                                  const fir::LLVMTypeConverter *typeConverter,
                                   bool emitErrorOnFailure = true) {
   auto eleTy = fir::unwrapSequenceType(type);
   if (auto t{mlir::dyn_cast<mlir::IntegerType>(eleTy)})
@@ -158,6 +160,10 @@ static int computeElementByteSize(mlir::Location loc, mlir::Type type,
   }
   if (auto t{mlir::dyn_cast<fir::CharacterType>(eleTy)})
     return kindMap.getCharacterBitsize(t.getFKind()) / 8;
+  if (fir::isa_derived(eleTy)) {
+    mlir::Type structTy = typeConverter->convertType(eleTy);
+    return dl->getTypeSizeInBits(structTy) / 8;
+  }
   if (emitErrorOnFailure)
     mlir::emitError(loc, "unsupported type");
   return 0;
@@ -178,7 +184,8 @@ static mlir::Value getSizeInBytes(fir::FirOpBuilder &builder,
   mlir::Value bytes;
   if (!mlir::dyn_cast_or_null<fir::BaseBoxType>(baseTy)) {
     if (fir::isa_trivial(baseTy)) {
-      int width = computeElementByteSize(loc, baseTy, kindMap);
+      int width =
+          computeElementByteSize(loc, baseTy, kindMap, dl, typeConverter);
       bytes = builder.createIntegerConstant(loc, builder.getI64Type(), width);
     } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(baseTy)) {
       std::size_t size = 0;
@@ -186,7 +193,8 @@ static mlir::Value getSizeInBytes(fir::FirOpBuilder &builder,
         mlir::Type structTy = typeConverter->convertType(seqTy.getEleTy());
         size = dl->getTypeSizeInBits(structTy) / 8;
       } else {
-        size = computeElementByteSize(loc, seqTy.getEleTy(), kindMap);
+        size = computeElementByteSize(loc, seqTy.getEleTy(), kindMap, dl,
+                                      typeConverter);
       }
       mlir::Value width =
           builder.createIntegerConstant(loc, builder.getI64Type(), size);
@@ -228,6 +236,86 @@ static mlir::Value getSizeInBytes(fir::FirOpBuilder &builder,
   return sizeInBytes;
 }
 
+/// Compute an offset in bytes from the beginning of the elements provided in
+/// "val". Basically, if it is not a memory access operation for an array such
+/// as fir::ArrayCoorOp or fir::CoordinateOp, then the element's offset is zero.
+static mlir::Value
+computeOffsetInBytes(fir::FirOpBuilder &builder, mlir::Location loc,
+                     mlir::ModuleOp module, mlir::DataLayout *dl,
+                     const fir::LLVMTypeConverter *typeConverter,
+                     mlir::Value val) {
+  fir::KindMapping kindMap{fir::getKindMapping(module)};
+  auto i64Ty = builder.getI64Type();
+  auto idxTy = builder.getIndexType();
+  auto zero = [&]() { return builder.createIntegerConstant(loc, i64Ty, 0); };
+  auto one = [&]() { return builder.createIntegerConstant(loc, i64Ty, 1); };
+
+  if (auto convert = val.getDefiningOp<fir::ConvertOp>())
+    return computeOffsetInBytes(builder, loc, module, dl, typeConverter,
+                                convert.getValue());
+
+  if (auto coor = val.getDefiningOp<fir::ArrayCoorOp>()) {
+    mlir::Value base = computeOffsetInBytes(builder, loc, module, dl,
+                                            typeConverter, coor.getMemref());
+    mlir::Type eleTy = fir::unwrapSequenceType(
+        fir::unwrapPassByRefType(coor.getMemref().getType()));
+    mlir::Value offset = zero();
+
+    llvm::SmallVector<mlir::Value> extents;
+    llvm::SmallVector<mlir::Value> origins;
+    if (mlir::Value shape = coor.getShape()) {
+      if (auto shapeOp = shape.getDefiningOp<fir::ShapeOp>()) {
+        extents.append(shapeOp.getExtents().begin(),
+                       shapeOp.getExtents().end());
+      } else if (auto shapeShiftOp = shape.getDefiningOp<fir::ShapeShiftOp>()) {
+        auto pairs = shapeShiftOp.getPairs();
+        for (size_t i = 0; i < pairs.size(); i += 2) {
+          origins.push_back(pairs[i]);
+          extents.push_back(pairs[i + 1]);
+        }
+      } else if (auto shiftOp = shape.getDefiningOp<fir::ShiftOp>())
+        origins.assign(shiftOp.getOrigins().begin(),
+                       shiftOp.getOrigins().end());
+    }
+
+    mlir::Value currentStride = builder.createIntegerConstant(
+        loc, i64Ty,
+        computeElementByteSize(loc, eleTy, kindMap, dl, typeConverter));
+
+    auto indices = coor.getIndices();
+    for (auto [dim, idx] : llvm::enumerate(indices)) {
+      mlir::Value lb, stride;
+      if (dim < origins.size())
+        lb = builder.createConvert(loc, i64Ty, origins[dim]);
+      else
+        lb = one();
+
+      idx = builder.createConvert(loc, i64Ty, idx);
+      idx = mlir::arith::SubIOp::create(builder, loc, idx, lb);
+      if (mlir::isa<fir::BaseBoxType>(
+              fir::unwrapRefType(coor.getMemref().getType()))) {
+        auto dims = fir::BoxDimsOp::create(
+            builder, loc, idxTy, idxTy, idxTy, coor.getMemref(),
+            builder.createIntegerConstant(loc, idxTy, dim));
+        stride = builder.createConvert(loc, i64Ty, dims.getByteStride());
+      } else {
+        stride = currentStride;
+        if (dim < extents.size()) {
+          mlir::Value ext = builder.createConvert(loc, i64Ty, extents[dim]);
+          currentStride =
+              mlir::arith::MulIOp::create(builder, loc, currentStride, ext);
+        }
+      }
+
+      mlir::Value delta =
+          mlir::arith::MulIOp::create(builder, loc, idx, stride);
+      offset = mlir::arith::AddIOp::create(builder, loc, offset, delta);
+    }
+    return mlir::arith::AddIOp::create(builder, loc, base, offset);
+  }
+  return zero();
+}
+
 // Most PRIF functions take `errmsg` and `errmsg_alloc` as two optional
 // arguments of intent (out). One is allocatable, the other is not.
 // It is the responsibility of the compiler to ensure that the appropriate
@@ -307,6 +395,60 @@ static fir::CallOp genPRIFStopErrorStop(fir::FirOpBuilder &builder,
   return fir::CallOp::create(builder, loc, funcOp, args);
 }
 
+static mlir::Value
+getInitialTeamIndex(fir::FirOpBuilder &builder, mlir::Location loc,
+                    mlir::Value coarrayHandle,
+                    llvm::SmallVector<mlir::Value> cosubscripts) {
+  mlir::Type i32Ty = builder.getI32Type();
+  mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());
+  mlir::Value index = builder.createTemporary(loc, i32Ty);
+  if (cosubscripts.size() == 0) {
+    // No cosubscripts is provided, the current image is used.
+    mlir::FunctionType ftype = mlir::FunctionType::get(
+        builder.getContext(),
+        /*inputs*/ {boxTy, builder.getRefType(i32Ty)}, /*results*/ {});
+    mlir::Value teamArg = fir::AbsentOp::create(builder, loc, boxTy);
+    mlir::func::FuncOp funcOp = builder.createFunction(
+        loc, getPRIFProcName("this_image_no_coarray"), ftype);
+    llvm::SmallVector<mlir::Value> args =
+        fir::runtime::createArguments(builder, loc, ftype, teamArg, index);
+    fir::CallOp::create(builder, loc, funcOp, args);
+    return index;
+  }
+
+  mlir::Type i64Ty = builder.getI64Type();
+  mlir::Type boxArrTy = genBoxedSequenceType(i64Ty);
+  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 index = builder.createIntegerConstant(loc, indexType, i);
+    auto addr = fir::CoordinateOp::create(builder, loc, addrType, sub, 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;
+}
+
 enum class TerminationKind { Normal = 0, Error = 1, FailImage = 2 };
 // Generates a wrapper function for the different kind of termination in PRIF.
 // This function will be used to register wrappers on PRIF runtime termination
@@ -1360,6 +1502,117 @@ struct MIFImageIndexOpConversion
   }
 };
 
+/// Convert mif.event_wait operation to runtime call of 'prif_event_wait*'
+struct MIFEventWaitOpConversion
+    : public mlir::OpRewritePattern<mif::EventWaitOp> {
+  using OpRewritePattern::OpRewritePattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(mif::EventWaitOp op,
+                  mlir::PatternRewriter &rewriter) const override {
+    auto mod = op->template getParentOfType<mlir::ModuleOp>();
+    fir::FirOpBuilder builder(rewriter, mod);
+    mlir::Location loc = op.getLoc();
+
+    mlir::Type ptrTy = fir::PointerType::get(builder.getNoneType());
+    mlir::Type i64Ty = builder.getI64Type();
+    mlir::Type errmsgTy = getPRIFErrmsgType(builder);
+    mlir::FunctionType ftype =
+        mlir::FunctionType::get(builder.getContext(),
+                                /*inputs*/
+                                {ptrTy, builder.getRefType(i64Ty),
+                                 getPRIFStatType(builder), errmsgTy, errmsgTy},
+                                /*results*/ {});
+    mlir::func::FuncOp funcOp =
+        builder.createFunction(loc, getPRIFProcName("event_wait"), ftype);
+
+    mlir::Value untilCount = builder.createTemporary(loc, i64Ty);
+    if (!op.getUntilCount())
+      untilCount =
+          fir::AbsentOp::create(builder, loc, builder.getRefType(i64Ty));
+    else {
+      untilCount = builder.createTemporary(loc, i64Ty);
+      mlir::Value u = builder.createConvert(loc, i64Ty, op.getUntilCount());
+      fir::StoreOp::create(builder, loc, u, untilCount);
+    }
+
+    mlir::Value stat = op.getStat();
+    if (!stat)
+      stat = fir::AbsentOp::create(builder, loc, getPRIFStatType(builder));
+    auto [errmsgArg, errmsgAllocArg] =
+        genErrmsgPRIF(builder, loc, op.getErrmsg());
+    llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+        builder, loc, ftype, op.getEvent(), untilCount, stat, errmsgArg,
+        errmsgAllocArg);
+    fir::CallOp callOp = fir::CallOp::create(builder, loc, funcOp, args);
+    rewriter.replaceOp(op, callOp);
+    return mlir::success();
+  }
+};
+
+/// Convert mif.event_post operation to runtime call of 'prif_event_post'
+struct MIFEventPostOpConversion
+    : public mlir::OpRewritePattern<mif::EventPostOp> {
+  using OpRewritePattern::OpRewritePattern;
+
+  MIFEventPostOpConversion(mlir::MLIRContext *context, mlir::DataLayout *dl,
+                           const fir::LLVMTypeConverter *typeConverter)
+      : OpRewritePattern(context), dl{dl}, typeConverter{typeConverter} {}
+
+  mlir::LogicalResult
+  matchAndRewrite(mif::EventPostOp op,
+                  mlir::PatternRewriter &rewriter) const override {
+    auto mod = op->template getParentOfType<mlir::ModuleOp>();
+    fir::FirOpBuilder builder(rewriter, mod);
+    mlir::Location loc = op.getLoc();
+
+    mlir::Type ptrTy = fir::PointerType::get(builder.getNoneType());
+    mlir::Type i32Ty = builder.getI32Type();
+    mlir::Type i64Ty = builder.getI64Type();
+    mlir::Type errmsgTy = getPRIFErrmsgType(builder);
+    mlir::FunctionType ftype = mlir::FunctionType::get(
+        builder.getContext(),
+        /*inputs*/
+        {builder.getRefType(i32Ty), ptrTy, builder.getRefType(i64Ty),
+         getPRIFStatType(builder), errmsgTy, errmsgTy},
+        /*results*/ {});
+    mlir::func::FuncOp funcOp =
+        builder.createFunction(loc, getPRIFProcName("event_post"), ftype);
+
+    mlir::Type eventType = fir::unwrapRefType(op.getEvent().getType());
+    bool isCoarray = false;
+    if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(eventType))
+      isCoarray = boxTy.isCoarray();
+    if (!isCoarray)
+      TODO(loc, "coarray: mif.event_post with event_var which is an "
+                "allocatable or pointer component of a coarray.");
+
+    mlir::Value offset = builder.createTemporary(loc, i64Ty);
+    mlir::Value zero = computeOffsetInBytes(builder, loc, mod, dl,
+                                            typeConverter, op.getEvent());
+    fir::StoreOp::create(builder, loc, zero, offset);
+
+    mlir::Value coarrayHandle = getCoarrayHandle(builder, loc, op.getEvent());
+    mlir::Value imageNum =
+        getInitialTeamIndex(builder, loc, coarrayHandle, op.getCosubscripts());
+    mlir::Value stat = op.getStat();
+    if (!stat)
+      stat = fir::AbsentOp::create(builder, loc, getPRIFStatType(builder));
+    auto [errmsgArg, errmsgAllocArg] =
+        genErrmsgPRIF(builder, loc, op.getErrmsg());
+    llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+        builder, loc, ftype, imageNum, coarrayHandle, offset, stat, errmsgArg,
+        errmsgAllocArg);
+    fir::CallOp callOp = fir::CallOp::create(builder, loc, funcOp, args);
+    rewriter.replaceOp(op, callOp);
+    return mlir::success();
+  }
+
+private:
+  mlir::DataLayout *dl;
+  const fir::LLVMTypeConverter *typeConverter;
+};
+
 class MIFOpConversion : public fir::impl::MIFOpConversionBase<MIFOpConversion> {
 public:
   void runOnOperation() override {
@@ -1402,17 +1655,17 @@ class MIFOpConversion : public fir::impl::MIFOpConversionBase<MIFOpConversion> {
 void mif::populateMIFOpConversionPatterns(
     const fir::LLVMTypeConverter &converter, mlir::DataLayout &dl,
     mlir::RewritePatternSet &patterns) {
-  patterns.insert<MIFAllocCoarrayOpConversion>(patterns.getContext(), &dl,
-                                               &converter);
-  patterns.insert<MIFInitOpConversion, MIFThisImageOpConversion,
-                  MIFNumImagesOpConversion, MIFSyncAllOpConversion,
-                  MIFSyncImagesOpConversion, MIFSyncMemoryOpConversion,
-                  MIFSyncTeamOpConversion, MIFCoBroadcastOpConversion,
-                  MIFCoMaxOpConversion, MIFCoMinOpConversion,
-                  MIFCoSumOpConversion, MIFFormTeamOpConversion,
-                  MIFChangeTeamOpConversion, MIFGetTeamOpConversion,
-                  MIFTeamNumberOpConversion, MIFDeallocCoarrayOpConversion,
-                  MIFCoshapeOpConversion, MIFLcoboundOpConversion,
-                  MIFUcoboundOpConversion, MIFImageIndexOpConversion>(
+  patterns.insert<MIFAllocCoarrayOpConversion, MIFEventPostOpConversion>(
+      patterns.getContext(), &dl, &converter);
+  patterns.insert<
+      MIFInitOpConversion, MIFThisImageOpConversion, MIFNumImagesOpConversion,
+      MIFSyncAllOpConversion, MIFSyncImagesOpConversion,
+      MIFSyncMemoryOpConversion, MIFSyncTeamOpConversion,
+      MIFCoBroadcastOpConversion, MIFCoMaxOpConversion, MIFCoMinOpConversion,
+      MIFCoSumOpConversion, MIFFormTeamOpConversion, MIFChangeTeamOpConversion,
+      MIFGetTeamOpConversion, MIFTeamNumberOpConversion,
+      MIFDeallocCoarrayOpConversion, MIFCoshapeOpConversion,
+      MIFLcoboundOpConversion, MIFUcoboundOpConversion,
+      MIFImageIndexOpConversion, MIFEventWaitOpConversion>(
       patterns.getContext());
 }
diff --git a/flang/test/Fir/MIF/events.mlir b/flang/test/Fir/MIF/events.mlir
new file mode 100644
index 0000000000000..0fa8cd91a19d2
--- /dev/null
+++ b/flang/test/Fir/MIF/events.mlir
@@ -0,0 +1,45 @@
+// RUN: fir-opt --mif-convert %s | FileCheck %s
+
+func.func @_QQmain() attributes {fir.bindc_name = "EVENT_TEST"} {
+  %0 = fir.alloca !fir.array<0xi64>
+  %1 = fir.alloca !fir.array<1xi64>
+  %2 = fir.dummy_scope : !fir.dscope
+  %3 = fir.address_of(@_QFEdata_ready) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>
+  %c1_i64 = arith.constant 1 : i64
+  %c0 = arith.constant 0 : index
+  %4 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<1xi64>>, index) -> !fir.ref<i64>
+  fir.store %c1_i64 to %4 : !fir.ref<i64>
+  %5 = fir.embox %1 : (!fir.ref<!fir.array<1xi64>>) -> !fir.box<!fir.array<1xi64>>
+  %6 = fir.embox %0 : (!fir.ref<!fir.array<0xi64>>) -> !fir.box<!fir.array<0xi64>>
+  mif.alloc_coarray %3 lcobounds %5 ucobounds %6 {uniq_name = "_QFEdata_ready"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>, !fir.box<!fir.array<1xi64>>, !fir.box<!fir.array<0xi64>>) -> ()
+  %7:2 = hlfir.declare %3 {uniq_name = "_QFEdata_ready"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>)
+  %8 = fir.alloca i32 {bindc_name = "me", uniq_name = "_QFEme"}
+  %9:2 = hlfir.declare %8 {uniq_name = "_QFEme"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+  %10 = mif.this_image : () -> i32
+  hlfir.assign %10 to %9#0 : i32, !fir.ref<i32>
+  %11 = fir.load %9#0 : !fir.ref<i32>
+  %c2_i32 = arith.constant 2 : i32
+  %12 = arith.cmpi eq, %11, %c2_i32 : i32
+  fir.if %12 {
+    %13 = hlfir.designate %7#0   : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>
+    %14 = fir.embox %13 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>, corank:1>
+    %c1_i64_0 = arith.constant 1 : i64
+    mif.event_post %14[%c1_i64_0] : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>, corank:1>, i64) -> ()
+  } else {
+    %13 = fir.load %9#0 : !fir.ref<i32>
+    %c1_i32 = arith.constant 1 : i32
+    %14 = arith.cmpi eq, %13, %c1_i32 : i32
+    fir.if %14 {
+      %c1_i32_0 = arith.constant 1 : i32
+      mif.event_wait %7#0 until_count %c1_i32_0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{_QM__fortran_builtinsT__builtin_event_type.__m1:i64,_QM__fortran_builtinsT__builtin_event_type.__m2:i64,_QM__fortran_builtinsT__builtin_event_type.__m3:i64,_QM__fortran_builtinsT__builtin_event_type.__m4:i64,_QM__fortran_builtinsT__builtin_event_type.__m5:i64,_QM__fortran_builtinsT__builtin_event_type.__m6:i64,_QM__fortran_builtinsT__builtin_event_type.__m7:i64,_QM__fortran_builtinsT__builtin_event_type.__m8:i64}>>, i32) -> ()
+    }
+  }
+  return
+}
+
+// CHECK: fir.call @_QMprifPprif_initial_team_index(
+// CHECK: fir.call @_QMprifPprif_event_post(%[[IMAGE_INDEX:.*]], %[[EVENT_PTR:.*]], %[[OFFSET:.*]], %[[STAT:.*]], %[[ERRMSG:.*]], %[[ERRMSG2:.*]]) : (!fir.ref<i32>, !fir.ptr<none>, !fir.ref<i64>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> ()
+
+
+// CHECK: fir.call @_QMprifPprif_event_wait(%[[EVENT_PTR:.*]], %[[UNTIL_COUNT:.*]], %[[STAT:.*]], %[[ERRMSG:.*]], %[[ERRMSG2:.*]]) : (!fir.ptr<none>, !fir.ref<i64>, !fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> ()
+
diff --git a/flang/test/Lower/MIF/events.f90 b/flang/test/Lower/MIF/events.f90
new file mode 100644
index 0000000000000..9ebf1130730ae
--- /dev/null
+++ b/flang/test/Lower/MIF/events.f90
@@ -0,0 +1,56 @@
+! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s --check-prefixes=COARRAY
+! RUN: not %flang_fc1 -emit-hlfir %s 2>&1 | FileCheck %s --check-prefixes=NOCOARRAY
+
+! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable.
+
+
+program event_test
+  use iso_fortran_env, only: event_type
+  implicit none
+  
+  type(event_type)  :: data_ready[*]
+  integer :: me
+
+  me = this_image()
+
+  if (me == 2) then
+     event post(data_ready[1])
+  else if (me == 1) then
+     event wait(data_ready, UNTIL_COUNT=1)
+  end if
+end program
+
+! COARRAY: %[[VAL_0:.*]] = fir.alloca !fir.array<0xi64>
+! COARRAY: %[[VAL_1:.*]] = fir.alloca !fir.array<1xi64>
+! COARRAY: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
+! COARRAY: %[[VAL_3:.*]] = fir.address_of(@_QFEdata_ready) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>
+! COARRAY: %c1_i64 = arith.constant 1 : i64
+! COARRAY: %c0 = arith.constant 0 : index
+! COARRAY: %[[VAL_4:.*]] = fir.coordinate_of %[[VAL_1]], %c0 : (!fir.ref<!fir.array<1xi64>>, index) -> !fir.ref<i64>
+! COARRAY: fir.store %c1_i64 to %[[VAL_4]] : !fir.ref<i64>
+! COARRAY: %[[VAL_5:.*]] = fir.embox %[[VAL_1]] : (!fir.ref<!fir.array<1xi64>>) -> !fir.box<!fir.array<1xi64>>
+! COARRAY: %[[VAL_6:.*]] = fir.embox %[[VAL_0]] : (!fir.ref<!fir.array<0xi64>>) -> !fir.box<!fir.array<0xi64>>
+! COARRAY: mif.alloc_coarray %[[VAL_3]] lcobounds %[[VAL_5]] ucobounds %[[VAL_6]] {uniq_name = "_QFEdata_ready"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>, !fir.box<!fir.array<1xi64>>, !fir.box<!fir.array<0xi64>>) -> ()
+! COARRAY: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFEdata_ready"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>)
+! COARRAY: %[[VAL_8:.*]] = fir.alloca i32 {bindc_name = "me", uniq_name = "_QFEme"}
+! COARRAY: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFEme"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! COARRAY: %[[VAL_10:.*]] = mif.this_image : () -> i32
+! COARRAY: hlfir.assign %[[VAL_10]] to %[[VAL_9]]#0 : i32, !fir.ref<i32>
+! COARRAY: %[[VAL_11:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32>
+! COARRAY: %c2_i32 = arith.constant 2 : i32
+! COARRAY: %[[VAL_12:.*]] = arith.cmpi eq, %[[VAL_11]], %c2_i32 : i32
+! COARRAY: fir.if %[[VAL_12]] {
+! COARRAY:   %[[VAL_13:.*]] = hlfir.designate %[[VAL_7]]#0   : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>
+! COARRAY:   %[[VAL_14:.*]] = fir.embox %[[VAL_13]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>) -> !fir.box<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>, corank:1>
+! COARRAY:   %c1_i64_0 = arith.constant 1 : i64
+! COARRAY:   mif.event_post %[[VAL_14]][%c1_i64_0] : (!fir.box<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>, corank:1>, i64) -> ()
+! COARRAY: } else {
+! COARRAY:   %[[VAL_15:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32>
+! COARRAY:   %c1_i32 = arith.constant 1 : i32
+! COARRAY:   %[[VAL_16:.*]] = arith.cmpi eq, %[[VAL_15]], %c1_i32 : i32
+! COARRAY:   fir.if %[[VAL_16]] {
+! COARRAY:     %c1_i32_0 = arith.constant 1 : i32
+! COARRAY:     mif.event_wait %[[VAL_7]]#0 until_count %c1_i32_0 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_event_type{{.*}}>>, i32) -> ()
+! COARRAY:   }
+! COARRAY: }
+! COARRAY: return



More information about the flang-commits mailing list