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
4 changes: 4 additions & 0 deletions flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ struct IntrinsicLibrary {
template <mlir::arith::CmpIPredicate pred>
fir::ExtendedValue genCPtrCompare(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
void genCoBroadcast(llvm::ArrayRef<fir::ExtendedValue>);
void genCoMax(llvm::ArrayRef<fir::ExtendedValue>);
void genCoMin(llvm::ArrayRef<fir::ExtendedValue>);
void genCoSum(llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genCosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genCospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
void genDateAndTime(llvm::ArrayRef<fir::ExtendedValue>);
Expand Down
22 changes: 22 additions & 0 deletions flang/include/flang/Optimizer/Builder/Runtime/Coarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ namespace fir::runtime {
return fir::NameUniquer::doProcedure({"prif"}, {}, oss.str()); \
}()

#define PRIF_STAT_TYPE builder.getRefType(builder.getI32Type())
#define PRIF_ERRMSG_TYPE \
fir::BoxType::get(fir::CharacterType::get(builder.getContext(), 1, \
fir::CharacterType::unknownLen()))

/// Generate Call to runtime prif_init
mlir::Value genInitCoarray(fir::FirOpBuilder &builder, mlir::Location loc);

Expand All @@ -49,5 +54,22 @@ mlir::Value getNumImagesWithTeam(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value getThisImage(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value team = {});

/// Generate call to runtime subroutine prif_co_broadcast
void genCoBroadcast(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value A, mlir::Value sourceImage, mlir::Value stat,
mlir::Value errmsg);

/// Generate call to runtime subroutine prif_co_max and prif_co_max_character
void genCoMax(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value A,
mlir::Value resultImage, mlir::Value stat, mlir::Value errmsg);

/// Generate call to runtime subroutine prif_co_min or prif_co_min_character
void genCoMin(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value A,
mlir::Value resultImage, mlir::Value stat, mlir::Value errmsg);

/// Generate call to runtime subroutine prif_co_sum
void genCoSum(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value A,
mlir::Value resultImage, mlir::Value stat, mlir::Value errmsg);

} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COARRAY_H
107 changes: 107 additions & 0 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,34 @@ static constexpr IntrinsicHandler handlers[]{
{"cmplx",
&I::genCmplx,
{{{"x", asValue}, {"y", asValue, handleDynamicOptional}}}},
{"co_broadcast",
&I::genCoBroadcast,
{{{"a", asBox},
{"source_image", asAddr},
{"stat", asAddr, handleDynamicOptional},
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental*/ false},
{"co_max",
&I::genCoMax,
{{{"a", asBox},
{"result_image", asAddr, handleDynamicOptional},
{"stat", asAddr, handleDynamicOptional},
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental*/ false},
{"co_min",
&I::genCoMin,
{{{"a", asBox},
{"result_image", asAddr, handleDynamicOptional},
{"stat", asAddr, handleDynamicOptional},
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental*/ false},
{"co_sum",
&I::genCoSum,
{{{"a", asBox},
{"result_image", asAddr, handleDynamicOptional},
{"stat", asAddr, handleDynamicOptional},
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental*/ false},
{"command_argument_count", &I::genCommandArgumentCount},
{"conjg", &I::genConjg},
{"cosd", &I::genCosd},
Expand Down Expand Up @@ -3686,6 +3714,85 @@ mlir::Value IntrinsicLibrary::genCmplx(mlir::Type resultType,
imag);
}

// CO_BROADCAST
void IntrinsicLibrary::genCoBroadcast(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value sourceImage = fir::getBase(args[1]);
mlir::Value status =
isStaticallyAbsent(args[2])
? fir::AbsentOp::create(builder, loc,
builder.getRefType(builder.getI32Type()))
.getResult()
: fir::getBase(args[2]);
mlir::Value errmsg =
isStaticallyAbsent(args[3])
? fir::AbsentOp::create(builder, loc, PRIF_ERRMSG_TYPE).getResult()
: fir::getBase(args[3]);
fir::runtime::genCoBroadcast(builder, loc, fir::getBase(args[0]), sourceImage,
status, errmsg);
}

// CO_MAX
void IntrinsicLibrary::genCoMax(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value refNone =
fir::AbsentOp::create(builder, loc,
builder.getRefType(builder.getI32Type()))
.getResult();
mlir::Value resultImage =
isStaticallyAbsent(args[1]) ? refNone : fir::getBase(args[1]);
mlir::Value status =
isStaticallyAbsent(args[2]) ? refNone : fir::getBase(args[2]);
mlir::Value errmsg =
isStaticallyAbsent(args[3])
? fir::AbsentOp::create(builder, loc, PRIF_ERRMSG_TYPE).getResult()
: fir::getBase(args[3]);
fir::runtime::genCoMax(builder, loc, fir::getBase(args[0]), resultImage,
status, errmsg);
}

// CO_MIN
void IntrinsicLibrary::genCoMin(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value refNone =
fir::AbsentOp::create(builder, loc,
builder.getRefType(builder.getI32Type()))
.getResult();
mlir::Value resultImage =
isStaticallyAbsent(args[1]) ? refNone : fir::getBase(args[1]);
mlir::Value status =
isStaticallyAbsent(args[2]) ? refNone : fir::getBase(args[2]);
mlir::Value errmsg =
isStaticallyAbsent(args[3])
? fir::AbsentOp::create(builder, loc, PRIF_ERRMSG_TYPE).getResult()
: fir::getBase(args[3]);
fir::runtime::genCoMin(builder, loc, fir::getBase(args[0]), resultImage,
status, errmsg);
}

// CO_SUM
void IntrinsicLibrary::genCoSum(llvm::ArrayRef<fir::ExtendedValue> args) {
checkCoarrayEnabled();
assert(args.size() == 4);
mlir::Value absentInt =
fir::AbsentOp::create(builder, loc,
builder.getRefType(builder.getI32Type()))
.getResult();
mlir::Value resultImage =
isStaticallyAbsent(args[1]) ? absentInt : fir::getBase(args[1]);
mlir::Value status =
isStaticallyAbsent(args[2]) ? absentInt : fir::getBase(args[2]);
mlir::Value errmsg =
isStaticallyAbsent(args[3])
? fir::AbsentOp::create(builder, loc, PRIF_ERRMSG_TYPE).getResult()
: fir::getBase(args[3]);
fir::runtime::genCoSum(builder, loc, fir::getBase(args[0]), resultImage,
status, errmsg);
}

// COMMAND_ARGUMENT_COUNT
fir::ExtendedValue IntrinsicLibrary::genCommandArgumentCount(
mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) {
Expand Down
99 changes: 90 additions & 9 deletions flang/lib/Optimizer/Builder/Runtime/Coarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@
using namespace Fortran::runtime;
using namespace Fortran::semantics;

// 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
// optional argument is passed, and at most one must be provided in a given
// call.
// Depending on the type of `errmsg`, this function will return the pair
// corresponding to (`errmsg`, `errmsg_alloc`).
static std::pair<mlir::Value, mlir::Value>
genErrmsgPRIF(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value errmsg) {
bool isAllocatableErrmsg = fir::isAllocatableType(errmsg.getType());

mlir::Value absent = fir::AbsentOp::create(builder, loc, PRIF_ERRMSG_TYPE);
mlir::Value errMsg = isAllocatableErrmsg ? absent : errmsg;
mlir::Value errMsgAlloc = isAllocatableErrmsg ? errmsg : absent;
return {errMsg, errMsgAlloc};
}

/// Generate Call to runtime prif_init
mlir::Value fir::runtime::genInitCoarray(fir::FirOpBuilder &builder,
mlir::Location loc) {
Expand All @@ -24,8 +42,8 @@ mlir::Value fir::runtime::genInitCoarray(fir::FirOpBuilder &builder,
builder.createFunction(loc, PRIFNAME_SUB("init"), ftype);
llvm::SmallVector<mlir::Value> args =
fir::runtime::createArguments(builder, loc, ftype, result);
builder.create<fir::CallOp>(loc, funcOp, args);
return builder.create<fir::LoadOp>(loc, result);
fir::CallOp::create(builder, loc, funcOp, args);
return fir::LoadOp::create(builder, loc, result);
}

/// Generate Call to runtime prif_num_images
Expand All @@ -38,8 +56,8 @@ mlir::Value fir::runtime::getNumImages(fir::FirOpBuilder &builder,
builder.createFunction(loc, PRIFNAME_SUB("num_images"), ftype);
llvm::SmallVector<mlir::Value> args =
fir::runtime::createArguments(builder, loc, ftype, result);
builder.create<fir::CallOp>(loc, funcOp, args);
return builder.create<fir::LoadOp>(loc, result);
fir::CallOp::create(builder, loc, funcOp, args);
return fir::LoadOp::create(builder, loc, result);
}

/// Generate Call to runtime prif_num_images_with_{team|team_number}
Expand All @@ -63,8 +81,8 @@ mlir::Value fir::runtime::getNumImagesWithTeam(fir::FirOpBuilder &builder,
team = builder.createBox(loc, team);
llvm::SmallVector<mlir::Value> args =
fir::runtime::createArguments(builder, loc, ftype, team, result);
builder.create<fir::CallOp>(loc, funcOp, args);
return builder.create<fir::LoadOp>(loc, result);
fir::CallOp::create(builder, loc, funcOp, args);
return fir::LoadOp::create(builder, loc, result);
}

/// Generate Call to runtime prif_this_image_no_coarray
Expand All @@ -78,9 +96,72 @@ mlir::Value fir::runtime::getThisImage(fir::FirOpBuilder &builder,

mlir::Value result = builder.createTemporary(loc, builder.getI32Type());
mlir::Value teamArg =
!team ? builder.create<fir::AbsentOp>(loc, boxTy) : team;
!team ? fir::AbsentOp::create(builder, loc, boxTy) : team;
llvm::SmallVector<mlir::Value> args =
fir::runtime::createArguments(builder, loc, ftype, teamArg, result);
builder.create<fir::CallOp>(loc, funcOp, args);
return builder.create<fir::LoadOp>(loc, result);
fir::CallOp::create(builder, loc, funcOp, args);
return fir::LoadOp::create(builder, loc, result);
}

/// Generate call to collective subroutines except co_reduce
/// A must be lowered as a box
void genCollectiveSubroutine(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value A, mlir::Value rootImage,
mlir::Value stat, mlir::Value errmsg,
std::string coName) {
mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());
mlir::FunctionType ftype =
PRIF_FUNCTYPE(boxTy, builder.getRefType(builder.getI32Type()),
PRIF_STAT_TYPE, PRIF_ERRMSG_TYPE, PRIF_ERRMSG_TYPE);
mlir::func::FuncOp funcOp = builder.createFunction(loc, coName, ftype);

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

/// Generate call to runtime subroutine prif_co_broadcast
void fir::runtime::genCoBroadcast(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value A,
mlir::Value sourceImage, mlir::Value stat,
mlir::Value errmsg) {
genCollectiveSubroutine(builder, loc, A, sourceImage, stat, errmsg,
PRIFNAME_SUB("co_broadcast"));
}

/// Generate call to runtime subroutine prif_co_max or prif_co_max_character
void fir::runtime::genCoMax(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value A, mlir::Value resultImage,
mlir::Value stat, mlir::Value errmsg) {
mlir::Type argTy =
fir::unwrapSequenceType(fir::unwrapPassByRefType(A.getType()));
if (mlir::isa<fir::CharacterType>(argTy))
genCollectiveSubroutine(builder, loc, A, resultImage, stat, errmsg,
PRIFNAME_SUB("co_max_character"));
else
genCollectiveSubroutine(builder, loc, A, resultImage, stat, errmsg,
PRIFNAME_SUB("co_max"));
}

/// Generate call to runtime subroutine prif_co_min or prif_co_min_character
void fir::runtime::genCoMin(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value A, mlir::Value resultImage,
mlir::Value stat, mlir::Value errmsg) {
mlir::Type argTy =
fir::unwrapSequenceType(fir::unwrapPassByRefType(A.getType()));
if (mlir::isa<fir::CharacterType>(argTy))
genCollectiveSubroutine(builder, loc, A, resultImage, stat, errmsg,
PRIFNAME_SUB("co_min_character"));
else
genCollectiveSubroutine(builder, loc, A, resultImage, stat, errmsg,
PRIFNAME_SUB("co_min"));
}

/// Generate call to runtime subroutine prif_co_sum
void fir::runtime::genCoSum(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value A, mlir::Value resultImage,
mlir::Value stat, mlir::Value errmsg) {
genCollectiveSubroutine(builder, loc, A, resultImage, stat, errmsg,
PRIFNAME_SUB("co_sum"));
}
Loading