[flang-commits] [flang] 529d094 - [fir] Add fir numeric intrinsic runtime call builder
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Thu Dec 2 01:22:46 PST 2021
Author: Valentin Clement
Date: 2021-12-02T10:22:26+01:00
New Revision: 529d0942daf3ed0766dafadad562dfeacf734c3e
URL: https://github.com/llvm/llvm-project/commit/529d0942daf3ed0766dafadad562dfeacf734c3e
DIFF: https://github.com/llvm/llvm-project/commit/529d0942daf3ed0766dafadad562dfeacf734c3e.diff
LOG: [fir] Add fir numeric intrinsic runtime call builder
This patch adds the FIR builder to generate the numeric intrinsic
runtime call.
This patch is part of the upstreaming effort from fir-dev branch.
Reviewed By: rovka
Differential Revision: https://reviews.llvm.org/D114477
Co-authored-by: Jean Perier <jperier at nvidia.com>
Co-authored-by: mleair <leairmark at gmail.com>
Added:
flang/include/flang/Optimizer/Builder/Runtime/Numeric.h
flang/lib/Optimizer/Builder/Runtime/Numeric.cpp
flang/unittests/Optimizer/Builder/Runtime/NumericTest.cpp
Modified:
flang/lib/Optimizer/Builder/CMakeLists.txt
flang/unittests/Optimizer/CMakeLists.txt
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h b/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h
new file mode 100644
index 0000000000000..323cc2ce6d49a
--- /dev/null
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h
@@ -0,0 +1,50 @@
+//===-- Numeric.h -- generate numeric intrinsics runtime calls --*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_NUMERIC_H
+#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_NUMERIC_H
+
+#include "mlir/Dialect/StandardOps/IR/Ops.h"
+
+namespace fir {
+class ExtendedValue;
+class FirOpBuilder;
+} // namespace fir
+
+namespace fir::runtime {
+
+/// Generate call to Exponent intrinsic runtime routine.
+mlir::Value genExponent(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Type resultType, mlir::Value x);
+
+/// Generate call to Fraction intrinsic runtime routine.
+mlir::Value genFraction(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value x);
+
+/// Generate call to Nearest intrinsic runtime routine.
+mlir::Value genNearest(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value x, mlir::Value s);
+
+/// Generate call to RRSpacing intrinsic runtime routine.
+mlir::Value genRRSpacing(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value x);
+
+/// Generate call to Scale intrinsic runtime routine.
+mlir::Value genScale(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value x, mlir::Value i);
+
+/// Generate call to Set_exponent intrinsic runtime routine.
+mlir::Value genSetExponent(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value x, mlir::Value i);
+
+/// Generate call to Spacing intrinsic runtime routine.
+mlir::Value genSpacing(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value x);
+
+} // namespace fir::runtime
+#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_NUMERIC_H
diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt
index 8d95558bcb1c5..4076c77b299bc 100644
--- a/flang/lib/Optimizer/Builder/CMakeLists.txt
+++ b/flang/lib/Optimizer/Builder/CMakeLists.txt
@@ -8,6 +8,7 @@ add_flang_library(FIRBuilder
FIRBuilder.cpp
MutableBox.cpp
Runtime/Assign.cpp
+ Runtime/Numeric.cpp
Runtime/Reduction.cpp
Runtime/Transformational.cpp
diff --git a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp
new file mode 100644
index 0000000000000..edcb40a7f0a38
--- /dev/null
+++ b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp
@@ -0,0 +1,398 @@
+//===-- Numeric.cpp -- runtime API for numeric intrinsics -----------------===//
+//
+// 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/Numeric.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/numeric.h"
+#include "mlir/Dialect/StandardOps/IR/Ops.h"
+
+using namespace Fortran::runtime;
+
+// The real*10 and real*16 placeholders below are used to force the
+// compilation of the real*10 and real*16 method names on systems that
+// may not have them in their runtime library. This can occur in the
+// case of cross compilation, for example.
+
+/// Placeholder for real*10 version of Exponent Intrinsic
+struct ForcedExponent10_4 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Exponent10_4));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF80(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 32);
+ return mlir::FunctionType::get(ctx, fltTy, intTy);
+ };
+ }
+};
+
+struct ForcedExponent10_8 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Exponent10_8));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF80(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 64);
+ return mlir::FunctionType::get(ctx, fltTy, intTy);
+ };
+ }
+};
+
+/// Placeholder for real*16 version of Exponent Intrinsic
+struct ForcedExponent16_4 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Exponent16_4));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF128(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 32);
+ return mlir::FunctionType::get(ctx, fltTy, intTy);
+ };
+ }
+};
+
+struct ForcedExponent16_8 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Exponent16_8));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF128(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 64);
+ return mlir::FunctionType::get(ctx, fltTy, intTy);
+ };
+ }
+};
+
+/// Placeholder for real*10 version of Fraction Intrinsic
+struct ForcedFraction10 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Fraction10));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::FloatType::getF80(ctx);
+ return mlir::FunctionType::get(ctx, {ty}, {ty});
+ };
+ }
+};
+
+/// Placeholder for real*16 version of Fraction Intrinsic
+struct ForcedFraction16 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Fraction16));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::FloatType::getF128(ctx);
+ return mlir::FunctionType::get(ctx, {ty}, {ty});
+ };
+ }
+};
+
+/// Placeholder for real*10 version of Nearest Intrinsic
+struct ForcedNearest10 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Nearest10));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF80(ctx);
+ auto boolTy = mlir::IntegerType::get(ctx, 1);
+ return mlir::FunctionType::get(ctx, {fltTy, boolTy}, {fltTy});
+ };
+ }
+};
+
+/// Placeholder for real*16 version of Nearest Intrinsic
+struct ForcedNearest16 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Nearest16));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF128(ctx);
+ auto boolTy = mlir::IntegerType::get(ctx, 1);
+ return mlir::FunctionType::get(ctx, {fltTy, boolTy}, {fltTy});
+ };
+ }
+};
+
+/// Placeholder for real*10 version of RRSpacing Intrinsic
+struct ForcedRRSpacing10 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(RRSpacing10));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::FloatType::getF80(ctx);
+ return mlir::FunctionType::get(ctx, {ty}, {ty});
+ };
+ }
+};
+
+/// Placeholder for real*16 version of RRSpacing Intrinsic
+struct ForcedRRSpacing16 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(RRSpacing16));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::FloatType::getF128(ctx);
+ return mlir::FunctionType::get(ctx, {ty}, {ty});
+ };
+ }
+};
+
+/// Placeholder for real*10 version of Scale Intrinsic
+struct ForcedScale10 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Scale10));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF80(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 64);
+ return mlir::FunctionType::get(ctx, {fltTy, intTy}, {fltTy});
+ };
+ }
+};
+
+/// Placeholder for real*16 version of Scale Intrinsic
+struct ForcedScale16 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Scale16));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF128(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 64);
+ return mlir::FunctionType::get(ctx, {fltTy, intTy}, {fltTy});
+ };
+ }
+};
+
+/// Placeholder for real*10 version of RRSpacing Intrinsic
+struct ForcedSetExponent10 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SetExponent10));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF80(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 64);
+ return mlir::FunctionType::get(ctx, {fltTy, intTy}, {fltTy});
+ };
+ }
+};
+
+/// Placeholder for real*10 version of RRSpacing Intrinsic
+struct ForcedSetExponent16 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SetExponent16));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto fltTy = mlir::FloatType::getF128(ctx);
+ auto intTy = mlir::IntegerType::get(ctx, 64);
+ return mlir::FunctionType::get(ctx, {fltTy, intTy}, {fltTy});
+ };
+ }
+};
+
+/// Placeholder for real*10 version of Spacing Intrinsic
+struct ForcedSpacing10 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Spacing10));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::FloatType::getF80(ctx);
+ return mlir::FunctionType::get(ctx, {ty}, {ty});
+ };
+ }
+};
+
+/// Placeholder for real*16 version of Spacing Intrinsic
+struct ForcedSpacing16 {
+ static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Spacing16));
+ static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+ return [](mlir::MLIRContext *ctx) {
+ auto ty = mlir::FloatType::getF128(ctx);
+ return mlir::FunctionType::get(ctx, {ty}, {ty});
+ };
+ }
+};
+
+/// Generate call to Exponent instrinsic runtime routine.
+mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Type resultType,
+ mlir::Value x) {
+ mlir::FuncOp func;
+ mlir::Type fltTy = x.getType();
+
+ if (fltTy.isF32()) {
+ if (resultType.isInteger(32))
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Exponent4_4)>(loc, builder);
+ else if (resultType.isInteger(64))
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Exponent4_8)>(loc, builder);
+ } else if (fltTy.isF64()) {
+ if (resultType.isInteger(32))
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Exponent8_4)>(loc, builder);
+ else if (resultType.isInteger(64))
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Exponent8_8)>(loc, builder);
+ } else if (fltTy.isF80()) {
+ if (resultType.isInteger(32))
+ func = fir::runtime::getRuntimeFunc<ForcedExponent10_4>(loc, builder);
+ else if (resultType.isInteger(64))
+ func = fir::runtime::getRuntimeFunc<ForcedExponent10_8>(loc, builder);
+ } else if (fltTy.isF128()) {
+ if (resultType.isInteger(32))
+ func = fir::runtime::getRuntimeFunc<ForcedExponent16_4>(loc, builder);
+ else if (resultType.isInteger(64))
+ func = fir::runtime::getRuntimeFunc<ForcedExponent16_8>(loc, builder);
+ } else
+ fir::emitFatalError(loc, "unsupported real kind in Exponent lowering");
+
+ auto funcTy = func.getType();
+ llvm::SmallVector<mlir::Value> args = {
+ builder.createConvert(loc, funcTy.getInput(0), x)};
+
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
+/// Generate call to Fraction instrinsic runtime routine.
+mlir::Value fir::runtime::genFraction(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value x) {
+ mlir::FuncOp func;
+ mlir::Type fltTy = x.getType();
+
+ if (fltTy.isF32())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Fraction4)>(loc, builder);
+ else if (fltTy.isF64())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Fraction8)>(loc, builder);
+ else if (fltTy.isF80())
+ func = fir::runtime::getRuntimeFunc<ForcedFraction10>(loc, builder);
+ else if (fltTy.isF128())
+ func = fir::runtime::getRuntimeFunc<ForcedFraction16>(loc, builder);
+ else
+ fir::emitFatalError(loc, "unsupported real kind in Fraction lowering");
+
+ auto funcTy = func.getType();
+ llvm::SmallVector<mlir::Value> args = {
+ builder.createConvert(loc, funcTy.getInput(0), x)};
+
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
+/// Generate call to Nearest intrinsic runtime routine.
+mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value x,
+ mlir::Value s) {
+ mlir::FuncOp func;
+ mlir::Type fltTy = x.getType();
+
+ if (fltTy.isF32())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Nearest4)>(loc, builder);
+ else if (fltTy.isF64())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Nearest8)>(loc, builder);
+ else if (fltTy.isF80())
+ func = fir::runtime::getRuntimeFunc<ForcedNearest10>(loc, builder);
+ else if (fltTy.isF128())
+ func = fir::runtime::getRuntimeFunc<ForcedNearest16>(loc, builder);
+ else
+ fir::emitFatalError(loc, "unsupported REAL kind in Nearest lowering");
+
+ auto funcTy = func.getType();
+
+ mlir::Type sTy = s.getType();
+ mlir::Value zero = builder.createRealZeroConstant(loc, sTy);
+ auto cmp = builder.create<mlir::arith::CmpFOp>(
+ loc, mlir::arith::CmpFPredicate::OGT, s, zero);
+
+ mlir::Type boolTy = mlir::IntegerType::get(builder.getContext(), 1);
+ mlir::Value False = builder.createIntegerConstant(loc, boolTy, 0);
+ mlir::Value True = builder.createIntegerConstant(loc, boolTy, 1);
+
+ mlir::Value positive = builder.create<mlir::SelectOp>(loc, cmp, True, False);
+ auto args = fir::runtime::createArguments(builder, loc, funcTy, x, positive);
+
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
+/// Generate call to RRSpacing intrinsic runtime routine.
+mlir::Value fir::runtime::genRRSpacing(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value x) {
+ mlir::FuncOp func;
+ mlir::Type fltTy = x.getType();
+
+ if (fltTy.isF32())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(RRSpacing4)>(loc, builder);
+ else if (fltTy.isF64())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(RRSpacing8)>(loc, builder);
+ else if (fltTy.isF80())
+ func = fir::runtime::getRuntimeFunc<ForcedRRSpacing10>(loc, builder);
+ else if (fltTy.isF128())
+ func = fir::runtime::getRuntimeFunc<ForcedRRSpacing16>(loc, builder);
+ else
+ fir::emitFatalError(loc, "unsupported real kind in RRSpacing lowering");
+
+ auto funcTy = func.getType();
+ llvm::SmallVector<mlir::Value> args = {
+ builder.createConvert(loc, funcTy.getInput(0), x)};
+
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
+/// Generate call to Scale intrinsic runtime routine.
+mlir::Value fir::runtime::genScale(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value x,
+ mlir::Value i) {
+ mlir::FuncOp func;
+ mlir::Type fltTy = x.getType();
+
+ if (fltTy.isF32())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Scale4)>(loc, builder);
+ else if (fltTy.isF64())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Scale8)>(loc, builder);
+ else if (fltTy.isF80())
+ func = fir::runtime::getRuntimeFunc<ForcedScale10>(loc, builder);
+ else if (fltTy.isF128())
+ func = fir::runtime::getRuntimeFunc<ForcedScale16>(loc, builder);
+ else
+ fir::emitFatalError(loc, "unsupported REAL kind in Scale lowering");
+
+ auto funcTy = func.getType();
+ auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i);
+
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
+/// Generate call to Set_exponent instrinsic runtime routine.
+mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value x,
+ mlir::Value i) {
+ mlir::FuncOp func;
+ mlir::Type fltTy = x.getType();
+
+ if (fltTy.isF32())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(SetExponent4)>(loc, builder);
+ else if (fltTy.isF64())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(SetExponent8)>(loc, builder);
+ else if (fltTy.isF80())
+ func = fir::runtime::getRuntimeFunc<ForcedSetExponent10>(loc, builder);
+ else if (fltTy.isF128())
+ func = fir::runtime::getRuntimeFunc<ForcedSetExponent16>(loc, builder);
+ else
+ fir::emitFatalError(loc, "unsupported real kind in Fraction lowering");
+
+ auto funcTy = func.getType();
+ auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i);
+
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
+
+/// Generate call to Spacing intrinsic runtime routine.
+mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder,
+ mlir::Location loc, mlir::Value x) {
+ mlir::FuncOp func;
+ mlir::Type fltTy = x.getType();
+
+ if (fltTy.isF32())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Spacing4)>(loc, builder);
+ else if (fltTy.isF64())
+ func = fir::runtime::getRuntimeFunc<mkRTKey(Spacing8)>(loc, builder);
+ else if (fltTy.isF80())
+ func = fir::runtime::getRuntimeFunc<ForcedSpacing10>(loc, builder);
+ else if (fltTy.isF128())
+ func = fir::runtime::getRuntimeFunc<ForcedSpacing16>(loc, builder);
+ else
+ fir::emitFatalError(loc, "unsupported real kind in Spacing lowering");
+
+ auto funcTy = func.getType();
+ llvm::SmallVector<mlir::Value> args = {
+ builder.createConvert(loc, funcTy.getInput(0), x)};
+
+ return builder.create<fir::CallOp>(loc, func, args).getResult(0);
+}
diff --git a/flang/unittests/Optimizer/Builder/Runtime/NumericTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/NumericTest.cpp
new file mode 100644
index 0000000000000..13dd80ef378f6
--- /dev/null
+++ b/flang/unittests/Optimizer/Builder/Runtime/NumericTest.cpp
@@ -0,0 +1,123 @@
+//===- NumericTest.cpp -- Numeric intrinsic 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/Numeric.h"
+#include "RuntimeCallTestBase.h"
+#include "gtest/gtest.h"
+
+void testGenExponent(fir::FirOpBuilder &builder, mlir::Type resultType,
+ mlir::Type xType, llvm::StringRef fctName) {
+ auto loc = builder.getUnknownLoc();
+ mlir::Value x = builder.create<fir::UndefOp>(loc, xType);
+ mlir::Value exp = fir::runtime::genExponent(builder, loc, resultType, x);
+ checkCallOp(exp.getDefiningOp(), fctName, 1, /*addLocArg=*/false);
+}
+
+TEST_F(RuntimeCallTest, genExponentTest) {
+ testGenExponent(*firBuilder, i32Ty, f32Ty, "_FortranAExponent4_4");
+ testGenExponent(*firBuilder, i64Ty, f32Ty, "_FortranAExponent4_8");
+ testGenExponent(*firBuilder, i32Ty, f64Ty, "_FortranAExponent8_4");
+ testGenExponent(*firBuilder, i64Ty, f64Ty, "_FortranAExponent8_8");
+ testGenExponent(*firBuilder, i32Ty, f80Ty, "_FortranAExponent10_4");
+ testGenExponent(*firBuilder, i64Ty, f80Ty, "_FortranAExponent10_8");
+ testGenExponent(*firBuilder, i32Ty, f128Ty, "_FortranAExponent16_4");
+ testGenExponent(*firBuilder, i64Ty, f128Ty, "_FortranAExponent16_8");
+}
+
+void testGenX(fir::FirOpBuilder &builder, mlir::Type xType,
+ mlir::Value (*genFct)(fir::FirOpBuilder &, Location, mlir::Value),
+ llvm::StringRef fctName) {
+ auto loc = builder.getUnknownLoc();
+ mlir::Value x = builder.create<fir::UndefOp>(loc, xType);
+ mlir::Value val = genFct(builder, loc, x);
+ checkCallOp(val.getDefiningOp(), fctName, 1, /*addLocArg=*/false);
+}
+
+TEST_F(RuntimeCallTest, genFractionTest) {
+ testGenX(*firBuilder, f32Ty, fir::runtime::genFraction, "_FortranAFraction4");
+ testGenX(*firBuilder, f64Ty, fir::runtime::genFraction, "_FortranAFraction8");
+ testGenX(
+ *firBuilder, f80Ty, fir::runtime::genFraction, "_FortranAFraction10");
+ testGenX(
+ *firBuilder, f128Ty, fir::runtime::genFraction, "_FortranAFraction16");
+}
+
+void testGenNearest(fir::FirOpBuilder &builder, mlir::Type xType,
+ mlir::Type sType, llvm::StringRef fctName) {
+ auto loc = builder.getUnknownLoc();
+ mlir::Value x = builder.create<fir::UndefOp>(loc, xType);
+ mlir::Value s = builder.create<fir::UndefOp>(loc, sType);
+ mlir::Value nearest = fir::runtime::genNearest(builder, loc, x, s);
+ checkCallOp(nearest.getDefiningOp(), fctName, 2, /*addLocArg=*/false);
+ auto callOp = mlir::dyn_cast<fir::CallOp>(nearest.getDefiningOp());
+ mlir::Value select = callOp.getOperands()[1];
+ EXPECT_TRUE(mlir::isa<mlir::SelectOp>(select.getDefiningOp()));
+ auto selectOp = mlir::dyn_cast<mlir::SelectOp>(select.getDefiningOp());
+ mlir::Value cmp = selectOp.condition();
+ EXPECT_TRUE(mlir::isa<mlir::arith::CmpFOp>(cmp.getDefiningOp()));
+ auto cmpOp = mlir::dyn_cast<mlir::arith::CmpFOp>(cmp.getDefiningOp());
+ EXPECT_EQ(s, cmpOp.lhs());
+}
+
+TEST_F(RuntimeCallTest, genNearestTest) {
+ testGenNearest(*firBuilder, f32Ty, f32Ty, "_FortranANearest4");
+ testGenNearest(*firBuilder, f64Ty, f32Ty, "_FortranANearest8");
+ testGenNearest(*firBuilder, f80Ty, f32Ty, "_FortranANearest10");
+ testGenNearest(*firBuilder, f128Ty, f32Ty, "_FortranANearest16");
+}
+
+TEST_F(RuntimeCallTest, genRRSpacingTest) {
+ testGenX(
+ *firBuilder, f32Ty, fir::runtime::genRRSpacing, "_FortranARRSpacing4");
+ testGenX(
+ *firBuilder, f64Ty, fir::runtime::genRRSpacing, "_FortranARRSpacing8");
+ testGenX(
+ *firBuilder, f80Ty, fir::runtime::genRRSpacing, "_FortranARRSpacing10");
+ testGenX(
+ *firBuilder, f128Ty, fir::runtime::genRRSpacing, "_FortranARRSpacing16");
+}
+
+void testGenXI(fir::FirOpBuilder &builder, mlir::Type xType, mlir::Type iType,
+ mlir::Value (*genFct)(
+ fir::FirOpBuilder &, Location, mlir::Value, mlir::Value),
+ llvm::StringRef fctName) {
+ auto loc = builder.getUnknownLoc();
+ mlir::Value x = builder.create<fir::UndefOp>(loc, xType);
+ mlir::Value i = builder.create<fir::UndefOp>(loc, iType);
+ mlir::Value val = genFct(builder, loc, x, i);
+ checkCallOp(val.getDefiningOp(), fctName, 2, /*addLocArg=*/false);
+}
+
+TEST_F(RuntimeCallTest, genScaleTest) {
+ testGenXI(
+ *firBuilder, f32Ty, f32Ty, fir::runtime::genScale, "_FortranAScale4");
+ testGenXI(
+ *firBuilder, f64Ty, f32Ty, fir::runtime::genScale, "_FortranAScale8");
+ testGenXI(
+ *firBuilder, f80Ty, f32Ty, fir::runtime::genScale, "_FortranAScale10");
+ testGenXI(
+ *firBuilder, f128Ty, f32Ty, fir::runtime::genScale, "_FortranAScale16");
+}
+
+TEST_F(RuntimeCallTest, genSetExponentTest) {
+ testGenXI(*firBuilder, f32Ty, f32Ty, fir::runtime::genSetExponent,
+ "_FortranASetExponent4");
+ testGenXI(*firBuilder, f64Ty, f32Ty, fir::runtime::genSetExponent,
+ "_FortranASetExponent8");
+ testGenXI(*firBuilder, f80Ty, f32Ty, fir::runtime::genSetExponent,
+ "_FortranASetExponent10");
+ testGenXI(*firBuilder, f128Ty, f32Ty, fir::runtime::genSetExponent,
+ "_FortranASetExponent16");
+}
+
+TEST_F(RuntimeCallTest, genSpacingTest) {
+ testGenX(*firBuilder, f32Ty, fir::runtime::genSpacing, "_FortranASpacing4");
+ testGenX(*firBuilder, f64Ty, fir::runtime::genSpacing, "_FortranASpacing8");
+ testGenX(*firBuilder, f80Ty, fir::runtime::genSpacing, "_FortranASpacing10");
+ testGenX(*firBuilder, f128Ty, fir::runtime::genSpacing, "_FortranASpacing16");
+}
diff --git a/flang/unittests/Optimizer/CMakeLists.txt b/flang/unittests/Optimizer/CMakeLists.txt
index 1ade44cd1904f..2f0f9c99fe3dc 100644
--- a/flang/unittests/Optimizer/CMakeLists.txt
+++ b/flang/unittests/Optimizer/CMakeLists.txt
@@ -14,6 +14,7 @@ add_flang_unittest(FlangOptimizerTests
Builder/DoLoopHelperTest.cpp
Builder/FIRBuilderTest.cpp
Builder/Runtime/AssignTest.cpp
+ Builder/Runtime/NumericTest.cpp
Builder/Runtime/ReductionTest.cpp
Builder/Runtime/TransformationalTest.cpp
FIRContextTest.cpp
More information about the flang-commits
mailing list