Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flang/docs/FortranStandardsSupport.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ the multi-image execution. The table entries are based on the document [The new
| Team arguments to other intrinsics | P | Experimental support via [PRIF](ParallelMultiImageFortranRuntime.md) |
| Coarrays allocated in teams | N | Multi-image/Coarray feature |
| Critical construct | N | Multi-image/Coarray feature |
| Events | N | Multi-image/Coarray feature |
| Events | P | Experimental support via [PRIF](ParallelMultiImageFortranRuntime.md) |
| Intrinsic move_alloc extensions | P | Multi-image/Coarray feature |
| Detecting failed and stopped images | N | Multi-image/Coarray feature |
| New and enhanced atomic subroutines | N | Multi-image/Coarray feature |
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ struct IntrinsicLibrary {
void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
fir::ExtendedValue genEtime(std::optional<mlir::Type>,
mlir::ArrayRef<fir::ExtendedValue> args);
void genEventQuery(llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genTimef(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genExtendsTypeOf(mlir::Type,
Expand Down
26 changes: 26 additions & 0 deletions flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,13 @@ def mif_DeallocCoarrayOp
// consistency semantics of surrounding accesses in the multi-image execution.
// For now we've modeled this by *deliberately* omitting mlir::MemoryEffects
// on these operations, to ensure analysis treats these ops conservatively.
//
// A call to EVENT_QUERY is not an image control statement, but is an atomic
// observation of the event variable (F23 16.9.82 p3), whose value other
// images may change at any time.
// Two queries therefore don't necessarily return the same value, and an
// unused query cannot be erased either, since it must still error-terminate
// when it fails without STAT. It follows the same modeling as above.
//===----------------------------------------------------------------------===//
def mif_EventPostOp : mif_Op<"event_post", [AttrSizedOperandSegments]> {
let summary = "Posts an event.";
Expand Down Expand Up @@ -644,4 +651,23 @@ def mif_EventWaitOp : mif_Op<"event_wait", [AttrSizedOperandSegments]> {
}];
}

def mif_EventQueryOp : mif_Op<"event_query", []> {
let summary = "Query the count of an event on the calling image.";
let description = [{
Argument: `event` shall be a noncoindexed variable of type EVENT_TYPE from the
intrinsic module ISO_FORTRAN_ENV.
Result: `count` shall be an integer scalar and indicate the current count
of EVENT.
}];

let arguments = (ins Arg<AnyRefOrBoxType>:$event,
Arg<Optional<AnyReferenceLike>>:$stat);
let results = (outs AnyInteger:$count);
let assemblyFormat = [{
$event
(`stat` $stat^ )?
attr-dict `:` functional-type(operands, results)
}];
}

#endif // FORTRAN_DIALECT_MIF_MIF_OPS
7 changes: 6 additions & 1 deletion flang/lib/Lower/ConvertCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2253,8 +2253,13 @@ genIntrinsicRefCore(Fortran::lower::PreparedActualArguments &loweredActuals,
// Trying to retrieve the corank of a variable if this is a coarray
unsigned corank = 0;
if (const Fortran::lower::SomeExpr *expr =
callContext.procRef.UnwrapArgExpr(arg.index()))
callContext.procRef.UnwrapArgExpr(arg.index())) {
corank = getCorank(*expr);
if (callContext.getProcedureName() == "event_query" && expr &&
Fortran::evaluate::ExtractCoarrayRef(*expr))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExtractCoarrayRef follows only the base of the argument's designator, not its subscripts, so this check does not stop a call with a coindexed object nested in a subscript. You can reproduce this by saving the following to repro.f90 and running flang -fcoarray -S -emit-llvm repro.f90 -o -:

subroutine q(k)
  use iso_fortran_env, only: event_type
  integer :: k
  type(event_type), save :: ev[*]
  integer, save :: n[*]
  integer :: a(10)
  call event_query(ev, a(n[k]))
end subroutine

The emitted q_ never reads k. It loads the subscript from the local n and stores the count into that element of a:

  call void @llvm.memcpy.p0.p0.i32(ptr align 8 %3, ptr align 8 @_QFqEn, i32 24, i1 false)
  %7 = getelementptr { ptr, i64, i32, i8, i8, i8, i8 }, ptr %3, i32 0, i32 0
  %8 = load ptr, ptr %7, align 8
  %9 = load i32, ptr %8, align 4
  ...
  %15 = getelementptr nusw nuw i32, ptr %4, i64 %14
  ...
  call void @_QMprifPprif_event_query(ptr %6, ptr %5, ptr null)
  %20 = load i64, ptr %5, align 8
  %21 = trunc i64 %20 to i32
  store i32 %21, ptr %15, align 4

An array element ev(n[k]) as EVENT and s(n[k]) as STAT compile the same way. Without this patch, all three calls stop with not yet implemented: intrinsic: EVENT_QUERY.

The missing image selector isn't specific to EVENT_QUERY: Without this patch, m = a(n[k]) and call system_clock(count=a(n[k])) also load the subscript from the local n. Could the check look for a coindexed object anywhere in each argument, subscripts included, for example with an evaluate::AnyTraverse visitor? Or would you prefer to leave these forms to the coarray access work in #212777?

// The only argument that can be coindexed is COUNT.
TODO(loc, "coarray: EVENT_QUERY with coindexed COUNT.");
}

if (!arg.value()) {
operands.emplace_back(fir::getAbsentIntrinsicArgument());
Expand Down
21 changes: 21 additions & 0 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,12 @@ static constexpr IntrinsicHandler handlers[]{
&I::genEtime,
{{{"values", asBox}, {"time", asBox}}},
/*isElemental=*/false},
{"event_query",
&I::genEventQuery,
{{{"event", asAddr},
{"count", asAddr},
{"stat", asAddr, handleDynamicOptional}}},
Comment thread
MattPD marked this conversation as resolved.
Resolved
/*isElemental=*/false},
{"execute_command_line",
&I::genExecuteCommandLine,
{{{"command", asBox},
Expand Down Expand Up @@ -4036,6 +4042,21 @@ IntrinsicLibrary::genEtime(std::optional<mlir::Type> resultType,
return {};
}

// EVENT_QUERY
void IntrinsicLibrary::genEventQuery(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled(loc, options);
assert(args.size() == 3);
Comment thread
JDPailleux marked this conversation as resolved.
Resolved

mlir::Value eventVarPtr = fir::getBase(args[0]);
mlir::Value count = fir::getBase(args[1]);
mlir::Value stat = fir::getBase(args[2]);

mlir::Type countTy = fir::unwrapPassByRefType(count.getType());
mlir::Value res =
mif::EventQueryOp::create(builder, loc, countTy, eventVarPtr, stat);
fir::StoreOp::create(builder, loc, res, count);
Comment thread
JDPailleux marked this conversation as resolved.
Resolved
}

// EXIT
void IntrinsicLibrary::genExit(llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 1);
Expand Down
61 changes: 50 additions & 11 deletions flang/lib/Optimizer/Transforms/MIFOpConversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,45 @@ struct MIFEventPostOpConversion
}
};

/// Convert mif.event_query operation to runtime call of 'prif_event_query'
struct MIFEventQueryOpConversion
: public mlir::OpRewritePattern<mif::EventQueryOp> {
using OpRewritePattern::OpRewritePattern;

mlir::LogicalResult
matchAndRewrite(mif::EventQueryOp 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 = getBuiltinCptrType(builder, loc);
mlir::Type i64Ty = builder.getI64Type();
mlir::FunctionType ftype = mlir::FunctionType::get(
builder.getContext(),
/*inputs*/
{builder.getRefType(ptrTy), builder.getRefType(i64Ty),
getPRIFStatType(builder)},
/*results*/ {});
mlir::func::FuncOp funcOp =
builder.createFunction(loc, getPRIFProcName("event_query"), ftype);

mlir::Value count = builder.createTemporary(loc, i64Ty);
mlir::Value stat = genStatPRIF(builder, loc, op.getStat());

mlir::Value cptrEvent =
convertRefTypeToCPtrType(builder, loc, op.getEvent());
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, ftype, cptrEvent, count, stat);
fir::CallOp::create(builder, loc, funcOp, args);

count = fir::LoadOp::create(builder, loc, count).getResult();
count = builder.createConvert(loc, op.getType(), count);
rewriter.replaceOp(op, count);
return mlir::success();
}
};

static void genCoarrayHandle(fir::FirOpBuilder &builder, mlir::ModuleOp mod,
fir::DeclareOp op) {
builder.setInsertionPointAfter(op);
Expand Down Expand Up @@ -1746,16 +1785,16 @@ void mif::populateMIFOpConversionPatterns(
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,
MIFEventPostOpConversion, MIFEventWaitOpConversion>(
patterns.insert<
MIFInitOpConversion, MIFThisImageOpConversion, MIFNumImagesOpConversion,
MIFSyncAllOpConversion, MIFSyncImagesOpConversion,
MIFSyncMemoryOpConversion, MIFSyncTeamOpConversion,
MIFCoBroadcastOpConversion, MIFCoMaxOpConversion, MIFCoMinOpConversion,
MIFCoSumOpConversion, MIFFormTeamOpConversion, MIFChangeTeamOpConversion,
MIFGetTeamOpConversion, MIFTeamNumberOpConversion,
MIFDeallocCoarrayOpConversion, MIFCoshapeOpConversion,
MIFLcoboundOpConversion, MIFUcoboundOpConversion,
MIFImageIndexOpConversion, MIFEventPostOpConversion,
MIFEventWaitOpConversion, MIFEventQueryOpConversion>(
patterns.getContext());
}
Loading