[flang] Support aint/anint for 80/128 bit in lowering

For aint/anint, LLVM conversion operations llvm.trunc and llvm.round
can support the edge case of aint(-0.) and anint(-0.). The output is -0.
and it is the same of `gfortran` and `classic flang`, while the output
of `ifort` is 0.. The `real(10)/real(16)` is not supported before.
Support it and remove the runtime functions for aint/anint.

For nint, `gfortran`, `ifort`, and LLVM Flang using llvm.lround have
different results when the magnitude of argument is more than the max of
result value range. So delay its support in lowering after more
investigations.

Reviewed By: vzakhari

Differential Revision: https://reviews.llvm.org/D130024
This commit is contained in:
Peixin Qiao 2022-07-23 14:44:20 +08:00
parent 33c18fbc19
commit 3ccd4ce29c
7 changed files with 162 additions and 256 deletions

View File

@ -18,90 +18,6 @@
namespace Fortran::runtime {
extern "C" {
// AINT
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint4_4)(
CppTypeFor<TypeCategory::Real, 4>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint4_8)(
CppTypeFor<TypeCategory::Real, 4>);
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint4_10)(
CppTypeFor<TypeCategory::Real, 4>);
#endif
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint4_16)(
CppTypeFor<TypeCategory::Real, 4>);
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint8_4)(
CppTypeFor<TypeCategory::Real, 8>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint8_8)(
CppTypeFor<TypeCategory::Real, 8>);
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint8_10)(
CppTypeFor<TypeCategory::Real, 8>);
#endif
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint8_16)(
CppTypeFor<TypeCategory::Real, 8>);
#endif
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint10_4)(
CppTypeFor<TypeCategory::Real, 10>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint10_8)(
CppTypeFor<TypeCategory::Real, 10>);
CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint10_10)(
CppTypeFor<TypeCategory::Real, 10>);
#endif
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint16_4)(
CppTypeFor<TypeCategory::Real, 16>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint16_8)(
CppTypeFor<TypeCategory::Real, 16>);
CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint16_16)(
CppTypeFor<TypeCategory::Real, 16>);
#endif
// ANINT
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint4_4)(
CppTypeFor<TypeCategory::Real, 4>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint4_8)(
CppTypeFor<TypeCategory::Real, 4>);
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint4_10)(
CppTypeFor<TypeCategory::Real, 4>);
#endif
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint4_16)(
CppTypeFor<TypeCategory::Real, 4>);
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint8_4)(
CppTypeFor<TypeCategory::Real, 8>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint8_8)(
CppTypeFor<TypeCategory::Real, 8>);
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint8_10)(
CppTypeFor<TypeCategory::Real, 8>);
#endif
#if LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint8_16)(
CppTypeFor<TypeCategory::Real, 8>);
#endif
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint10_4)(
CppTypeFor<TypeCategory::Real, 10>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint10_8)(
CppTypeFor<TypeCategory::Real, 10>);
CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint10_10)(
CppTypeFor<TypeCategory::Real, 10>);
#endif
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint16_4)(
CppTypeFor<TypeCategory::Real, 16>);
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint16_8)(
CppTypeFor<TypeCategory::Real, 16>);
CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint16_16)(
CppTypeFor<TypeCategory::Real, 16>);
#endif
// CEILING
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)(
CppTypeFor<TypeCategory::Real, 4>);

View File

