Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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: 2 additions & 0 deletions flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ struct IntrinsicLibrary {
void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genReduce(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genReduceDim(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genRepeat(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genReshape(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genRRSpacing(mlir::Type resultType,
Expand Down
182 changes: 177 additions & 5 deletions flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Runtime/reduce.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/MLIRContext.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -52,6 +53,34 @@ namespace fir::runtime {
using TypeBuilderFunc = mlir::Type (*)(mlir::MLIRContext *);
using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *);

#define REDUCTION_OPERATION_MODEL(T) \
template <> \
constexpr TypeBuilderFunc \
getModel<Fortran::runtime::ReductionOperation<T>>() { \
return [](mlir::MLIRContext *context) -> mlir::Type { \
TypeBuilderFunc f{getModel<T>()}; \
auto refTy = fir::ReferenceType::get(f(context)); \
return mlir::FunctionType::get(context, {refTy, refTy}, refTy); \
}; \
}

#define REDUCTION_CHAR_OPERATION_MODEL(T) \
template <> \
constexpr TypeBuilderFunc \
getModel<Fortran::runtime::ReductionCharOperation<T>>() { \
return [](mlir::MLIRContext *context) -> mlir::Type { \
TypeBuilderFunc f{getModel<T>()}; \
auto voidTy = fir::LLVMPointerType::get( \
context, mlir::IntegerType::get(context, 8)); \
auto size_tTy = \
mlir::IntegerType::get(context, 8 * sizeof(std::size_t)); \
auto refTy = fir::ReferenceType::get(f(context)); \
return mlir::FunctionType::get( \
context, {refTy, size_tTy, refTy, refTy, size_tTy, size_tTy}, \
voidTy); \
}; \
}

//===----------------------------------------------------------------------===//
// Type builder models
//===----------------------------------------------------------------------===//
Expand All @@ -75,14 +104,24 @@ constexpr TypeBuilderFunc getModel<unsigned int>() {
return mlir::IntegerType::get(context, 8 * sizeof(unsigned int));
};
}

template <>
constexpr TypeBuilderFunc getModel<short int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 8 * sizeof(short int));
};
}
template <>
constexpr TypeBuilderFunc getModel<short int *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
TypeBuilderFunc f{getModel<short int>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<const short int *>() {
return getModel<short int *>();
}
template <>
constexpr TypeBuilderFunc getModel<int>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 8 * sizeof(int));
Expand All @@ -96,6 +135,17 @@ constexpr TypeBuilderFunc getModel<int &>() {
};
}
template <>
constexpr TypeBuilderFunc getModel<int *>() {
return getModel<int &>();
}
template <>
constexpr TypeBuilderFunc getModel<const int *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
TypeBuilderFunc f{getModel<int>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<char *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return fir::ReferenceType::get(mlir::IntegerType::get(context, 8));
Expand Down Expand Up @@ -130,6 +180,43 @@ constexpr TypeBuilderFunc getModel<signed char>() {
};
}
template <>
constexpr TypeBuilderFunc getModel<signed char *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
TypeBuilderFunc f{getModel<signed char>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<const signed char *>() {
return getModel<signed char *>();
}
template <>
constexpr TypeBuilderFunc getModel<char16_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 8 * sizeof(char16_t));
};
}
template <>
constexpr TypeBuilderFunc getModel<char16_t *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
TypeBuilderFunc f{getModel<char16_t>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<char32_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 8 * sizeof(char32_t));
};
}
template <>
constexpr TypeBuilderFunc getModel<char32_t *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
TypeBuilderFunc f{getModel<char32_t>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<unsigned char>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 8 * sizeof(unsigned char));
Expand Down Expand Up @@ -175,6 +262,10 @@ constexpr TypeBuilderFunc getModel<long *>() {
return getModel<long &>();
}
template <>
constexpr TypeBuilderFunc getModel<const long *>() {
return getModel<long *>();
}
template <>
constexpr TypeBuilderFunc getModel<long long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 8 * sizeof(long long));
Expand All @@ -198,6 +289,7 @@ template <>
constexpr TypeBuilderFunc getModel<long long *>() {
return getModel<long long &>();
}

