diff --git a/flang/include/flang/Runtime/numeric.h b/flang/include/flang/Runtime/numeric.h --- a/flang/include/flang/Runtime/numeric.h +++ b/flang/include/flang/Runtime/numeric.h @@ -18,90 +18,6 @@ namespace Fortran::runtime { extern "C" { -// AINT -CppTypeFor RTNAME(Aint4_4)( - CppTypeFor); -CppTypeFor RTNAME(Aint4_8)( - CppTypeFor); -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Aint4_10)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 -CppTypeFor RTNAME(Aint4_16)( - CppTypeFor); -#endif -CppTypeFor RTNAME(Aint8_4)( - CppTypeFor); -CppTypeFor RTNAME(Aint8_8)( - CppTypeFor); -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Aint8_10)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 -CppTypeFor RTNAME(Aint8_16)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Aint10_4)( - CppTypeFor); -CppTypeFor RTNAME(Aint10_8)( - CppTypeFor); -CppTypeFor RTNAME(Aint10_10)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 -CppTypeFor RTNAME(Aint16_4)( - CppTypeFor); -CppTypeFor RTNAME(Aint16_8)( - CppTypeFor); -CppTypeFor RTNAME(Aint16_16)( - CppTypeFor); -#endif - -// ANINT -CppTypeFor RTNAME(Anint4_4)( - CppTypeFor); -CppTypeFor RTNAME(Anint4_8)( - CppTypeFor); -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Anint4_10)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 -CppTypeFor RTNAME(Anint4_16)( - CppTypeFor); -#endif -CppTypeFor RTNAME(Anint8_4)( - CppTypeFor); -CppTypeFor RTNAME(Anint8_8)( - CppTypeFor); -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Anint8_10)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 113 -CppTypeFor RTNAME(Anint8_16)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Anint10_4)( - CppTypeFor); -CppTypeFor RTNAME(Anint10_8)( - CppTypeFor); -CppTypeFor RTNAME(Anint10_10)( - CppTypeFor); -#endif -#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 -CppTypeFor RTNAME(Anint16_4)( - CppTypeFor); -CppTypeFor RTNAME(Anint16_8)( - CppTypeFor); -CppTypeFor RTNAME(Anint16_16)( - CppTypeFor); -#endif - // CEILING CppTypeFor RTNAME(Ceiling4_1)( CppTypeFor); diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -1045,6 +1045,11 @@ 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 @@ // 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}, {"anint", "llvm.round.f64", genF64F64FuncType, genMathOp}, + {"anint", "llvm.round.f80", genF80F80FuncType, + genMathOp}, + {"anint", "llvm.round.f128", genF128F128FuncType, + genMathOp}, {"atan", "atanf", genF32F32FuncType, genMathOp}, {"atan", "atan", genF64F64FuncType, genMathOp}, {"atan2", "atan2f", genF32F32F32FuncType, genMathOp}, diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -16,13 +16,8 @@ namespace Fortran::runtime { -// AINT -template inline RESULT Aint(ARG x) { - return std::trunc(x); -} - -// ANINT & NINT -template inline RESULT Anint(ARG x) { +// NINT (16.9.141) +template inline RESULT Nint(ARG x) { if (x >= 0) { return std::trunc(x + ARG{0.5}); } else { @@ -163,126 +158,6 @@ extern "C" { -CppTypeFor RTNAME(Aint4_4)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint4_8)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint8_4)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint8_8)( - CppTypeFor x) { - return Aint>(x); -} -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Aint4_10)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint8_10)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint10_4)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint10_8)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint10_10)( - CppTypeFor x) { - return Aint>(x); -} -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTNAME(Aint4_16)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint8_16)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint16_4)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint16_8)( - CppTypeFor x) { - return Aint>(x); -} -CppTypeFor RTNAME(Aint16_16)( - CppTypeFor x) { - return Aint>(x); -} -#endif - -CppTypeFor RTNAME(Anint4_4)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint4_8)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint8_4)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint8_8)( - CppTypeFor x) { - return Anint>(x); -} -#if LDBL_MANT_DIG == 64 -CppTypeFor RTNAME(Anint4_10)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint8_10)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint10_4)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint10_8)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint10_10)( - CppTypeFor x) { - return Anint>(x); -} -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTNAME(Anint4_16)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint8_16)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint16_4)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint16_8)( - CppTypeFor x) { - return Anint>(x); -} -CppTypeFor RTNAME(Anint16_16)( - CppTypeFor x) { - return Anint>(x); -} -#endif - CppTypeFor RTNAME(Ceiling4_1)( CppTypeFor x) { return Ceiling>(x); @@ -689,92 +564,92 @@ CppTypeFor RTNAME(Nint4_1)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint4_2)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint4_4)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint4_8)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(Nint4_16)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #endif CppTypeFor RTNAME(Nint8_1)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint8_2)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint8_4)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint8_8)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(Nint8_16)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #endif #if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(Nint10_1)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint10_2)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint10_4)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint10_8)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(Nint10_16)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #endif #elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(Nint16_1)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint16_2)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint16_4)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } CppTypeFor RTNAME(Nint16_8)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(Nint16_16)( CppTypeFor x) { - return Anint>(x); + return Nint>(x); } #endif #endif diff --git a/flang/test/Lower/Intrinsics/aint.f90 b/flang/test/Lower/Intrinsics/aint.f90 --- a/flang/test/Lower/Intrinsics/aint.f90 +++ b/flang/test/Lower/Intrinsics/aint.f90 @@ -10,3 +10,45 @@ real :: a, b b = aint(a) end subroutine + +! CHECK-LABEL: func.func @_QPaint_test_real8( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "a"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.call @llvm.trunc.f64(%[[VAL_2]]) : (f64) -> f64 +! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.call @llvm.trunc.f80(%[[VAL_2]]) : (f80) -> f80 +! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.call @llvm.trunc.f128(%[[VAL_2]]) : (f128) -> f128 +! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! CHECK: return +! CHECK: } + +subroutine aint_test_real16(a, b) + real(16) :: a, b + b = aint(a) +end subroutine diff --git a/flang/test/Lower/Intrinsics/anint.f90 b/flang/test/Lower/Intrinsics/anint.f90 --- a/flang/test/Lower/Intrinsics/anint.f90 +++ b/flang/test/Lower/Intrinsics/anint.f90 @@ -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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f32) -> f32 +! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f64) -> f64 +! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f80) -> f80 +! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! 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 {fir.bindc_name = "a"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "b"}) { +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f128) -> f128 +! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref +! CHECK: return +! CHECK: } + +subroutine anint_test_real16(a, b) + real(16) :: a, b + b = anint(a) +end subroutine diff --git a/flang/test/Lower/math-lowering.f90 b/flang/test/Lower/math-lowering.f90 --- a/flang/test/Lower/math-lowering.f90 +++ b/flang/test/Lower/math-lowering.f90 @@ -77,6 +77,22 @@ ! 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 @@ ! 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 diff --git a/flang/unittests/Runtime/Numeric.cpp b/flang/unittests/Runtime/Numeric.cpp --- a/flang/unittests/Runtime/Numeric.cpp +++ b/flang/unittests/Runtime/Numeric.cpp @@ -18,28 +18,6 @@ // 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>::infinity()), - std::numeric_limits>::infinity()); - EXPECT_TRUE( - std::isnan(RTNAME(Aint8_8)(std::numeric_limits>::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>::infinity()), - std::numeric_limits>::infinity()); - EXPECT_TRUE( - std::isnan(RTNAME(Aint8_8)(std::numeric_limits>::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);