Skip to content
Merged
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
3 changes: 3 additions & 0 deletions flang/include/flang/Lower/AbstractConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ class AbstractConverter {
virtual const Fortran::lower::pft::FunctionLikeUnit *
getCurrentFunctionUnit() const = 0;

/// Check support of Multi-image features if -fcoarray is provided
virtual void checkCoarrayEnabled() = 0;

//===--------------------------------------------------------------------===//
// Types
//===--------------------------------------------------------------------===//
Expand Down
9 changes: 0 additions & 9 deletions flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -573,15 +573,6 @@ struct IntrinsicLibrary {

void setResultMustBeFreed() { resultMustBeFreed = true; }

// Check support of coarray features
void checkCoarrayEnabled() {
if (converter &&
!converter->getFoldingContext().languageFeatures().IsEnabled(
Fortran::common::LanguageFeature::Coarray))
fir::emitFatalError(loc, "Coarrays disabled, use '-fcoarray' to enable.",
false);
}

fir::FirOpBuilder &builder;
mlir::Location loc;
bool resultMustBeFreed = false;
Expand Down
10 changes: 10 additions & 0 deletions flang/include/flang/Optimizer/Builder/Runtime/Coarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,15 @@ void genCoMin(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value A,
void genCoSum(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value A,
mlir::Value resultImage, mlir::Value stat, mlir::Value errmsg);

/// Generate call to runtime subroutine prif_sync_all
void genSyncAllStatement(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value stat, mlir::Value errmsg);
/// Generate call to runtime subroutine prif_sync_memory
void genSyncMemoryStatement(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value stat, mlir::Value errmsg);
/// Generate call to runtime subroutine prif_sync_images
void genSyncImagesStatement(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value imageSet, mlir::Value stat,
mlir::Value errmsg);
} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COARRAY_H
10 changes: 10 additions & 0 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
return currentFunctionUnit;
}

void checkCoarrayEnabled() override final {
if (!getFoldingContext().languageFeatures().IsEnabled(
Fortran::common::LanguageFeature::Coarray))
fir::emitFatalError(
getCurrentLocation(),
"Not yet implemented: Multi-image features are experimental and are "
"disabled by default, use '-fcoarray' to enable.",
false);
}

void registerTypeInfo(mlir::Location loc,
Fortran::lower::SymbolRef typeInfoSym,
const Fortran::semantics::DerivedTypeSpec &typeSpec,
Expand Down
97 changes: 91 additions & 6 deletions flang/lib/Lower/Runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "flang/Lower/OpenMP.h"
#include "flang/Lower/StatementContext.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Runtime/Coarray.h"
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
Expand Down Expand Up @@ -47,6 +48,42 @@ static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) {
builder.setInsertionPointToStart(newBlock);
}

/// Initializes values for STAT and ERRMSG
static std::pair<mlir::Value, mlir::Value> getStatAndErrmsg(
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
Fortran::lower::StatementContext stmtCtx;

mlir::Value errMsgExpr, statExpr;
for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) {
std::visit(Fortran::common::visitors{
[&](const Fortran::parser::StatVariable &statVar) {
statExpr = fir::getBase(converter.genExprAddr(
loc, Fortran::semantics::GetExpr(statVar), stmtCtx));
},
[&](const Fortran::parser::MsgVariable &errMsgVar) {
const Fortran::semantics::SomeExpr *expr =
Fortran::semantics::GetExpr(errMsgVar);
errMsgExpr = fir::getBase(
converter.genExprBox(loc, *expr, stmtCtx));
}},
statOrErr.u);
}

if (!statExpr) {
statExpr = fir::AbsentOp::create(builder, loc,
builder.getRefType(builder.getI32Type()));
}
if (!errMsgExpr) {
errMsgExpr = fir::AbsentOp::create(
builder, loc,
fir::BoxType::get(fir::CharacterType::get(
builder.getContext(), 1, fir::CharacterType::unknownLen())));
}
return {statExpr, errMsgExpr};
}

