forked from OSchip/llvm-project
[fir] Add fir reduction builder
This patch introduces a bunch of builder functions to create function calls to runtime reduction functions. This patch is part of the upstreaming effort from fir-dev branch. This patch failed previously because a macro was missing. Reviewed By: awarzynski Differential Revision: https://reviews.llvm.org/D114460 Co-authored-by: Jean Perier <jperier@nvidia.com> Co-authored-by: mleair <leairmark@gmail.com>
This commit is contained in:
parent
ce22b7f17b
commit
f6ae8e8cc7
|
@ -361,6 +361,7 @@ struct RuntimeTableEntry<RuntimeTableKey<KT>, RuntimeIdentifier<Cs...>> {
|
|||
#undef FirE
|
||||
#define FirE(L, I) (I < sizeof(L) / sizeof(*L) ? L[I] : 0)
|
||||
#define FirQuoteKey(X) #X
|
||||
#define ExpandAndQuoteKey(X) FirQuoteKey(X)
|
||||
#define FirMacroExpandKey(X) \
|
||||
FirE(X, 0), FirE(X, 1), FirE(X, 2), FirE(X, 3), FirE(X, 4), FirE(X, 5), \
|
||||
FirE(X, 6), FirE(X, 7), FirE(X, 8), FirE(X, 9), FirE(X, 10), \
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
//===-- Reduction.h -- generate calls to reduction runtime API --*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The runtime routines generated in this file are generally storing the result
|
||||
// in a descriptor (represented as a `box` in FIR). Some function might
|
||||
// have a specialization where the value is returned as a scalar value, e.g.
|
||||
// `genAll` is a specialization of `genAllDescriptor`.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_REDUCTION_H
|
||||
#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_REDUCTION_H
|
||||
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
|
||||
namespace fir {
|
||||
class ExtendedValue;
|
||||
class FirOpBuilder;
|
||||
} // namespace fir
|
||||
|
||||
namespace fir::runtime {
|
||||
|
||||
/// Generate call to `all` runtime routine.
|
||||
/// This calls the descriptor based runtime call implementation of the `all`
|
||||
/// intrinsic.
|
||||
void genAllDescriptor(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value maskBox,
|
||||
mlir::Value dim);
|
||||
|
||||
/// Generate call to `any` runtime routine.
|
||||
/// This calls the descriptor based runtime call implementation of the `any`
|
||||
/// intrinsic.
|
||||
void genAnyDescriptor(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value maskBox,
|
||||
mlir::Value dim);
|
||||
|
||||
/// Generate call to `all` runtime routine. This version of `all` is specialized
|
||||
/// for rank 1 mask arguments.
|
||||
/// This calls the version that returns a scalar logical value.
|
||||
mlir::Value genAll(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value maskBox, mlir::Value dim);
|
||||
|
||||
/// Generate call to `any` runtime routine. This version of `any` is specialized
|
||||
/// for rank 1 mask arguments.
|
||||
/// This calls the version that returns a scalar logical value.
|
||||
mlir::Value genAny(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value maskBox, mlir::Value dim);
|
||||
|
||||
/// Generate call to `count` runtime routine. This routine is a specialized
|
||||
/// version when mask is a rank one array or the dim argument is not
|
||||
/// specified by the user.
|
||||
mlir::Value genCount(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value maskBox, mlir::Value dim);
|
||||
|
||||
/// Generate call to general CountDim runtime routine. This routine has a
|
||||
/// descriptor result.
|
||||
void genCountDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value maskBox, mlir::Value dim,
|
||||
mlir::Value kind);
|
||||
|
||||
/// Generate call to `dot_product` intrinsic runtime routine.
|
||||
mlir::Value genDotProduct(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value vectorABox, mlir::Value vectorBBox,
|
||||
mlir::Value resultBox);
|
||||
|
||||
/// Generate call to `maxloc` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
void genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value maskBox,
|
||||
mlir::Value kind, mlir::Value back);
|
||||
|
||||
/// Generate call to `maxloc` intrinsic runtime routine. This is the version
|
||||
/// that takes a dim argument.
|
||||
void genMaxlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox, mlir::Value kind, mlir::Value back);
|
||||
|
||||
/// Generate call to `minloc` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
void genMinloc(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value maskBox,
|
||||
mlir::Value kind, mlir::Value back);
|
||||
|
||||
/// Generate call to `minloc` intrinsic runtime routine. This is the version
|
||||
/// that takes a dim argument.
|
||||
void genMinlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox, mlir::Value kind, mlir::Value back);
|
||||
|
||||
/// Generate call to `maxval` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value genMaxval(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value arrayBox, mlir::Value maskBox);
|
||||
|
||||
/// Generate call to `maxval` intrinsic runtime routine. This is the version
|
||||
/// that that handles 1 dimensional character arrays with no DIM argument.
|
||||
void genMaxvalChar(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value maskBox);
|
||||
|
||||
/// Generate call to `maxval` intrinsic runtime routine. This is the version
|
||||
/// that takes arrays of any rank with a dim argument specified.
|
||||
void genMaxvalDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox);
|
||||
|
||||
/// Generate call to `minval` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value genMinval(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value arrayBox, mlir::Value maskBox);
|
||||
|
||||
/// Generate call to `minval` intrinsic runtime routine. This is the version
|
||||
/// that that handles 1 dimensional character arrays with no DIM argument.
|
||||
void genMinvalChar(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value maskBox);
|
||||
|
||||
/// Generate call to `minval` intrinsic runtime routine. This is the version
|
||||
/// that takes arrays of any rank with a dim argument specified.
|
||||
void genMinvalDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox);
|
||||
|
||||
/// Generate call to `product` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value genProduct(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value arrayBox, mlir::Value maskBox,
|
||||
mlir::Value resultBox);
|
||||
|
||||
/// Generate call to `product` intrinsic runtime routine. This is the version
|
||||
/// that takes arrays of any rank with a dim argument specified.
|
||||
void genProductDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox);
|
||||
|
||||
/// Generate call to `sum` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value genSum(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value arrayBox, mlir::Value maskBox,
|
||||
mlir::Value resultBox);
|
||||
|
||||
/// Generate call to `sum` intrinsic runtime routine. This is the version
|
||||
/// that takes arrays of any rank with a dim argument specified.
|
||||
void genSumDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox);
|
||||
|
||||
} // namespace fir::runtime
|
||||
|
||||
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_REDUCTION_H
|
|
@ -8,6 +8,7 @@ add_flang_library(FIRBuilder
|
|||
FIRBuilder.cpp
|
||||
MutableBox.cpp
|
||||
Runtime/Assign.cpp
|
||||
Runtime/Reduction.cpp
|
||||
Runtime/Transformational.cpp
|
||||
|
||||
DEPENDS
|
||||
|
|
|
@ -0,0 +1,928 @@
|
|||
//===-- Reduction.cpp -- generate reduction intrinsics runtime calls- -----===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flang/Optimizer/Builder/Runtime/Reduction.h"
|
||||
#include "flang/Lower/Todo.h"
|
||||
#include "flang/Optimizer/Builder/BoxValue.h"
|
||||
#include "flang/Optimizer/Builder/Character.h"
|
||||
#include "flang/Optimizer/Builder/FIRBuilder.h"
|
||||
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
|
||||
#include "flang/Runtime/reduction.h"
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
|
||||
using namespace Fortran::runtime;
|
||||
|
||||
/// Placeholder for real*10 version of Maxval Intrinsic
|
||||
struct ForcedMaxvalReal10 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF80(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*16 version of Maxval Intrinsic
|
||||
struct ForcedMaxvalReal16 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MaxvalReal16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF128(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for integer*16 version of Maxval Intrinsic
|
||||
struct ForcedMaxvalInteger16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(MaxvalInteger16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::IntegerType::get(ctx, 128);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*10 version of Minval Intrinsic
|
||||
struct ForcedMinvalReal10 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MinvalReal10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF80(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*16 version of Minval Intrinsic
|
||||
struct ForcedMinvalReal16 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(MinvalReal16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF128(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for integer*16 version of Minval Intrinsic
|
||||
struct ForcedMinvalInteger16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(MinvalInteger16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::IntegerType::get(ctx, 128);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*10 version of Product Intrinsic
|
||||
struct ForcedProductReal10 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF80(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*16 version of Product Intrinsic
|
||||
struct ForcedProductReal16 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF128(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for integer*16 version of Product Intrinsic
|
||||
struct ForcedProductInteger16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(ProductInteger16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::IntegerType::get(ctx, 128);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for complex(10) version of Product Intrinsic
|
||||
struct ForcedProductComplex10 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(CppProductComplex10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::ComplexType::get(mlir::FloatType::getF80(ctx));
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
auto resTy = fir::ReferenceType::get(ty);
|
||||
return mlir::FunctionType::get(
|
||||
ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for complex(16) version of Product Intrinsic
|
||||
struct ForcedProductComplex16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(CppProductComplex16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::ComplexType::get(mlir::FloatType::getF128(ctx));
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
auto resTy = fir::ReferenceType::get(ty);
|
||||
return mlir::FunctionType::get(
|
||||
ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*10 version of DotProduct Intrinsic
|
||||
struct ForcedDotProductReal10 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(DotProductReal10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF80(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*16 version of DotProduct Intrinsic
|
||||
struct ForcedDotProductReal16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(DotProductReal16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF128(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for complex(10) version of DotProduct Intrinsic
|
||||
struct ForcedDotProductComplex10 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(CppDotProductComplex10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::ComplexType::get(mlir::FloatType::getF80(ctx));
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
auto resTy = fir::ReferenceType::get(ty);
|
||||
return mlir::FunctionType::get(ctx, {resTy, boxTy, boxTy, strTy, intTy},
|
||||
{});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for complex(16) version of DotProduct Intrinsic
|
||||
struct ForcedDotProductComplex16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(CppDotProductComplex16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::ComplexType::get(mlir::FloatType::getF128(ctx));
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
auto resTy = fir::ReferenceType::get(ty);
|
||||
return mlir::FunctionType::get(ctx, {resTy, boxTy, boxTy, strTy, intTy},
|
||||
{});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for integer*16 version of DotProduct Intrinsic
|
||||
struct ForcedDotProductInteger16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(DotProductInteger16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::IntegerType::get(ctx, 128);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, boxTy, strTy, intTy}, {ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*10 version of Sum Intrinsic
|
||||
struct ForcedSumReal10 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumReal10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF80(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for real*16 version of Sum Intrinsic
|
||||
struct ForcedSumReal16 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumReal16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::FloatType::getF128(ctx);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for integer*16 version of Sum Intrinsic
|
||||
struct ForcedSumInteger16 {
|
||||
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SumInteger16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::IntegerType::get(ctx, 128);
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy, intTy, boxTy},
|
||||
{ty});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for complex(10) version of Sum Intrinsic
|
||||
struct ForcedSumComplex10 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(CppSumComplex10));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::ComplexType::get(mlir::FloatType::getF80(ctx));
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
auto resTy = fir::ReferenceType::get(ty);
|
||||
return mlir::FunctionType::get(
|
||||
ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Placeholder for complex(16) version of Sum Intrinsic
|
||||
struct ForcedSumComplex16 {
|
||||
static constexpr const char *name =
|
||||
ExpandAndQuoteKey(RTNAME(CppSumComplex16));
|
||||
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
|
||||
return [](mlir::MLIRContext *ctx) {
|
||||
auto ty = mlir::ComplexType::get(mlir::FloatType::getF128(ctx));
|
||||
auto boxTy =
|
||||
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
|
||||
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
|
||||
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
|
||||
auto resTy = fir::ReferenceType::get(ty);
|
||||
return mlir::FunctionType::get(
|
||||
ctx, {resTy, boxTy, strTy, intTy, intTy, boxTy}, {});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Generate call to specialized runtime function that takes a mask and
|
||||
/// dim argument. The All, Any, and Count intrinsics use this pattern.
|
||||
template <typename FN>
|
||||
mlir::Value genSpecial2Args(FN func, fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value maskBox,
|
||||
mlir::Value dim) {
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, maskBox,
|
||||
sourceFile, sourceLine, dim);
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
||||
|
||||
/// Generate calls to reduction intrinsics such as All and Any.
|
||||
/// These are the descriptor based implementations that take two
|
||||
/// arguments (mask, dim).
|
||||
template <typename FN>
|
||||
static void genReduction2Args(FN func, fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value maskBox, mlir::Value dim) {
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, resultBox, maskBox, dim, sourceFile, sourceLine);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Generate calls to reduction intrinsics such as Maxval and Minval.
|
||||
/// These take arguments such as (array, dim, mask).
|
||||
template <typename FN>
|
||||
static void genReduction3Args(FN func, fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox) {
|
||||
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
|
||||
auto args =
|
||||
fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, dim,
|
||||
sourceFile, sourceLine, maskBox);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Generate calls to reduction intrinsics such as Maxloc and Minloc.
|
||||
/// These take arguments such as (array, mask, kind, back).
|
||||
template <typename FN>
|
||||
static void genReduction4Args(FN func, fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value arrayBox, mlir::Value maskBox,
|
||||
mlir::Value kind, mlir::Value back) {
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
|
||||
arrayBox, kind, sourceFile,
|
||||
sourceLine, maskBox, back);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Generate calls to reduction intrinsics such as Maxloc and Minloc.
|
||||
/// These take arguments such as (array, dim, mask, kind, back).
|
||||
template <typename FN>
|
||||
static void
|
||||
genReduction5Args(FN func, fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim,
|
||||
mlir::Value maskBox, mlir::Value kind, mlir::Value back) {
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
|
||||
arrayBox, kind, dim, sourceFile,
|
||||
sourceLine, maskBox, back);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Generate call to `all` runtime routine.
|
||||
/// This calls the descriptor based runtime call implementation of the `all`
|
||||
/// intrinsic.
|
||||
void fir::runtime::genAllDescriptor(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value maskBox, mlir::Value dim) {
|
||||
auto allFunc = fir::runtime::getRuntimeFunc<mkRTKey(AllDim)>(loc, builder);
|
||||
genReduction2Args(allFunc, builder, loc, resultBox, maskBox, dim);
|
||||
}
|
||||
|
||||
/// Generate call to `any` runtime routine.
|
||||
/// This calls the descriptor based runtime call implementation of the `any`
|
||||
/// intrinsic.
|
||||
void fir::runtime::genAnyDescriptor(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value maskBox, mlir::Value dim) {
|
||||
auto anyFunc = fir::runtime::getRuntimeFunc<mkRTKey(AnyDim)>(loc, builder);
|
||||
genReduction2Args(anyFunc, builder, loc, resultBox, maskBox, dim);
|
||||
}
|
||||
|
||||
/// Generate call to `all` intrinsic runtime routine. This routine is
|
||||
/// specialized for mask arguments with rank == 1.
|
||||
mlir::Value fir::runtime::genAll(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value maskBox, mlir::Value dim) {
|
||||
auto allFunc = fir::runtime::getRuntimeFunc<mkRTKey(All)>(loc, builder);
|
||||
return genSpecial2Args(allFunc, builder, loc, maskBox, dim);
|
||||
}
|
||||
|
||||
/// Generate call to `any` intrinsic runtime routine. This routine is
|
||||
/// specialized for mask arguments with rank == 1.
|
||||
mlir::Value fir::runtime::genAny(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value maskBox, mlir::Value dim) {
|
||||
auto anyFunc = fir::runtime::getRuntimeFunc<mkRTKey(Any)>(loc, builder);
|
||||
return genSpecial2Args(anyFunc, builder, loc, maskBox, dim);
|
||||
}
|
||||
|
||||
/// Generate call to `count` runtime routine. This routine is a specialized
|
||||
/// version when mask is a rank one array or the dim argument is not
|
||||
/// specified by the user.
|
||||
mlir::Value fir::runtime::genCount(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value maskBox,
|
||||
mlir::Value dim) {
|
||||
auto countFunc = fir::runtime::getRuntimeFunc<mkRTKey(Count)>(loc, builder);
|
||||
return genSpecial2Args(countFunc, builder, loc, maskBox, dim);
|
||||
}
|
||||
|
||||
/// Generate call to general CountDim runtime routine. This routine has a
|
||||
/// descriptor result.
|
||||
void fir::runtime::genCountDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value maskBox,
|
||||
mlir::Value dim, mlir::Value kind) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(CountDim)>(loc, builder);
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(5));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, resultBox, maskBox, dim, kind, sourceFile, sourceLine);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Generate call to `maxloc` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value maskBox, mlir::Value kind,
|
||||
mlir::Value back) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(Maxloc)>(loc, builder);
|
||||
genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind,
|
||||
back);
|
||||
}
|
||||
|
||||
/// Generate call to `maxloc` intrinsic runtime routine. This is the version
|
||||
/// that takes a dim argument.
|
||||
void fir::runtime::genMaxlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value dim, mlir::Value maskBox,
|
||||
mlir::Value kind, mlir::Value back) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(MaxlocDim)>(loc, builder);
|
||||
genReduction5Args(func, builder, loc, resultBox, arrayBox, dim, maskBox, kind,
|
||||
back);
|
||||
}
|
||||
|
||||
/// Generate call to `maxval` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value arrayBox,
|
||||
mlir::Value maskBox) {
|
||||
mlir::FuncOp func;
|
||||
auto ty = arrayBox.getType();
|
||||
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
|
||||
auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy();
|
||||
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
|
||||
|
||||
if (eleTy.isF32())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalReal4)>(loc, builder);
|
||||
else if (eleTy.isF64())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalReal8)>(loc, builder);
|
||||
else if (eleTy.isF80())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedMaxvalReal10>(loc, builder);
|
||||
else if (eleTy.isF128())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedMaxvalReal16>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger1)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger2)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger4)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalInteger8)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16)))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedMaxvalInteger16>(loc, builder);
|
||||
else
|
||||
fir::emitFatalError(loc, "invalid type in Maxval lowering");
|
||||
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
|
||||
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
||||
|
||||
/// Generate call to `maxval` intrinsic runtime routine. This is the version
|
||||
/// that handles any rank array with the dim argument specified.
|
||||
void fir::runtime::genMaxvalDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value dim, mlir::Value maskBox) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(MaxvalDim)>(loc, builder);
|
||||
genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
|
||||
}
|
||||
|
||||
/// Generate call to `maxval` intrinsic runtime routine. This is the version
|
||||
/// that handles character arrays of rank 1 and without a DIM argument.
|
||||
void fir::runtime::genMaxvalChar(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value maskBox) {
|
||||
auto func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(MaxvalCharacter)>(loc, builder);
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Generate call to `minloc` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
void fir::runtime::genMinloc(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value maskBox, mlir::Value kind,
|
||||
mlir::Value back) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(Minloc)>(loc, builder);
|
||||
genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind,
|
||||
back);
|
||||
}
|
||||
|
||||
/// Generate call to `minloc` intrinsic runtime routine. This is the version
|
||||
/// that takes a dim argument.
|
||||
void fir::runtime::genMinlocDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value dim, mlir::Value maskBox,
|
||||
mlir::Value kind, mlir::Value back) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(MinlocDim)>(loc, builder);
|
||||
genReduction5Args(func, builder, loc, resultBox, arrayBox, dim, maskBox, kind,
|
||||
back);
|
||||
}
|
||||
|
||||
/// Generate call to `minval` intrinsic runtime routine. This is the version
|
||||
/// that handles any rank array with the dim argument specified.
|
||||
void fir::runtime::genMinvalDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value dim, mlir::Value maskBox) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalDim)>(loc, builder);
|
||||
genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
|
||||
}
|
||||
|
||||
/// Generate call to `minval` intrinsic runtime routine. This is the version
|
||||
/// that handles character arrays of rank 1 and without a DIM argument.
|
||||
void fir::runtime::genMinvalChar(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value maskBox) {
|
||||
auto func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(MinvalCharacter)>(loc, builder);
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, resultBox, arrayBox, sourceFile, sourceLine, maskBox);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Generate call to `minval` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value arrayBox,
|
||||
mlir::Value maskBox) {
|
||||
mlir::FuncOp func;
|
||||
auto ty = arrayBox.getType();
|
||||
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
|
||||
auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy();
|
||||
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
|
||||
|
||||
if (eleTy.isF32())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalReal4)>(loc, builder);
|
||||
else if (eleTy.isF64())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalReal8)>(loc, builder);
|
||||
else if (eleTy.isF80())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedMinvalReal10>(loc, builder);
|
||||
else if (eleTy.isF128())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedMinvalReal16>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger1)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger2)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger4)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(MinvalInteger8)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16)))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedMinvalInteger16>(loc, builder);
|
||||
else
|
||||
fir::emitFatalError(loc, "invalid type in Minval lowering");
|
||||
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
|
||||
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
||||
|
||||
/// Generate call to `product` intrinsic runtime routine. This is the version
|
||||
/// that handles any rank array with the dim argument specified.
|
||||
void fir::runtime::genProductDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value dim, mlir::Value maskBox) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(ProductDim)>(loc, builder);
|
||||
genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
|
||||
}
|
||||
|
||||
/// Generate call to `product` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value arrayBox,
|
||||
mlir::Value maskBox,
|
||||
mlir::Value resultBox) {
|
||||
mlir::FuncOp func;
|
||||
auto ty = arrayBox.getType();
|
||||
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
|
||||
auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy();
|
||||
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
|
||||
|
||||
if (eleTy.isF32())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(ProductReal4)>(loc, builder);
|
||||
else if (eleTy.isF64())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(ProductReal8)>(loc, builder);
|
||||
else if (eleTy.isF80())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedProductReal10>(loc, builder);
|
||||
else if (eleTy.isF128())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedProductReal16>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger1)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger2)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger4)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(ProductInteger8)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16)))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedProductInteger16>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 4))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(CppProductComplex4)>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 8))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(CppProductComplex8)>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 10))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedProductComplex10>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 16))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedProductComplex16>(loc, builder);
|
||||
else
|
||||
fir::emitFatalError(loc, "invalid type in Product lowering");
|
||||
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
if (fir::isa_complex(eleTy)) {
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
|
||||
auto args =
|
||||
fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
|
||||
sourceFile, sourceLine, dim, maskBox);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
return resultBox;
|
||||
}
|
||||
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
|
||||
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
||||
|
||||
/// Generate call to `dot_product` intrinsic runtime routine.
|
||||
mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc,
|
||||
mlir::Value vectorABox,
|
||||
mlir::Value vectorBBox,
|
||||
mlir::Value resultBox) {
|
||||
mlir::FuncOp func;
|
||||
auto ty = vectorABox.getType();
|
||||
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
|
||||
auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy();
|
||||
|
||||
if (eleTy.isF32())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(DotProductReal4)>(loc, builder);
|
||||
else if (eleTy.isF64())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(DotProductReal8)>(loc, builder);
|
||||
else if (eleTy.isF80())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedDotProductReal10>(loc, builder);
|
||||
else if (eleTy.isF128())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedDotProductReal16>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 4))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(CppDotProductComplex4)>(
|
||||
loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 8))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(CppDotProductComplex8)>(
|
||||
loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 10))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<ForcedDotProductComplex10>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 16))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<ForcedDotProductComplex16>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1)))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger1)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2)))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger2)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4)))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger4)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8)))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(DotProductInteger8)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16)))
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<ForcedDotProductInteger16>(loc, builder);
|
||||
else if (eleTy.isa<fir::LogicalType>())
|
||||
func =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(DotProductLogical)>(loc, builder);
|
||||
else
|
||||
fir::emitFatalError(loc, "invalid type in DotProduct lowering");
|
||||
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
|
||||
if (fir::isa_complex(eleTy)) {
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(4));
|
||||
auto args =
|
||||
fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorABox,
|
||||
vectorBBox, sourceFile, sourceLine);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
return resultBox;
|
||||
}
|
||||
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, vectorABox,
|
||||
vectorBBox, sourceFile, sourceLine);
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
||||
/// Generate call to Sum intrinsic runtime routine. This is the version
|
||||
/// that handles any rank array with the dim argument specified.
|
||||
void fir::runtime::genSumDim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value arrayBox,
|
||||
mlir::Value dim, mlir::Value maskBox) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(SumDim)>(loc, builder);
|
||||
genReduction3Args(func, builder, loc, resultBox, arrayBox, dim, maskBox);
|
||||
}
|
||||
|
||||
/// Generate call to `sum` intrinsic runtime routine. This is the version
|
||||
/// that does not take a dim argument.
|
||||
mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value arrayBox, mlir::Value maskBox,
|
||||
mlir::Value resultBox) {
|
||||
mlir::FuncOp func;
|
||||
auto ty = arrayBox.getType();
|
||||
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
|
||||
auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy();
|
||||
auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
|
||||
|
||||
if (eleTy.isF32())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(SumReal4)>(loc, builder);
|
||||
else if (eleTy.isF64())
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(SumReal8)>(loc, builder);
|
||||
else if (eleTy.isF80())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedSumReal10>(loc, builder);
|
||||
else if (eleTy.isF128())
|
||||
func = fir::runtime::getRuntimeFunc<ForcedSumReal16>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(1)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger1)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(2)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger2)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(4)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger4)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(8)))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(SumInteger8)>(loc, builder);
|
||||
else if (eleTy ==
|
||||
builder.getIntegerType(builder.getKindMap().getIntegerBitsize(16)))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedSumInteger16>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 4))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(CppSumComplex4)>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 8))
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(CppSumComplex8)>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 10))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedSumComplex10>(loc, builder);
|
||||
else if (eleTy == fir::ComplexType::get(builder.getContext(), 16))
|
||||
func = fir::runtime::getRuntimeFunc<ForcedSumComplex16>(loc, builder);
|
||||
else
|
||||
fir::emitFatalError(loc, "invalid type in Sum lowering");
|
||||
|
||||
auto fTy = func.getType();
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
if (fir::isa_complex(eleTy)) {
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
|
||||
auto args =
|
||||
fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox,
|
||||
sourceFile, sourceLine, dim, maskBox);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
return resultBox;
|
||||
}
|
||||
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(2));
|
||||
auto args = fir::runtime::createArguments(
|
||||
builder, loc, fTy, arrayBox, sourceFile, sourceLine, dim, maskBox);
|
||||
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
|
@ -0,0 +1,327 @@
|
|||
//===- ReductionTest.cpp -- Reduction runtime builder unit tests ----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flang/Optimizer/Builder/Runtime/Reduction.h"
|
||||
#include "RuntimeCallTestBase.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST_F(RuntimeCallTest, genAllTest) {
|
||||
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value undef = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||
mlir::Value all = fir::runtime::genAll(*firBuilder, loc, undef, dim);
|
||||
checkCallOp(all.getDefiningOp(), "_FortranAAll", 2);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genAllDescriptorTest) {
|
||||
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value result = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value mask = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||
fir::runtime::genAllDescriptor(*firBuilder, loc, result, mask, dim);
|
||||
checkCallOpFromResultBox(result, "_FortranAAllDim", 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genAnyTest) {
|
||||
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value undef = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||
mlir::Value any = fir::runtime::genAny(*firBuilder, loc, undef, dim);
|
||||
checkCallOp(any.getDefiningOp(), "_FortranAAny", 2);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genAnyDescriptorTest) {
|
||||
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value result = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value mask = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||
fir::runtime::genAnyDescriptor(*firBuilder, loc, result, mask, dim);
|
||||
checkCallOpFromResultBox(result, "_FortranAAnyDim", 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genCountTest) {
|
||||
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value undef = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||
mlir::Value count = fir::runtime::genCount(*firBuilder, loc, undef, dim);
|
||||
checkCallOp(count.getDefiningOp(), "_FortranACount", 2);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genCountDimTest) {
|
||||
mlir::Location loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value result = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value mask = firBuilder->create<fir::UndefOp>(loc, seqTy10);
|
||||
mlir::Value dim = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||
mlir::Value kind = firBuilder->createIntegerConstant(loc, i32Ty, 1);
|
||||
fir::runtime::genCountDim(*firBuilder, loc, result, mask, dim, kind);
|
||||
checkCallOpFromResultBox(result, "_FortranACountDim", 4);
|
||||
}
|
||||
|
||||
void testGenMaxVal(
|
||||
fir::FirOpBuilder &builder, mlir::Type eleTy, llvm::StringRef fctName) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), eleTy);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value undef = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value max = fir::runtime::genMaxval(builder, loc, undef, mask);
|
||||
checkCallOp(max.getDefiningOp(), fctName, 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMaxValTest) {
|
||||
testGenMaxVal(*firBuilder, f32Ty, "_FortranAMaxvalReal4");
|
||||
testGenMaxVal(*firBuilder, f64Ty, "_FortranAMaxvalReal8");
|
||||
testGenMaxVal(*firBuilder, f80Ty, "_FortranAMaxvalReal10");
|
||||
testGenMaxVal(*firBuilder, f128Ty, "_FortranAMaxvalReal16");
|
||||
|
||||
testGenMaxVal(*firBuilder, i8Ty, "_FortranAMaxvalInteger1");
|
||||
testGenMaxVal(*firBuilder, i16Ty, "_FortranAMaxvalInteger2");
|
||||
testGenMaxVal(*firBuilder, i32Ty, "_FortranAMaxvalInteger4");
|
||||
testGenMaxVal(*firBuilder, i64Ty, "_FortranAMaxvalInteger8");
|
||||
testGenMaxVal(*firBuilder, i128Ty, "_FortranAMaxvalInteger16");
|
||||
}
|
||||
|
||||
void testGenMinVal(
|
||||
fir::FirOpBuilder &builder, mlir::Type eleTy, llvm::StringRef fctName) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), eleTy);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value undef = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value min = fir::runtime::genMinval(builder, loc, undef, mask);
|
||||
checkCallOp(min.getDefiningOp(), fctName, 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMinValTest) {
|
||||
testGenMinVal(*firBuilder, f32Ty, "_FortranAMinvalReal4");
|
||||
testGenMinVal(*firBuilder, f64Ty, "_FortranAMinvalReal8");
|
||||
testGenMinVal(*firBuilder, f80Ty, "_FortranAMinvalReal10");
|
||||
testGenMinVal(*firBuilder, f128Ty, "_FortranAMinvalReal16");
|
||||
|
||||
testGenMinVal(*firBuilder, i8Ty, "_FortranAMinvalInteger1");
|
||||
testGenMinVal(*firBuilder, i16Ty, "_FortranAMinvalInteger2");
|
||||
testGenMinVal(*firBuilder, i32Ty, "_FortranAMinvalInteger4");
|
||||
testGenMinVal(*firBuilder, i64Ty, "_FortranAMinvalInteger8");
|
||||
testGenMinVal(*firBuilder, i128Ty, "_FortranAMinvalInteger16");
|
||||
}
|
||||
|
||||
void testGenSum(
|
||||
fir::FirOpBuilder &builder, mlir::Type eleTy, llvm::StringRef fctName) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), eleTy);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value undef = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value sum = fir::runtime::genSum(builder, loc, undef, mask, result);
|
||||
if (fir::isa_complex(eleTy))
|
||||
checkCallOpFromResultBox(result, fctName, 4);
|
||||
else
|
||||
checkCallOp(sum.getDefiningOp(), fctName, 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genSumTest) {
|
||||
testGenSum(*firBuilder, f32Ty, "_FortranASumReal4");
|
||||
testGenSum(*firBuilder, f64Ty, "_FortranASumReal8");
|
||||
testGenSum(*firBuilder, f80Ty, "_FortranASumReal10");
|
||||
testGenSum(*firBuilder, f128Ty, "_FortranASumReal16");
|
||||
testGenSum(*firBuilder, i8Ty, "_FortranASumInteger1");
|
||||
testGenSum(*firBuilder, i16Ty, "_FortranASumInteger2");
|
||||
testGenSum(*firBuilder, i32Ty, "_FortranASumInteger4");
|
||||
testGenSum(*firBuilder, i64Ty, "_FortranASumInteger8");
|
||||
testGenSum(*firBuilder, i128Ty, "_FortranASumInteger16");
|
||||
testGenSum(*firBuilder, c4Ty, "_FortranACppSumComplex4");
|
||||
testGenSum(*firBuilder, c8Ty, "_FortranACppSumComplex8");
|
||||
testGenSum(*firBuilder, c10Ty, "_FortranACppSumComplex10");
|
||||
testGenSum(*firBuilder, c16Ty, "_FortranACppSumComplex16");
|
||||
}
|
||||
|
||||
void testGenProduct(
|
||||
fir::FirOpBuilder &builder, mlir::Type eleTy, llvm::StringRef fctName) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), eleTy);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value undef = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value prod =
|
||||
fir::runtime::genProduct(builder, loc, undef, mask, result);
|
||||
if (fir::isa_complex(eleTy))
|
||||
checkCallOpFromResultBox(result, fctName, 4);
|
||||
else
|
||||
checkCallOp(prod.getDefiningOp(), fctName, 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genProduct) {
|
||||
testGenProduct(*firBuilder, f32Ty, "_FortranAProductReal4");
|
||||
testGenProduct(*firBuilder, f64Ty, "_FortranAProductReal8");
|
||||
testGenProduct(*firBuilder, f80Ty, "_FortranAProductReal10");
|
||||
testGenProduct(*firBuilder, f128Ty, "_FortranAProductReal16");
|
||||
testGenProduct(*firBuilder, i8Ty, "_FortranAProductInteger1");
|
||||
testGenProduct(*firBuilder, i16Ty, "_FortranAProductInteger2");
|
||||
testGenProduct(*firBuilder, i32Ty, "_FortranAProductInteger4");
|
||||
testGenProduct(*firBuilder, i64Ty, "_FortranAProductInteger8");
|
||||
testGenProduct(*firBuilder, i128Ty, "_FortranAProductInteger16");
|
||||
testGenProduct(*firBuilder, c4Ty, "_FortranACppProductComplex4");
|
||||
testGenProduct(*firBuilder, c8Ty, "_FortranACppProductComplex8");
|
||||
testGenProduct(*firBuilder, c10Ty, "_FortranACppProductComplex10");
|
||||
testGenProduct(*firBuilder, c16Ty, "_FortranACppProductComplex16");
|
||||
}
|
||||
|
||||
void testGenDotProduct(
|
||||
fir::FirOpBuilder &builder, mlir::Type eleTy, llvm::StringRef fctName) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), eleTy);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value a = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value b = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value prod = fir::runtime::genDotProduct(builder, loc, a, b, result);
|
||||
if (fir::isa_complex(eleTy))
|
||||
checkCallOpFromResultBox(result, fctName, 3);
|
||||
else
|
||||
checkCallOp(prod.getDefiningOp(), fctName, 2);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genDotProduct) {
|
||||
testGenDotProduct(*firBuilder, f32Ty, "_FortranADotProductReal4");
|
||||
testGenDotProduct(*firBuilder, f64Ty, "_FortranADotProductReal8");
|
||||
testGenDotProduct(*firBuilder, f80Ty, "_FortranADotProductReal10");
|
||||
testGenDotProduct(*firBuilder, f128Ty, "_FortranADotProductReal16");
|
||||
testGenDotProduct(*firBuilder, i8Ty, "_FortranADotProductInteger1");
|
||||
testGenDotProduct(*firBuilder, i16Ty, "_FortranADotProductInteger2");
|
||||
testGenDotProduct(*firBuilder, i32Ty, "_FortranADotProductInteger4");
|
||||
testGenDotProduct(*firBuilder, i64Ty, "_FortranADotProductInteger8");
|
||||
testGenDotProduct(*firBuilder, i128Ty, "_FortranADotProductInteger16");
|
||||
testGenDotProduct(*firBuilder, c4Ty, "_FortranACppDotProductComplex4");
|
||||
testGenDotProduct(*firBuilder, c8Ty, "_FortranACppDotProductComplex8");
|
||||
testGenDotProduct(*firBuilder, c10Ty, "_FortranACppDotProductComplex10");
|
||||
testGenDotProduct(*firBuilder, c16Ty, "_FortranACppDotProductComplex16");
|
||||
}
|
||||
|
||||
void checkGenMxxloc(fir::FirOpBuilder &builder,
|
||||
void (*genFct)(fir::FirOpBuilder &, Location, mlir::Value, mlir::Value,
|
||||
mlir::Value, mlir::Value, mlir::Value),
|
||||
llvm::StringRef fctName, unsigned nbArgs) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
mlir::Type i32Ty = builder.getI32Type();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value a = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value kind = builder.createIntegerConstant(loc, i32Ty, 1);
|
||||
mlir::Value back = builder.createIntegerConstant(loc, i32Ty, 1);
|
||||
genFct(builder, loc, result, a, mask, kind, back);
|
||||
checkCallOpFromResultBox(result, fctName, nbArgs);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMaxlocTest) {
|
||||
checkGenMxxloc(*firBuilder, fir::runtime::genMaxloc, "_FortranAMaxloc", 5);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMinlocTest) {
|
||||
checkGenMxxloc(*firBuilder, fir::runtime::genMinloc, "_FortranAMinloc", 5);
|
||||
}
|
||||
|
||||
void checkGenMxxlocDim(fir::FirOpBuilder &builder,
|
||||
void (*genFct)(fir::FirOpBuilder &, Location, mlir::Value, mlir::Value,
|
||||
mlir::Value, mlir::Value, mlir::Value, mlir::Value),
|
||||
llvm::StringRef fctName, unsigned nbArgs) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
auto i32Ty = builder.getI32Type();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value a = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value kind = builder.createIntegerConstant(loc, i32Ty, 1);
|
||||
mlir::Value dim = builder.createIntegerConstant(loc, i32Ty, 1);
|
||||
mlir::Value back = builder.createIntegerConstant(loc, i32Ty, 1);
|
||||
genFct(builder, loc, result, a, dim, mask, kind, back);
|
||||
checkCallOpFromResultBox(result, fctName, nbArgs);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMaxlocDimTest) {
|
||||
checkGenMxxlocDim(
|
||||
*firBuilder, fir::runtime::genMaxlocDim, "_FortranAMaxlocDim", 6);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMinlocDimTest) {
|
||||
checkGenMxxlocDim(
|
||||
*firBuilder, fir::runtime::genMinlocDim, "_FortranAMinlocDim", 6);
|
||||
}
|
||||
|
||||
void checkGenMxxvalChar(fir::FirOpBuilder &builder,
|
||||
void (*genFct)(
|
||||
fir::FirOpBuilder &, Location, mlir::Value, mlir::Value, mlir::Value),
|
||||
llvm::StringRef fctName, unsigned nbArgs) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
auto i32Ty = builder.getI32Type();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value a = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
genFct(builder, loc, result, a, mask);
|
||||
checkCallOpFromResultBox(result, fctName, nbArgs);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMaxvalCharTest) {
|
||||
checkGenMxxvalChar(
|
||||
*firBuilder, fir::runtime::genMaxvalChar, "_FortranAMaxvalCharacter", 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMinvalCharTest) {
|
||||
checkGenMxxvalChar(
|
||||
*firBuilder, fir::runtime::genMinvalChar, "_FortranAMinvalCharacter", 3);
|
||||
}
|
||||
|
||||
void checkGen4argsDim(fir::FirOpBuilder &builder,
|
||||
void (*genFct)(fir::FirOpBuilder &, Location, mlir::Value, mlir::Value,
|
||||
mlir::Value, mlir::Value),
|
||||
llvm::StringRef fctName, unsigned nbArgs) {
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
auto i32Ty = builder.getI32Type();
|
||||
mlir::Type seqTy =
|
||||
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);
|
||||
mlir::Type refSeqTy = fir::ReferenceType::get(seqTy);
|
||||
mlir::Value a = builder.create<fir::UndefOp>(loc, refSeqTy);
|
||||
mlir::Value result = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value mask = builder.create<fir::UndefOp>(loc, seqTy);
|
||||
mlir::Value dim = builder.createIntegerConstant(loc, i32Ty, 1);
|
||||
genFct(builder, loc, result, a, dim, mask);
|
||||
checkCallOpFromResultBox(result, fctName, nbArgs);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMaxvalDimTest) {
|
||||
checkGen4argsDim(
|
||||
*firBuilder, fir::runtime::genMaxvalDim, "_FortranAMaxvalDim", 4);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genMinvalDimTest) {
|
||||
checkGen4argsDim(
|
||||
*firBuilder, fir::runtime::genMinvalDim, "_FortranAMinvalDim", 4);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genProductDimTest) {
|
||||
checkGen4argsDim(
|
||||
*firBuilder, fir::runtime::genProductDim, "_FortranAProductDim", 4);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genSumDimTest) {
|
||||
checkGen4argsDim(*firBuilder, fir::runtime::genSumDim, "_FortranASumDim", 4);
|
||||
}
|
|
@ -48,6 +48,8 @@ public:
|
|||
c8Ty = fir::ComplexType::get(firBuilder->getContext(), 8);
|
||||
c10Ty = fir::ComplexType::get(firBuilder->getContext(), 10);
|
||||
c16Ty = fir::ComplexType::get(firBuilder->getContext(), 16);
|
||||
|
||||
seqTy10 = fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);
|
||||
}
|
||||
|
||||
mlir::MLIRContext context;
|
||||
|
@ -68,6 +70,7 @@ public:
|
|||
mlir::Type c8Ty;
|
||||
mlir::Type c10Ty;
|
||||
mlir::Type c16Ty;
|
||||
mlir::Type seqTy10;
|
||||
};
|
||||
|
||||
/// Check that the \p op is a `fir::CallOp` operation and its name matches
|
||||
|
|
|
@ -14,6 +14,7 @@ add_flang_unittest(FlangOptimizerTests
|
|||
Builder/DoLoopHelperTest.cpp
|
||||
Builder/FIRBuilderTest.cpp
|
||||
Builder/Runtime/AssignTest.cpp
|
||||
Builder/Runtime/ReductionTest.cpp
|
||||
Builder/Runtime/TransformationalTest.cpp
|
||||
FIRContextTest.cpp
|
||||
InternalNamesTest.cpp
|
||||
|
|
Loading…
Reference in New Issue