[flang-commits] [flang] 9e8f677 - [flang] Lower exponentiation without using pgmath.
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Wed Dec 14 15:33:12 PST 2022
Author: Slava Zakharin
Date: 2022-12-14T15:32:51-08:00
New Revision: 9e8f6772990131d6aa62ba7010907d9dceb45d08
URL: https://github.com/llvm/llvm-project/commit/9e8f6772990131d6aa62ba7010907d9dceb45d08
DIFF: https://github.com/llvm/llvm-project/commit/9e8f6772990131d6aa62ba7010907d9dceb45d08.diff
LOG: [flang] Lower exponentiation without using pgmath.
Exponentiation is lowered to either math::FPowI or Fortran runtime
call (in case of --math-runtime=precise).
MathToFuncs convertor will convert math::FPowI operations with
exponent width >32 to calls of outlined implementations and otherwise
will leave the operation to MathToLLVM convertor.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D139806
Added:
Modified:
flang/include/flang/Runtime/numeric.h
flang/lib/Lower/IntrinsicCall.cpp
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/runtime/numeric.cpp
flang/test/Lower/HLFIR/binary-ops.f90
flang/test/Lower/math-lowering.f90
flang/test/Lower/power-operator.f90
flang/unittests/Runtime/Numeric.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Runtime/numeric.h b/flang/include/flang/Runtime/numeric.h
index 4b656a762e31c..2710659081013 100644
--- a/flang/include/flang/Runtime/numeric.h
+++ b/flang/include/flang/Runtime/numeric.h
@@ -377,6 +377,40 @@ CppTypeFor<TypeCategory::Real, 16> RTNAME(Spacing16)(
CppTypeFor<TypeCategory::Real, 16>);
#endif
+CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4i)(
+ CppTypeFor<TypeCategory::Real, 4> b,
+ CppTypeFor<TypeCategory::Integer, 4> e);
+CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8i)(
+ CppTypeFor<TypeCategory::Real, 8> b,
+ CppTypeFor<TypeCategory::Integer, 4> e);
+#if LDBL_MANT_DIG == 64
+CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10i)(
+ CppTypeFor<TypeCategory::Real, 10> b,
+ CppTypeFor<TypeCategory::Integer, 4> e);
+#endif
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
+CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16i)(
+ CppTypeFor<TypeCategory::Real, 16> b,
+ CppTypeFor<TypeCategory::Integer, 4> e);
+#endif
+
+CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4k)(
+ CppTypeFor<TypeCategory::Real, 4> b,
+ CppTypeFor<TypeCategory::Integer, 8> e);
+CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8k)(
+ CppTypeFor<TypeCategory::Real, 8> b,
+ CppTypeFor<TypeCategory::Integer, 8> e);
+#if LDBL_MANT_DIG == 64
+CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10k)(
+ CppTypeFor<TypeCategory::Real, 10> b,
+ CppTypeFor<TypeCategory::Integer, 8> e);
+#endif
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
+CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16k)(
+ CppTypeFor<TypeCategory::Real, 16> b,
+ CppTypeFor<TypeCategory::Integer, 8> e);
+#endif
+
} // extern "C"
} // namespace Fortran::runtime
#endif // FORTRAN_RUNTIME_NUMERIC_H_
diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index bda58064796d4..595576cd7084d 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -1513,9 +1513,14 @@ static constexpr MathOperation mathOperations[] = {
genComplexMathOp<mlir::complex::PowOp>},
{"pow", "cpow", genComplexComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::PowOp>},
- // TODO: add PowIOp in math and complex dialects.
- {"pow", "llvm.powi.f32.i32", genF32F32IntFuncType<32>, genLibCall},
- {"pow", "llvm.powi.f64.i32", genF64F64IntFuncType<32>, genLibCall},
+ {"pow", RTNAME_STRING(FPow4i), genF32F32IntFuncType<32>,
+ genMathOp<mlir::math::FPowIOp>},
+ {"pow", RTNAME_STRING(FPow8i), genF64F64IntFuncType<32>,
+ genMathOp<mlir::math::FPowIOp>},
+ {"pow", RTNAME_STRING(FPow4k), genF32F32IntFuncType<64>,
+ genMathOp<mlir::math::FPowIOp>},
+ {"pow", RTNAME_STRING(FPow8k), genF64F64IntFuncType<64>,
+ genMathOp<mlir::math::FPowIOp>},
{"pow", RTNAME_STRING(cpowi), genComplexComplexIntFuncType<4, 32>,
genLibCall},
{"pow", RTNAME_STRING(zpowi), genComplexComplexIntFuncType<8, 32>,
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 85f2f2173a5c3..b195ad0992ac1 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -3628,7 +3628,14 @@ class FIRToLLVMLowering
// function operations in it. We have to run such conversions
// as passes here.
mlir::OpPassManager mathConvertionPM("builtin.module");
- mathConvertionPM.addPass(mlir::createConvertMathToFuncs());
+
+ // Convert math::FPowI operations to inline implementation
+ // only if the exponent's width is greater than 32, otherwise,
+ // it will be lowered to LLVM intrinsic operation by a later conversion.
+ mlir::ConvertMathToFuncsOptions mathToFuncsOptions{};
+ mathToFuncsOptions.minWidthOfFPowIExponent = 33;
+ mathConvertionPM.addPass(
+ mlir::createConvertMathToFuncs(mathToFuncsOptions));
mathConvertionPM.addPass(mlir::createConvertComplexToStandardPass());
if (mlir::failed(runPipeline(mathConvertionPM, mod)))
return signalPassFailure();
diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp
index 0a37fc96d313c..7afa5802db049 100644
--- a/flang/runtime/numeric.cpp
+++ b/flang/runtime/numeric.cpp
@@ -255,6 +255,38 @@ template <int PREC, typename T> inline T Nearest(T x, bool positive) {
}
}
+// Exponentiation operator for (Real ** Integer) cases (10.1.5.2.1).
+template <typename BTy, typename ETy> BTy FPowI(BTy base, ETy exp) {
+ if (exp == ETy{0})
+ return BTy{1};
+ bool isNegativePower{exp < ETy{0}};
+ bool isMinPower{exp == std::numeric_limits<ETy>::min()};
+ if (isMinPower) {
+ exp = std::numeric_limits<ETy>::max();
+ } else if (isNegativePower) {
+ exp = -exp;
+ }
+ BTy result{1};
+ BTy origBase{base};
+ while (true) {
+ if (exp & ETy{1}) {
+ result *= base;
+ }
+ exp >>= 1;
+ if (exp == ETy{0}) {
+ break;
+ }
+ base *= base;
+ }
+ if (isMinPower) {
+ result *= origBase;
+ }
+ if (isNegativePower) {
+ result = BTy{1} / result;
+ }
+ return result;
+}
+
extern "C" {
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)(
@@ -871,5 +903,55 @@ CppTypeFor<TypeCategory::Real, 16> RTNAME(Spacing16)(
return Spacing<113>(x);
}
#endif
+
+CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4i)(
+ CppTypeFor<TypeCategory::Real, 4> b,
+ CppTypeFor<TypeCategory::Integer, 4> e) {
+ return FPowI(b, e);
+}
+CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8i)(
+ CppTypeFor<TypeCategory::Real, 8> b,
+ CppTypeFor<TypeCategory::Integer, 4> e) {
+ return FPowI(b, e);
+}
+#if LDBL_MANT_DIG == 64
+CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10i)(
+ CppTypeFor<TypeCategory::Real, 10> b,
+ CppTypeFor<TypeCategory::Integer, 4> e) {
+ return FPowI(b, e);
+}
+#endif
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
+CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16i)(
+ CppTypeFor<TypeCategory::Real, 16> b,
+ CppTypeFor<TypeCategory::Integer, 4> e) {
+ return FPowI(b, e);
+}
+#endif
+
+CppTypeFor<TypeCategory::Real, 4> RTNAME(FPow4k)(
+ CppTypeFor<TypeCategory::Real, 4> b,
+ CppTypeFor<TypeCategory::Integer, 8> e) {
+ return FPowI(b, e);
+}
+CppTypeFor<TypeCategory::Real, 8> RTNAME(FPow8k)(
+ CppTypeFor<TypeCategory::Real, 8> b,
+ CppTypeFor<TypeCategory::Integer, 8> e) {
+ return FPowI(b, e);
+}
+#if LDBL_MANT_DIG == 64
+CppTypeFor<TypeCategory::Real, 10> RTNAME(FPow10k)(
+ CppTypeFor<TypeCategory::Real, 10> b,
+ CppTypeFor<TypeCategory::Integer, 8> e) {
+ return FPowI(b, e);
+}
+#endif
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
+CppTypeFor<TypeCategory::Real, 16> RTNAME(FPow16k)(
+ CppTypeFor<TypeCategory::Real, 16> b,
+ CppTypeFor<TypeCategory::Integer, 8> e) {
+ return FPowI(b, e);
+}
+#endif
} // extern "C"
} // namespace Fortran::runtime
diff --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90
index fb7b7648f7132..8e5dced1396d0 100644
--- a/flang/test/Lower/HLFIR/binary-ops.f90
+++ b/flang/test/Lower/HLFIR/binary-ops.f90
@@ -180,7 +180,7 @@ subroutine real_to_int_power(x, y, z)
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<f32>
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
-! CHECK: %[[VAL_8:.*]] = fir.call @llvm.powi.f32.i32(%[[VAL_6]], %[[VAL_7]]) fastmath<contract> : (f32, i32) -> f32
+! CHECK: %[[VAL_8:.*]] = math.fpowi %[[VAL_6]], %[[VAL_7]] fastmath<contract> : f32, i32
subroutine complex_to_int_power(x, y, z)
complex :: x, y
diff --git a/flang/test/Lower/math-lowering.f90 b/flang/test/Lower/math-lowering.f90
index 1bf5639f717fe..b6b720045f24b 100644
--- a/flang/test/Lower/math-lowering.f90
+++ b/flang/test/Lower/math-lowering.f90
@@ -449,35 +449,51 @@ function test_real8(x)
! RUN: bbc -emit-fir %t/exponentiation.f90 -o - --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/exponentiation.f90
! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=precise %t/exponentiation.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/exponentiation.f90
-function test_real4(x, y, s, i)
+function test_real4(x, y, s, i, k)
real :: x, y, test_real4
integer(2) :: s
integer(4) :: i
- test_real4 = x ** s + x ** y + x ** i
+ integer(8) :: k
+ test_real4 = x ** s + x ** y + x ** i + x ** k
end function
! ALL-LABEL: @_QPtest_real4
! ALL: [[STOI:%[A-Za-z0-9._]+]] = fir.convert {{%[A-Za-z0-9._]+}} : (i16) -> i32
-! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) {{.*}}: (f32, i32) -> f32
+! FAST: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32, i32
+! RELAXED: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32, i32
+! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @_FortranAFPow4i({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f32, i32) -> f32
! FAST: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32
! RELAXED: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @powf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f32, f32) -> f32
-! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f32, i32) -> f32
-
-function test_real8(x, y, s, i)
+! FAST: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32, i32
+! RELAXED: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32, i32
+! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @_FortranAFPow4i({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f32, i32) -> f32
+! FAST: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32, i64
+! RELAXED: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f32, i64
+! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @_FortranAFPow4k({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f32, i64) -> f32
+
+function test_real8(x, y, s, i, k)
real(8) :: x, y, test_real8
integer(2) :: s
integer(4) :: i
- test_real8 = x ** s + x ** y + x ** i
+ integer(8) :: k
+ test_real8 = x ** s + x ** y + x ** i + x ** k
end function
! ALL-LABEL: @_QPtest_real8
! ALL: [[STOI:%[A-Za-z0-9._]+]] = fir.convert {{%[A-Za-z0-9._]+}} : (i16) -> i32
-! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) {{.*}}: (f64, i32) -> f64
+! FAST: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64, i32
+! RELAXED: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64, i32
+! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @_FortranAFPow8i({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f64, i32) -> f64
! FAST: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64
! RELAXED: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @pow({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f64, f64) -> f64
-! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f64, i32) -> f64
+! FAST: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64, i32
+! RELAXED: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64, i32
+! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @_FortranAFPow8i({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f64, i32) -> f64
+! FAST: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64, i64
+! RELAXED: {{%[A-Za-z0-9._]+}} = math.fpowi {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} {{.*}}: f64, i64
+! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @_FortranAFPow8k({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) {{.*}}: (f64, i64) -> f64
//--- sign.f90
! RUN: bbc -emit-fir %t/sign.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/sign.f90
diff --git a/flang/test/Lower/power-operator.f90 b/flang/test/Lower/power-operator.f90
index 867830f959aa0..67b93d33e63cc 100644
--- a/flang/test/Lower/power-operator.f90
+++ b/flang/test/Lower/power-operator.f90
@@ -1,9 +1,9 @@
-! RUN: bbc -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX-FAST"
-! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
-! RUN: bbc --disable-mlir-complex -emit-fir %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
-! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX-FAST"
-! RUN: %flang_fc1 -emit-fir -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
-! RUN: %flang_fc1 -emit-fir -mllvm --disable-mlir-complex %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
+! RUN: bbc -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,FAST"
+! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s --check-prefixes="PRECISE"
+! RUN: bbc --disable-mlir-complex -emit-fir %s -o - | FileCheck %s --check-prefixes="PRECISE"
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,FAST"
+! RUN: %flang_fc1 -emit-fir -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="PRECISE"
+! RUN: %flang_fc1 -emit-fir -mllvm --disable-mlir-complex %s -o - | FileCheck %s --check-prefixes="PRECISE"
! Test power operation lowering
@@ -12,7 +12,7 @@ subroutine pow_r4_i4(x, y, z)
real :: x, z
integer :: y
z = x ** y
- ! CHECK: call @llvm.powi.f32.i32
+ ! CHECK: math.fpowi {{.*}} : f32, i32
end subroutine
! CHECK-LABEL: pow_r4_r4
@@ -27,7 +27,7 @@ subroutine pow_r4_i8(x, y, z)
real :: x, z
integer(8) :: y
z = x ** y
- ! CHECK: call @__fs_powk_1
+ ! CHECK: math.fpowi {{.*}} : f32, i64
end subroutine
! CHECK-LABEL: pow_r8_i4
@@ -35,7 +35,7 @@ subroutine pow_r8_i4(x, y, z)
real(8) :: x, z
integer :: y
z = x ** y
- ! CHECK: call @llvm.powi.f64.i32
+ ! CHECK: math.fpowi {{.*}} : f64, i32
end subroutine
! CHECK-LABEL: pow_r8_i8
@@ -43,7 +43,7 @@ subroutine pow_r8_i8(x, y, z)
real(8) :: x, z
integer(8) :: y
z = x ** y
- ! CHECK: call @__fd_powk_1
+ ! CHECK: math.fpowi {{.*}} : f64, i64
end subroutine
! CHECK-LABEL: pow_r8_r8
@@ -126,15 +126,15 @@ subroutine pow_c8_i8(x, y, z)
subroutine pow_c4_c4(x, y, z)
complex :: x, y, z
z = x ** y
- ! CMPLX-FAST: complex.pow %{{.*}}, %{{.*}} : complex<f32>
- ! CMPLX-PRECISE: call @cpowf
+ ! FAST: complex.pow %{{.*}}, %{{.*}} : complex<f32>
+ ! PRECISE: call @cpowf
end subroutine
! CHECK-LABEL: pow_c8_c8
subroutine pow_c8_c8(x, y, z)
complex(8) :: x, y, z
z = x ** y
- ! CMPLX-FAST: complex.pow %{{.*}}, %{{.*}} : complex<f64>
- ! CMPLX-PRECISE: call @cpow
+ ! FAST: complex.pow %{{.*}}, %{{.*}} : complex<f64>
+ ! PRECISE: call @cpow
end subroutine
diff --git a/flang/unittests/Runtime/Numeric.cpp b/flang/unittests/Runtime/Numeric.cpp
index 04770af50ca3e..456d25fa4e1eb 100644
--- a/flang/unittests/Runtime/Numeric.cpp
+++ b/flang/unittests/Runtime/Numeric.cpp
@@ -205,3 +205,82 @@ TEST(Numeric, Spacing) {
EXPECT_TRUE(
std::isnan(RTNAME(Spacing8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
+
+TEST(Numeric, FPowI) {
+ EXPECT_EQ(RTNAME(FPow4i)(Real<4>{0}, Int<4>{0}), Real<4>{1});
+ EXPECT_EQ(RTNAME(FPow4i)(Real<4>{0.3}, Int<4>{0}), Real<4>{1});
+ EXPECT_EQ(RTNAME(FPow4i)(Real<4>{2}, Int<4>{-1}), Real<4>{0.5});
+ EXPECT_EQ(RTNAME(FPow4i)(Real<4>{0.5}, Int<4>{-1}), Real<4>{2});
+ EXPECT_EQ(RTNAME(FPow4i)(Real<4>{-3}, Int<4>{3}), Real<4>{-27});
+ EXPECT_EQ(RTNAME(FPow4i)(Real<4>{-2}, Int<4>{-3}), Real<4>{-0.125});
+
+ EXPECT_EQ(RTNAME(FPow4k)(Real<4>{0}, Int<8>{0}), Real<4>{1});
+ EXPECT_EQ(RTNAME(FPow4k)(Real<4>{0.3}, Int<8>{0}), Real<4>{1});
+ EXPECT_EQ(RTNAME(FPow4k)(Real<4>{2}, Int<8>{-1}), Real<4>{0.5});
+ EXPECT_EQ(RTNAME(FPow4k)(Real<4>{0.5}, Int<8>{-1}), Real<4>{2});
+ EXPECT_EQ(RTNAME(FPow4k)(Real<4>{-3}, Int<8>{3}), Real<4>{-27});
+ EXPECT_EQ(RTNAME(FPow4k)(Real<4>{-2}, Int<8>{-3}), Real<4>{-0.125});
+
+ EXPECT_EQ(RTNAME(FPow8i)(Real<8>{0}, Int<4>{0}), Real<8>{1});
+ EXPECT_EQ(RTNAME(FPow8i)(Real<8>{0.3}, Int<4>{0}), Real<8>{1});
+ EXPECT_EQ(RTNAME(FPow8i)(Real<8>{2}, Int<4>{-1}), Real<8>{0.5});
+ EXPECT_EQ(RTNAME(FPow8i)(Real<8>{0.5}, Int<4>{-1}), Real<8>{2});
+ EXPECT_EQ(RTNAME(FPow8i)(Real<8>{-3}, Int<4>{3}), Real<8>{-27});
+ EXPECT_EQ(RTNAME(FPow8i)(Real<8>{-2}, Int<4>{-3}), Real<8>{-0.125});
+
+ EXPECT_EQ(RTNAME(FPow8k)(Real<8>{0}, Int<8>{0}), Real<8>{1});
+ EXPECT_EQ(RTNAME(FPow8k)(Real<8>{0.3}, Int<8>{0}), Real<8>{1});
+ EXPECT_EQ(RTNAME(FPow8k)(Real<8>{2}, Int<8>{-1}), Real<8>{0.5});
+ EXPECT_EQ(RTNAME(FPow8k)(Real<8>{0.5}, Int<8>{-1}), Real<8>{2});
+ EXPECT_EQ(RTNAME(FPow8k)(Real<8>{-3}, Int<8>{3}), Real<8>{-27});
+ EXPECT_EQ(RTNAME(FPow8k)(Real<8>{-2}, Int<8>{-3}), Real<8>{-0.125});
+
+#if LDBL_MANT_DIG == 64
+ EXPECT_EQ(RTNAME(FPow10i)(Real<10>{0}, Int<4>{0}), Real<10>{1});
+ EXPECT_EQ(RTNAME(FPow10i)(Real<10>{0.3}, Int<4>{0}), Real<10>{1});
+ EXPECT_EQ(RTNAME(FPow10i)(Real<10>{2}, Int<4>{-1}), Real<10>{0.5});
+ EXPECT_EQ(RTNAME(FPow10i)(Real<10>{0.5}, Int<4>{-1}), Real<10>{2});
+ EXPECT_EQ(RTNAME(FPow10i)(Real<10>{-3}, Int<4>{3}), Real<10>{-27});
+ EXPECT_EQ(RTNAME(FPow10i)(Real<10>{-2}, Int<4>{-3}), Real<10>{-0.125});
+
+ EXPECT_EQ(RTNAME(FPow10k)(Real<10>{0}, Int<8>{0}), Real<10>{1});
+ EXPECT_EQ(RTNAME(FPow10k)(Real<10>{0.3}, Int<8>{0}), Real<10>{1});
+ EXPECT_EQ(RTNAME(FPow10k)(Real<10>{2}, Int<8>{-1}), Real<10>{0.5});
+ EXPECT_EQ(RTNAME(FPow10k)(Real<10>{0.5}, Int<8>{-1}), Real<10>{2});
+ EXPECT_EQ(RTNAME(FPow10k)(Real<10>{-3}, Int<8>{3}), Real<10>{-27});
+ EXPECT_EQ(RTNAME(FPow10k)(Real<10>{-2}, Int<8>{-3}), Real<10>{-0.125});
+#endif
+#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
+ EXPECT_EQ(RTNAME(FPow16i)(Real<16>{0}, Int<4>{0}), Real<16>{1});
+ EXPECT_EQ(RTNAME(FPow16i)(Real<16>{0.3}, Int<4>{0}), Real<16>{1});
+ EXPECT_EQ(RTNAME(FPow16i)(Real<16>{2}, Int<4>{-1}), Real<16>{0.5});
+ EXPECT_EQ(RTNAME(FPow16i)(Real<16>{0.5}, Int<4>{-1}), Real<16>{2});
+ EXPECT_EQ(RTNAME(FPow16i)(Real<16>{-3}, Int<4>{3}), Real<16>{-27});
+ EXPECT_EQ(RTNAME(FPow16i)(Real<16>{-2}, Int<4>{-3}), Real<16>{-0.125});
+
+ EXPECT_EQ(RTNAME(FPow16k)(Real<16>{0}, Int<8>{0}), Real<16>{1});
+ EXPECT_EQ(RTNAME(FPow16k)(Real<16>{0.3}, Int<8>{0}), Real<16>{1});
+ EXPECT_EQ(RTNAME(FPow16k)(Real<16>{2}, Int<8>{-1}), Real<16>{0.5});
+ EXPECT_EQ(RTNAME(FPow16k)(Real<16>{0.5}, Int<8>{-1}), Real<16>{2});
+ EXPECT_EQ(RTNAME(FPow16k)(Real<16>{-3}, Int<8>{3}), Real<16>{-27});
+ EXPECT_EQ(RTNAME(FPow16k)(Real<16>{-2}, Int<8>{-3}), Real<16>{-0.125});
+#endif
+
+ // Test some extreme values.
+ if (sizeof(double) == sizeof(std::uint64_t)) {
+ // (0x3FF0000000000001 ** -2147483648) ~ 0x3FEFFFFF00000401
+ double base;
+ *reinterpret_cast<std::uint64_t *>(&base) = 4607182418800017409ULL;
+ double result;
+ *reinterpret_cast<std::uint64_t *>(&result) = 4607182414505051137ULL;
+ EXPECT_TRUE(std::abs(RTNAME(FPow8i)(Real<8>{base},
+ Int<4>{std::numeric_limits<Int<4>>::min()}) -
+ Real<8>{result}) < 0.00000000001);
+
+ // (0x3FF0000000000001 ** 4294967296ULL) ~ 0x3FF00001000007FF
+ *reinterpret_cast<std::uint64_t *>(&base) = 4607182418800017409ULL;
+ *reinterpret_cast<std::uint64_t *>(&result) = 4607182423094986751ULL;
+ EXPECT_TRUE(std::abs(RTNAME(FPow8k)(Real<8>{base}, Int<8>{4294967296ULL}) -
+ Real<8>{result}) < 0.00000000001);
+ }
+}
More information about the flang-commits
mailing list