@ -1045,6 +1045,11 @@ static mlir::FunctionType genF64F64FuncType(mlir::MLIRContext *context) {
return mlir::FunctionType::get(context, {t}, {t});
}
static mlir::FunctionType genF80F80FuncType(mlir::MLIRContext *context) {
mlir::Type t = mlir::FloatType::getF80(context);
return mlir::FunctionType::get(context, {t}, {t});
}
static mlir::FunctionType genF128F128FuncType(mlir::MLIRContext *context) {
mlir::Type t = mlir::FloatType::getF128(context);
return mlir::FunctionType::get(context, {t}, {t});
@ -1190,11 +1195,17 @@ static constexpr MathOperation mathOperations[] = {
// llvm.trunc behaves the same way as libm's trunc.
{"aint", "llvm.trunc.f32", genF32F32FuncType, genLibCall},
{"aint", "llvm.trunc.f64", genF64F64FuncType, genLibCall},
{"aint", "llvm.trunc.f80", genF80F80FuncType, genLibCall},
{"aint", "llvm.trunc.f128", genF128F128FuncType, genLibCall},
// llvm.round behaves the same way as libm's round.
{"anint", "llvm.round.f32", genF32F32FuncType,
genMathOp<mlir::LLVM::RoundOp>},
{"anint", "llvm.round.f64", genF64F64FuncType,
genMathOp<mlir::LLVM::RoundOp>},
{"anint", "llvm.round.f80", genF80F80FuncType,
genMathOp<mlir::LLVM::RoundOp>},
{"anint", "llvm.round.f128", genF128F128FuncType,
genMathOp<mlir::LLVM::RoundOp>},
{"atan", "atanf", genF32F32FuncType, genMathOp<mlir::math::AtanOp>},
{"atan", "atan", genF64F64FuncType, genMathOp<mlir::math::AtanOp>},
{"atan2", "atan2f", genF32F32F32FuncType, genMathOp<mlir::math::Atan2Op>},

View File

@ -16,13 +16,8 @@
namespace Fortran::runtime {
// AINT
template <typename RESULT, typename ARG> inline RESULT Aint(ARG x) {
return std::trunc(x);
}
// ANINT & NINT
template <typename RESULT, typename ARG> inline RESULT Anint(ARG x) {
// NINT (16.9.141)
template <typename RESULT, typename ARG> inline RESULT Nint(ARG x) {
if (x >= 0) {
return std::trunc(x + ARG{0.5});
} else {
@ -163,126 +158,6 @@ template <int PREC, typename T> inline T Nearest(T x, bool positive) {
extern "C" {
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint4_4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint4_8)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint8_4)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint8_8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint4_10)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Aint<CppTypeFor<TypeCategory::Real, 10>>(x);
}
CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint8_10)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Aint<CppTypeFor<TypeCategory::Real, 10>>(x);
}
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint10_4)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint10_8)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
CppTypeFor<TypeCategory::Real, 10> RTNAME(Aint10_10)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Aint<CppTypeFor<TypeCategory::Real, 10>>(x);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint4_16)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Aint<CppTypeFor<TypeCategory::Real, 16>>(x);
}
CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint8_16)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Aint<CppTypeFor<TypeCategory::Real, 16>>(x);
}
CppTypeFor<TypeCategory::Real, 4> RTNAME(Aint16_4)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Aint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Aint16_8)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Aint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
CppTypeFor<TypeCategory::Real, 16> RTNAME(Aint16_16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Aint<CppTypeFor<TypeCategory::Real, 16>>(x);
}
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint4_4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint4_8)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint8_4)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint8_8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint4_10)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Real, 10>>(x);
}
CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint8_10)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Real, 10>>(x);
}
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint10_4)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint10_8)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
CppTypeFor<TypeCategory::Real, 10> RTNAME(Anint10_10)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Real, 10>>(x);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint4_16)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Real, 16>>(x);
}
CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint8_16)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Real, 16>>(x);
}
CppTypeFor<TypeCategory::Real, 4> RTNAME(Anint16_4)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Real, 4>>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Anint16_8)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Real, 8>>(x);
}
CppTypeFor<TypeCategory::Real, 16> RTNAME(Anint16_16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Real, 16>>(x);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
@ -689,92 +564,92 @@ CppTypeFor<TypeCategory::Real, 16> RTNAME(Nearest16)(
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint4_1)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint4_2)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint4_4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint4_8)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint4_16)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint8_1)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint8_2)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint8_4)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint8_8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint8_16)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint10_1)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint10_2)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint10_4)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint10_8)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint10_16)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint16_1)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 1>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint16_2)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 2>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint16_4)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 4>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint16_8)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 8>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint16_16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Anint<CppTypeFor<TypeCategory::Integer, 16>>(x);
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#endif

View File