//===----------------------------------------------------------------------===//
// Misc. Fortran statements that lower to runtime calls
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -169,20 +206,68 @@ void Fortran::lower::genUnlockStatement(

void Fortran::lower::genSyncAllStatement(
Fortran::lower::AbstractConverter &converter,
const Fortran::parser::SyncAllStmt &) {
TODO(converter.getCurrentLocation(), "coarray: SYNC ALL runtime");
const Fortran::parser::SyncAllStmt &stmt) {
mlir::Location loc = converter.getCurrentLocation();
converter.checkCoarrayEnabled();

// Handle STAT and ERRMSG values
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v;
auto [statAddr, errMsgAddr] = getStatAndErrmsg(converter, loc, statOrErrList);

fir::FirOpBuilder &builder = converter.getFirOpBuilder();
fir::runtime::genSyncAllStatement(builder, loc, statAddr, errMsgAddr);
}

void Fortran::lower::genSyncImagesStatement(
Fortran::lower::AbstractConverter &converter,
const Fortran::parser::SyncImagesStmt &) {
TODO(converter.getCurrentLocation(), "coarray: SYNC IMAGES runtime");
const Fortran::parser::SyncImagesStmt &stmt) {
mlir::Location loc = converter.getCurrentLocation();
converter.checkCoarrayEnabled();
fir::FirOpBuilder &builder = converter.getFirOpBuilder();

// Handle STAT and ERRMSG values
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
auto [statAddr, errMsgAddr] = getStatAndErrmsg(converter, loc, statOrErrList);

// SYNC_IMAGES(*) is passed as count == -1 while SYNC IMAGES([]) has count
// == 0. Note further that SYNC IMAGES(*) is not semantically equivalent to
// SYNC ALL.
Fortran::lower::StatementContext stmtCtx;
mlir::Value imageSet;
const Fortran::parser::SyncImagesStmt::ImageSet &imgSet =
std::get<Fortran::parser::SyncImagesStmt::ImageSet>(stmt.t);
std::visit(Fortran::common::visitors{
[&](const Fortran::parser::IntExpr &intExpr) {
const SomeExpr *expr = Fortran::semantics::GetExpr(intExpr);
imageSet =
fir::getBase(converter.genExprBox(loc, *expr, stmtCtx));
},
[&](const Fortran::parser::Star &) {
imageSet = fir::AbsentOp::create(
builder, loc,
fir::BoxType::get(fir::SequenceType::get(
{fir::SequenceType::getUnknownExtent()},
builder.getI32Type())));
}},
imgSet.u);

fir::runtime::genSyncImagesStatement(builder, loc, imageSet, statAddr,
errMsgAddr);
}

void Fortran::lower::genSyncMemoryStatement(
Fortran::lower::AbstractConverter &converter,
const Fortran::parser::SyncMemoryStmt &) {
TODO(converter.getCurrentLocation(), "coarray: SYNC MEMORY runtime");
const Fortran::parser::SyncMemoryStmt &stmt) {
mlir::Location loc = converter.getCurrentLocation();
converter.checkCoarrayEnabled();

// Handle STAT and ERRMSG values
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v;
auto [statAddr, errMsgAddr] = getStatAndErrmsg(converter, loc, statOrErrList);

fir::FirOpBuilder &builder = converter.getFirOpBuilder();
fir::runtime::genSyncMemoryStatement(builder, loc, statAddr, errMsgAddr);
}

void Fortran::lower::genSyncTeamStatement(
Expand Down
12 changes: 6 additions & 6 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3716,7 +3716,7 @@ mlir::Value IntrinsicLibrary::genCmplx(mlir::Type resultType,

// CO_BROADCAST
void IntrinsicLibrary::genCoBroadcast(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
converter->checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value sourceImage = fir::getBase(args[1]);
mlir::Value status =
Expand All @@ -3735,7 +3735,7 @@ void IntrinsicLibrary::genCoBroadcast(llvm::ArrayRef<fir::ExtendedValue> args) {

// CO_MAX
void IntrinsicLibrary::genCoMax(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
converter->checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value refNone =
fir::AbsentOp::create(builder, loc,
Expand All @@ -3755,7 +3755,7 @@ void IntrinsicLibrary::genCoMax(llvm::ArrayRef<fir::ExtendedValue> args) {

// CO_MIN
void IntrinsicLibrary::genCoMin(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
converter->checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value refNone =
fir::AbsentOp::create(builder, loc,
Expand All @@ -3775,7 +3775,7 @@ void IntrinsicLibrary::genCoMin(llvm::ArrayRef<fir::ExtendedValue> args) {

// CO_SUM
void IntrinsicLibrary::genCoSum(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
converter->checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value absentInt =
fir::AbsentOp::create(builder, loc,
Expand Down Expand Up @@ -7438,7 +7438,7 @@ IntrinsicLibrary::genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue> args) {
fir::ExtendedValue
IntrinsicLibrary::genNumImages(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
converter->checkCoarrayEnabled();
assert(args.size() == 0 || args.size() == 1);

if (args.size())
Expand Down Expand Up @@ -8519,7 +8519,7 @@ mlir::Value IntrinsicLibrary::genThisGrid(mlir::Type resultType,
fir::ExtendedValue
IntrinsicLibrary::genThisImage(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
converter->checkCoarrayEnabled();
assert(args.size() >= 1 && args.size() <= 3);
const bool coarrayIsAbsent = args.size() == 1;
mlir::Value team =
Expand Down
61 changes: 61 additions & 0 deletions flang/lib/Optimizer/Builder/Runtime/Coarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,64 @@ void fir::runtime::genCoSum(fir::FirOpBuilder &builder, mlir::Location loc,
genCollectiveSubroutine(builder, loc, A, resultImage, stat, errmsg,
PRIFNAME_SUB("co_sum"));
}

/// Generate call to runtime subroutine prif_sync_all
void fir::runtime::genSyncAllStatement(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value stat,
mlir::Value errmsg) {
mlir::FunctionType ftype =
PRIF_FUNCTYPE(PRIF_STAT_TYPE, PRIF_ERRMSG_TYPE, PRIF_ERRMSG_TYPE);
mlir::func::FuncOp funcOp =
builder.createFunction(loc, PRIFNAME_SUB("sync_all"), ftype);

auto [errmsgArg, errmsgAllocArg] = genErrmsgPRIF(builder, loc, errmsg);
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, ftype, stat, errmsgArg, errmsgAllocArg);
fir::CallOp::create(builder, loc, funcOp, args);
}

/// Generate call to runtime subroutine prif_sync_memory
void fir::runtime::genSyncMemoryStatement(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value stat,
mlir::Value errmsg) {
mlir::FunctionType ftype =
PRIF_FUNCTYPE(PRIF_STAT_TYPE, PRIF_ERRMSG_TYPE, PRIF_ERRMSG_TYPE);
mlir::func::FuncOp funcOp =
builder.createFunction(loc, PRIFNAME_SUB("sync_memory"), ftype);

auto [errmsgArg, errmsgAllocArg] = genErrmsgPRIF(builder, loc, errmsg);
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, ftype, stat, errmsgArg, errmsgAllocArg);
fir::CallOp::create(builder, loc, funcOp, args);
}

/// Generate call to runtime subroutine prif_sync_images
void fir::runtime::genSyncImagesStatement(fir::FirOpBuilder &builder,
mlir::Location loc,
mlir::Value imageSet,
mlir::Value stat,
mlir::Value errmsg) {
mlir::Type imgSetTy = fir::BoxType::get(fir::SequenceType::get(
{fir::SequenceType::getUnknownExtent()}, builder.getI32Type()));
mlir::FunctionType ftype = PRIF_FUNCTYPE(imgSetTy, PRIF_STAT_TYPE,
PRIF_ERRMSG_TYPE, PRIF_ERRMSG_TYPE);
mlir::func::FuncOp funcOp =
builder.createFunction(loc, PRIFNAME_SUB("sync_images"), ftype);

// If imageSet is scalar, PRIF require to pass an array of size 1.
if (auto boxTy = mlir::dyn_cast<fir::BoxType>(imageSet.getType())) {
if (!mlir::isa<fir::SequenceType>(boxTy.getEleTy())) {
mlir::Value one =
builder.createIntegerConstant(loc, builder.getI32Type(), 1);
mlir::Value shape = fir::ShapeOp::create(builder, loc, one);
imageSet = fir::ReboxOp::create(
builder, loc,
fir::BoxType::get(fir::SequenceType::get({1}, builder.getI32Type())),
imageSet, shape, mlir::Value{});
}
}
auto [errmsgArg, errmsgAllocArg] = genErrmsgPRIF(builder, loc, errmsg);
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, ftype, imageSet, stat, errmsgArg, errmsgAllocArg);
fir::CallOp::create(builder, loc, funcOp, args);
}
37 changes: 37 additions & 0 deletions flang/test/Lower/Coarray/sync_all.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
! 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

program test_sync_all
implicit none
! NOCOARRAY: Not yet implemented: Multi-image features are experimental and are disabled by default, use '-fcoarray' to enable.

! COARRAY: %[[ERRMSG:.*]]:2 = hlfir.declare %[[VAL_1:.*]] typeparams %[[C_128:.*]] {uniq_name = "_QFEerror_message"} : (!fir.ref<!fir.char<1,128>>, index) -> (!fir.ref<!fir.char<1,128>>, !fir.ref<!fir.char<1,128>>)
! COARRAY: %[[STAT:.*]]:2 = hlfir.declare %[[VAL_2:.*]] {uniq_name = "_QFEsync_status"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
integer sync_status
character(len=128) :: error_message

! COARRAY: %[[VAL_3:.*]] = fir.absent !fir.ref<i32>
! COARRAY: %[[VAL_4:.*]] = fir.absent !fir.box<!fir.char<1,?>>
! COARRAY: %[[VAL_5:.*]] = fir.absent !fir.box<!fir.char<1,?>>
! COARRAY: fir.call @_QMprifPprif_sync_all(%[[VAL_3]], %[[VAL_4]], %[[VAL_5]]) fastmath<contract> : (!fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> ()
sync all

! COARRAY: %[[VAL_6:.*]] = fir.absent !fir.box<!fir.char<1,?>>
! COARRAY: %[[VAL_7:.*]] = fir.absent !fir.box<!fir.char<1,?>>
! COARRAY: fir.call @_QMprifPprif_sync_all(%[[STAT]]#0, %[[VAL_6]], %[[VAL_7]]) fastmath<contract> : (!fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> ()
sync all(stat=sync_status)

! COARRAY: %[[VAL_8:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>>
! COARRAY: %[[VAL_9:.*]] = fir.absent !fir.ref<i32>
! COARRAY: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.char<1,?>>
! COARRAY: %[[VAL_11:.*]] = fir.convert %[[VAL_8]] : (!fir.box<!fir.char<1,128>>) -> !fir.box<!fir.char<1,?>>
! COARRAY: fir.call @_QMprifPprif_sync_all(%[[VAL_9]], %[[VAL_11]], %[[VAL_10]]) fastmath<contract> : (!fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> ()
sync all( errmsg=error_message)

! COARRAY: %[[VAL_12:.*]] = fir.embox %[[ERRMSG]]#0 : (!fir.ref<!fir.char<1,128>>) -> !fir.box<!fir.char<1,128>>
! COARRAY: %[[VAL_13:.*]] = fir.absent !fir.box<!fir.char<1,?>>
! COARRAY: %[[VAL_14:.*]] = fir.convert %[[VAL_12]] : (!fir.box<!fir.char<1,128>>) -> !fir.box<!fir.char<1,?>>
! COARRAY: fir.call @_QMprifPprif_sync_all(%[[STAT]]#0, %[[VAL_14]], %[[VAL_13]]) fastmath<contract> : (!fir.ref<i32>, !fir.box<!fir.char<1,?>>, !fir.box<!fir.char<1,?>>) -> ()
sync all(stat=sync_status, errmsg=error_message)

end program test_sync_all
Loading