template <>
constexpr TypeBuilderFunc getModel<unsigned long>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
Expand Down Expand Up @@ -228,6 +320,27 @@ constexpr TypeBuilderFunc getModel<double *>() {
return getModel<double &>();
}
template <>
constexpr TypeBuilderFunc getModel<const double *>() {
return getModel<double *>();
}
template <>
constexpr TypeBuilderFunc getModel<long double>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::FloatType::getF80(context);
};
}
template <>
constexpr TypeBuilderFunc getModel<long double *>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
TypeBuilderFunc f{getModel<long double>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<const long double *>() {
return getModel<long double *>();
}
template <>
constexpr TypeBuilderFunc getModel<float>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::FloatType::getF32(context);
Expand All @@ -245,6 +358,10 @@ constexpr TypeBuilderFunc getModel<float *>() {
return getModel<float &>();
}
template <>
constexpr TypeBuilderFunc getModel<const float *>() {
return getModel<float *>();
}
template <>
constexpr TypeBuilderFunc getModel<bool>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::IntegerType::get(context, 1);
Expand All @@ -258,20 +375,48 @@ constexpr TypeBuilderFunc getModel<bool &>() {
};
}
template <>
constexpr TypeBuilderFunc getModel<std::complex<float>>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::ComplexType::get(mlir::FloatType::getF32(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<std::complex<float> &>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
auto ty = mlir::ComplexType::get(mlir::FloatType::getF32(context));
return fir::ReferenceType::get(ty);
TypeBuilderFunc f{getModel<std::complex<float>>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<std::complex<float> *>() {
return getModel<std::complex<float> &>();
}
template <>
constexpr TypeBuilderFunc getModel<const std::complex<float> *>() {
return getModel<std::complex<float> *>();
}
template <>
constexpr TypeBuilderFunc getModel<std::complex<double>>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::ComplexType::get(mlir::FloatType::getF64(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<std::complex<double> &>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
auto ty = mlir::ComplexType::get(mlir::FloatType::getF64(context));
return fir::ReferenceType::get(ty);
TypeBuilderFunc f{getModel<std::complex<double>>()};
return fir::ReferenceType::get(f(context));
};
}
template <>
constexpr TypeBuilderFunc getModel<std::complex<double> *>() {
return getModel<std::complex<double> &>();
}
template <>
constexpr TypeBuilderFunc getModel<const std::complex<double> *>() {
return getModel<std::complex<double> *>();
}
template <>
constexpr TypeBuilderFunc getModel<c_float_complex_t>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return fir::ComplexType::get(context, sizeof(float));
Expand Down Expand Up @@ -332,6 +477,33 @@ constexpr TypeBuilderFunc getModel<void>() {
};
}

REDUCTION_OPERATION_MODEL(std::int8_t)
REDUCTION_OPERATION_MODEL(std::int16_t)
REDUCTION_OPERATION_MODEL(std::int32_t)
REDUCTION_OPERATION_MODEL(std::int64_t)
REDUCTION_OPERATION_MODEL(Fortran::common::int128_t)

REDUCTION_OPERATION_MODEL(float)
REDUCTION_OPERATION_MODEL(double)
REDUCTION_OPERATION_MODEL(long double)

REDUCTION_OPERATION_MODEL(std::complex<float>)
REDUCTION_OPERATION_MODEL(std::complex<double>)

REDUCTION_CHAR_OPERATION_MODEL(char)
REDUCTION_CHAR_OPERATION_MODEL(char16_t)
REDUCTION_CHAR_OPERATION_MODEL(char32_t)

template <>
constexpr TypeBuilderFunc
getModel<Fortran::runtime::ReductionDerivedTypeOperation>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
auto voidTy =
fir::LLVMPointerType::get(context, mlir::IntegerType::get(context, 8));
return mlir::FunctionType::get(context, {voidTy, voidTy, voidTy}, voidTy);
};
}