@ -10,3 +10,45 @@ subroutine aint_test(a, b)
real :: a, b
b = aint(a)
end subroutine
! CHECK-LABEL: func.func @_QPaint_test_real8(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f64> {fir.bindc_name = "a"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f64> {fir.bindc_name = "b"}) {
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f64>
! CHECK: %[[VAL_3:.*]] = fir.call @llvm.trunc.f64(%[[VAL_2]]) : (f64) -> f64
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f64>
! CHECK: return
! CHECK: }
subroutine aint_test_real8(a, b)
real(8) :: a, b
b = aint(a)
end subroutine
! CHECK-LABEL: func.func @_QPaint_test_real10(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f80> {fir.bindc_name = "a"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f80> {fir.bindc_name = "b"}) {
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f80>
! CHECK: %[[VAL_3:.*]] = fir.call @llvm.trunc.f80(%[[VAL_2]]) : (f80) -> f80
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f80>
! CHECK: return
! CHECK: }
subroutine aint_test_real10(a, b)
real(10) :: a, b
b = aint(a)
end subroutine
! CHECK-LABEL: func.func @_QPaint_test_real16(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f128> {fir.bindc_name = "a"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f128> {fir.bindc_name = "b"}) {
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f128>
! CHECK: %[[VAL_3:.*]] = fir.call @llvm.trunc.f128(%[[VAL_2]]) : (f128) -> f128
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f128>
! CHECK: return
! CHECK: }
subroutine aint_test_real16(a, b)
real(16) :: a, b
b = aint(a)
end subroutine

View File

@ -1,9 +1,57 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! CHECK-LABEL: anint_test
! CHECK-LABEL: func.func @_QPanint_test(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> {fir.bindc_name = "a"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}) {
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f32>
! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f32) -> f32
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f32>
! CHECK: return
! CHECK: }
subroutine anint_test(a, b)
real :: a, b
! CHECK: "llvm.intr.round"
b = anint(a)
end subroutine
! CHECK-LABEL: func.func @_QPanint_test_real8(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f64> {fir.bindc_name = "a"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f64> {fir.bindc_name = "b"}) {
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f64>
! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f64) -> f64
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f64>
! CHECK: return
! CHECK: }
subroutine anint_test_real8(a, b)
real(8) :: a, b
b = anint(a)
end subroutine
! CHECK-LABEL: func.func @_QPanint_test_real10(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f80> {fir.bindc_name = "a"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f80> {fir.bindc_name = "b"}) {
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f80>
! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f80) -> f80
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f80>
! CHECK: return
! CHECK: }
subroutine anint_test_real10(a, b)
real(10) :: a, b
b = anint(a)
end subroutine
! CHECK-LABEL: func.func @_QPanint_test_real16(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f128> {fir.bindc_name = "a"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f128> {fir.bindc_name = "b"}) {
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f128>
! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f128) -> f128
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f128>
! CHECK: return
! CHECK: }
subroutine anint_test_real16(a, b)
real(16) :: a, b
b = anint(a)
end subroutine

View File

@ -77,6 +77,22 @@ end function
! ALL-LABEL: @_QPtest_real8
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.trunc.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64
function test_real10(x)
real(10) :: x, test_real10
test_real10 = aint(x)
end function
! ALL-LABEL: @_QPtest_real10
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.trunc.f80({{%[A-Za-z0-9._]+}}) : (f80) -> f80
function test_real16(x)
real(16) :: x, test_real16
test_real16 = aint(x)
end function
! ALL-LABEL: @_QPtest_real16
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.trunc.f128({{%[A-Za-z0-9._]+}}) : (f128) -> f128
//--- anint.f90
! RUN: bbc -emit-fir %t/anint.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/anint.f90
! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=fast %t/anint.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/anint.f90
@ -105,6 +121,26 @@ end function
! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f64) -> f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64
function test_real10(x)
real(10) :: x, test_real10
test_real10 = anint(x)
end function
! ALL-LABEL: @_QPtest_real10
! FAST: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f80) -> f80
! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f80) -> f80
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f80({{%[A-Za-z0-9._]+}}) : (f80) -> f80
function test_real16(x)
real(16) :: x, test_real16
test_real16 = anint(x)
end function
! ALL-LABEL: @_QPtest_real16
! FAST: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f128) -> f128
! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f128) -> f128
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f128({{%[A-Za-z0-9._]+}}) : (f128) -> f128
//--- atan.f90
! RUN: bbc -emit-fir %t/atan.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/atan.f90
! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=fast %t/atan.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/atan.f90

View File

@ -18,28 +18,6 @@ template <int KIND> using Real = CppTypeFor<TypeCategory::Real, KIND>;
// Simple tests of numeric intrinsic functions using examples from Fortran 2018
TEST(Numeric, Aint) {
EXPECT_EQ(RTNAME(Aint4_4)(Real<4>{3.7}), 3.0);
EXPECT_EQ(RTNAME(Aint8_4)(Real<8>{-3.7}), -3.0);
EXPECT_EQ(RTNAME(Aint8_8)(Real<8>{0}), 0.0);
EXPECT_EQ(RTNAME(Aint4_4)(std::numeric_limits<Real<4>>::infinity()),
std::numeric_limits<Real<4>>::infinity());
EXPECT_TRUE(
std::isnan(RTNAME(Aint8_8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
TEST(Numeric, Anint) {
EXPECT_EQ(RTNAME(Anint4_4)(Real<4>{2.783}), 3.0);
EXPECT_EQ(RTNAME(Anint8_4)(Real<8>{-2.783}), -3.0);
EXPECT_EQ(RTNAME(Anint4_4)(Real<4>{2.5}), 3.0);
EXPECT_EQ(RTNAME(Anint8_4)(Real<8>{-2.5}), -3.0);
EXPECT_EQ(RTNAME(Anint8_8)(Real<8>{0}), 0.0);
EXPECT_EQ(RTNAME(Anint4_4)(std::numeric_limits<Real<4>>::infinity()),
std::numeric_limits<Real<4>>::infinity());
EXPECT_TRUE(
std::isnan(RTNAME(Aint8_8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
TEST(Numeric, Ceiling) {
EXPECT_EQ(RTNAME(Ceiling4_4)(Real<4>{3.7}), 4);
EXPECT_EQ(RTNAME(Ceiling8_8)(Real<8>{-3.7}), -3);