template <typename...>
struct RuntimeTableKey;
template <typename RT, typename... ATs>
Expand Down
16 changes: 16 additions & 0 deletions flang/include/flang/Optimizer/Builder/Runtime/Reduction.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,22 @@ void genIParityDim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
mlir::Value maskBox);

/// Generate call to `Reduce` intrinsic runtime routine. This is the version
/// that does not take a dim argument and store the result in the provided
/// result value. This is used for COMPLEX, CHARACTER and DERIVED TYPES.
void genReduce(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value arrayBox, mlir::Value operation, mlir::Value maskBox,
mlir::Value identity, mlir::Value ordered,
mlir::Value resultBox);

/// Generate call to `Reduce` intrinsic runtime routine. This is the version
/// that does not take a dim argument and return a scalare result. This is used
/// for REAL, INTEGER and LOGICAL TYPES.
mlir::Value genReduce(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value arrayBox, mlir::Value operation,
mlir::Value maskBox, mlir::Value identity,
mlir::Value ordered);

} // namespace fir::runtime

#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_REDUCTION_H
60 changes: 57 additions & 3 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,8 @@ static constexpr IntrinsicHandler handlers[]{
{"operation", asAddr},
{"dim", asValue},
{"mask", asBox, handleDynamicOptional},
{"identity", asValue},
{"ordered", asValue}}},
{"identity", asAddr, handleDynamicOptional},
{"ordered", asValue, handleDynamicOptional}}},
/*isElemental=*/false},
{"repeat",
&I::genRepeat,
Expand Down Expand Up @@ -5705,7 +5705,61 @@ void IntrinsicLibrary::genRandomSeed(llvm::ArrayRef<fir::ExtendedValue> args) {
fir::ExtendedValue
IntrinsicLibrary::genReduce(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
TODO(loc, "intrinsic: reduce");
assert(args.size() == 6);

fir::BoxValue arrayTmp = builder.createBox(loc, args[0]);
mlir::Value array = fir::getBase(arrayTmp);
mlir::Value operation = fir::getBase(args[1]);
int rank = arrayTmp.rank();
assert(rank >= 1);

mlir::Type ty = array.getType();
mlir::Type arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
mlir::Type eleTy = mlir::cast<fir::SequenceType>(arrTy).getEleTy();

// Handle optional arguments
bool absentDim = isStaticallyAbsent(args[2]);

auto mask = isStaticallyAbsent(args[3])
? builder.create<fir::AbsentOp>(
loc, fir::BoxType::get(builder.getI1Type()))
: builder.createBox(loc, args[3]);

mlir::Value identity =
isStaticallyAbsent(args[4])
? builder.create<fir::AbsentOp>(loc, fir::ReferenceType::get(eleTy))
: fir::getBase(args[4]);

mlir::Value ordered = isStaticallyAbsent(args[5])
? builder.createBool(loc, false)
: fir::getBase(args[5]);

// We call the type specific versions because the result is scalar
// in the case below.
if (absentDim || rank == 1) {
if (fir::isa_complex(eleTy) || fir::isa_derived(eleTy)) {
mlir::Value result = builder.createTemporary(loc, eleTy);
fir::runtime::genReduce(builder, loc, array, operation, mask, identity,
ordered, result);
if (fir::isa_derived(eleTy))
return result;
return builder.create<fir::LoadOp>(loc, result);
}
if (fir::isa_char(eleTy)) {
// Create mutable fir.box to be passed to the runtime for the result.
fir::MutableBoxValue resultMutableBox =
fir::factory::createTempMutableBox(builder, loc, eleTy);
mlir::Value resultIrBox =
fir::factory::getMutableIRBox(builder, loc, resultMutableBox);
fir::runtime::genReduce(builder, loc, array, operation, mask, identity,
ordered, resultIrBox);
// Handle cleanup of allocatable result descriptor and return
return readAndAddCleanUp(resultMutableBox, resultType, "REDUCE");
}
return fir::runtime::genReduce(builder, loc, array, operation, mask,
identity, ordered);
}
TODO(loc, "reduce with array result");
}

// REPEAT
Expand Down
Loading