[libc-commits] [libc] [libc][math][c23] Finish optimizing fmul (PR #107517)
Job Henandez Lara via libc-commits
libc-commits at lists.llvm.org
Mon Sep 9 19:30:53 PDT 2024
https://github.com/Jobhdez updated https://github.com/llvm/llvm-project/pull/107517
>From 6bca4f7d3addd4f03b44f13c57e1ce9a582b9c2b Mon Sep 17 00:00:00 2001
From: Job Hernandez <hj93 at protonmail.com>
Date: Thu, 5 Sep 2024 21:26:49 -0700
Subject: [PATCH 1/7] add draft, one more test to go
---
libc/src/math/generic/CMakeLists.txt | 4 +++-
libc/src/math/generic/fmul.cpp | 18 ++++++++++++++++--
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 350072f4b9649d..5a1ee3b8b83c77 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2958,7 +2958,9 @@ add_entrypoint_object(
HDRS
../fmul.h
DEPENDS
- libc.src.__support.FPUtil.generic.mul
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.double_double
COMPILE_OPTIONS
-O3
)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 64c27d6e2f9564..fe8f5b0bb7c45b 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -5,16 +5,30 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
#include "src/math/fmul.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/__support/FPUtil/double_double.h"
namespace LIBC_NAMESPACE_DECL {
-
+ /*
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
return fputil::generic::mul<float>(x, y);
}
+ */
+LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
+ fputil::DoubleDouble prod = fputil::exact_mult(x, y);
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() || fputil::FPBits<double>(prod.hi).is_zero()))
+ return static_cast<float>(prod.hi);
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() || fputil::FPBits<double>(prod.hi).is_zero())) {
+ fputil::set_errno_if_required(EDOM);
+ fputil::raise_except_if_required(FE_INVALID);
+ return fputil::FPBits<double>::quiet_nan().get_val();
+ }
+ return static_cast<float>(prod.hi + prod.lo);
+}
} // namespace LIBC_NAMESPACE_DECL
>From db2fe1ef877461b168dcede8b4d3c44f95116139 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Fri, 6 Sep 2024 16:33:54 -0700
Subject: [PATCH 2/7] add darwin entrypoints
---
libc/config/darwin/arm/entrypoints.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index a012504daa5c54..e764eab64d2418 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -171,6 +171,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fminl
libc.src.math.fmod
libc.src.math.fmodf
+ libc.src.math.fmul
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
>From c4edba3f76f15e704b95a5c3e188f16efeb35808 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Fri, 6 Sep 2024 16:35:42 -0700
Subject: [PATCH 3/7] format code
---
libc/src/math/generic/fmul.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index fe8f5b0bb7c45b..c2536645b593bd 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -5,25 +5,27 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+#include "src/math/fmul.h"
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
-#include "src/math/fmul.h"
+#include "src/__support/FPUtil/double_double.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "src/__support/FPUtil/double_double.h"
namespace LIBC_NAMESPACE_DECL {
- /*
+/*
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
- return fputil::generic::mul<float>(x, y);
+return fputil::generic::mul<float>(x, y);
}
- */
+*/
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
- if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() || fputil::FPBits<double>(prod.hi).is_zero()))
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() ||
+ fputil::FPBits<double>(prod.hi).is_zero()))
return static_cast<float>(prod.hi);
- if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() || fputil::FPBits<double>(prod.hi).is_zero())) {
+ if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() ||
+ fputil::FPBits<double>(prod.hi).is_zero())) {
fputil::set_errno_if_required(EDOM);
fputil::raise_except_if_required(FE_INVALID);
return fputil::FPBits<double>::quiet_nan().get_val();
>From 9533e593f54d247bb068e3172dfdfab23280faf1 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Sat, 7 Sep 2024 20:14:50 -0700
Subject: [PATCH 4/7] add new case
---
libc/config/darwin/arm/entrypoints.txt | 2 ++
libc/src/math/generic/fmul.cpp | 17 +++++++++++++++--
libc/test/src/math/smoke/fmul_test.cpp | 17 +++++++++++++++++
3 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index e764eab64d2418..2d5dbeff485747 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -81,6 +81,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdlib.llabs
libc.src.stdlib.lldiv
libc.src.stdlib.qsort
+ libc.src.stdlib.rand
+ libc.src.stdlib.srand
libc.src.stdlib.strtod
libc.src.stdlib.strtof
libc.src.stdlib.strtol
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index c2536645b593bd..28d96448cbb2df 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -21,8 +21,9 @@ return fputil::generic::mul<float>(x, y);
*/
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
- if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf_or_nan() ||
- fputil::FPBits<double>(prod.hi).is_zero()))
+ fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
+
+ if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero()))
return static_cast<float>(prod.hi);
if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() ||
fputil::FPBits<double>(prod.hi).is_zero())) {
@@ -30,7 +31,19 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::raise_except_if_required(FE_INVALID);
return fputil::FPBits<double>::quiet_nan().get_val();
}
+ if (prod.lo == 0.0)
+ return static_cast<float>(prod.hi);
+
+ if (lo_bits.sign() != hi_bits.sign()) {
+ // Check if sticky bit of hi are all 0
+ constexpr uint64_t STICKY_MASK = 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
+ uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
+ uint64_t result_bits = (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
+ double result = fputil::FPBits<double>(result_bits).get_val();
+ return static_cast<float>(result);
+}
return static_cast<float>(prod.hi + prod.lo);
+
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
index 3f6df66456bac5..e4165b23da1389 100644
--- a/libc/test/src/math/smoke/fmul_test.cpp
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -11,3 +11,20 @@
#include "src/math/fmul.h"
LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
+
+TEST_F(LlvmLibcMulTest, SpecialInputs) {
+ constexpr double INPUTS[][2] = {
+ {0x1.0100010002p8, 0x1.fffcp14},
+ };
+
+ constexpr float RESULTS[] = {
+ 0x1.00fdfep+23f,
+ };
+
+ constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
+
+ for (size_t i = 0; i < N; ++i) {
+ float result = LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]);
+ EXPECT_FP_EQ(RESULTS[i], result);
+ }
+}
>From 908eb18ee1ca94803f8e5980bc0375e94a2821c0 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Sat, 7 Sep 2024 20:15:16 -0700
Subject: [PATCH 5/7] format code
---
libc/src/math/generic/fmul.cpp | 15 ++++++++-------
libc/test/src/math/smoke/fmul_test.cpp | 4 ++--
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/libc/src/math/generic/fmul.cpp b/libc/src/math/generic/fmul.cpp
index 28d96448cbb2df..a9de90edd2a7ab 100644
--- a/libc/src/math/generic/fmul.cpp
+++ b/libc/src/math/generic/fmul.cpp
@@ -22,7 +22,7 @@ return fputil::generic::mul<float>(x, y);
LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
fputil::DoubleDouble prod = fputil::exact_mult(x, y);
fputil::FPBits<double> hi_bits(prod.hi), lo_bits(prod.lo);
-
+
if (LIBC_UNLIKELY(hi_bits.is_inf_or_nan() || hi_bits.is_zero()))
return static_cast<float>(prod.hi);
if (LIBC_UNLIKELY(fputil::FPBits<double>(prod.hi).is_inf() ||
@@ -33,17 +33,18 @@ LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
}
if (prod.lo == 0.0)
return static_cast<float>(prod.hi);
-
+
if (lo_bits.sign() != hi_bits.sign()) {
- // Check if sticky bit of hi are all 0
- constexpr uint64_t STICKY_MASK = 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
+ // Check if sticky bit of hi are all 0
+ constexpr uint64_t STICKY_MASK =
+ 0xFFF'FFFF; // Lower (52 - 23 - 1 = 28 bits)
uint64_t sticky_bits = (hi_bits.uintval() & STICKY_MASK);
- uint64_t result_bits = (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
+ uint64_t result_bits =
+ (sticky_bits == 0) ? (hi_bits.uintval() - 1) : hi_bits.uintval();
double result = fputil::FPBits<double>(result_bits).get_val();
return static_cast<float>(result);
-}
+ }
return static_cast<float>(prod.hi + prod.lo);
-
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/smoke/fmul_test.cpp b/libc/test/src/math/smoke/fmul_test.cpp
index e4165b23da1389..48a5afd247bcfb 100644
--- a/libc/test/src/math/smoke/fmul_test.cpp
+++ b/libc/test/src/math/smoke/fmul_test.cpp
@@ -14,11 +14,11 @@ LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
TEST_F(LlvmLibcMulTest, SpecialInputs) {
constexpr double INPUTS[][2] = {
- {0x1.0100010002p8, 0x1.fffcp14},
+ {0x1.0100010002p8, 0x1.fffcp14},
};
constexpr float RESULTS[] = {
- 0x1.00fdfep+23f,
+ 0x1.00fdfep+23f,
};
constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
>From 7f9a4bf35c0a252686ca09880da24bd613bc9c46 Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Mon, 9 Sep 2024 19:30:08 -0700
Subject: [PATCH 6/7] run mpfr tests
---
libc/test/src/math/fmul_test.cpp | 27 +++++++++++++++++++
.../math/performance_testing/CMakeLists.txt | 2 ++
.../math/performance_testing/fmul_perf.cpp | 4 ++-
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/libc/test/src/math/fmul_test.cpp b/libc/test/src/math/fmul_test.cpp
index 3f6df66456bac5..c134c3fa299d85 100644
--- a/libc/test/src/math/fmul_test.cpp
+++ b/libc/test/src/math/fmul_test.cpp
@@ -10,4 +10,31 @@
#include "src/math/fmul.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
+
+TEST_F(LlvmLibcMulTest, SpecialInputs) {
+ namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+ double INPUTS[][2] = {
+ {0x1.0100010002p8, 0x1.fffcp14},
+ };
+
+ constexpr float RESULTS[] = {
+ 0x1.00fdfep+23f,
+ };
+
+
+ constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
+
+ for (size_t i = 0; i < N; ++i) {
+ double a = INPUTS[i][0];
+
+ for (int j = 0; j < 180; ++j) {
+ a *= 0.5;
+ mpfr::BinaryInput<double> input{INPUTS[i][0], INPUTS[i][1]};
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]), 0.5);
+ }
+ }
+}
diff --git a/libc/test/src/math/performance_testing/CMakeLists.txt b/libc/test/src/math/performance_testing/CMakeLists.txt
index ed1b03f3493c7d..60c074a248f72a 100644
--- a/libc/test/src/math/performance_testing/CMakeLists.txt
+++ b/libc/test/src/math/performance_testing/CMakeLists.txt
@@ -484,6 +484,8 @@ add_perf_binary(
DEPENDS
.binary_op_single_output_diff
libc.src.math.fmul
+ libc.src.__support.FPUtil.generic.mul
+ libc.src.__support.FPUtil.fp_bits
COMPILE_OPTIONS
-fno-builtin
)
diff --git a/libc/test/src/math/performance_testing/fmul_perf.cpp b/libc/test/src/math/performance_testing/fmul_perf.cpp
index a215405eb6aa5d..d6156f1519c507 100644
--- a/libc/test/src/math/performance_testing/fmul_perf.cpp
+++ b/libc/test/src/math/performance_testing/fmul_perf.cpp
@@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//
#include "BinaryOpSingleOutputPerf.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/generic/mul.h"
#include "src/math/fmul.h"
static constexpr size_t DOUBLE_ROUNDS = 40;
float fmul_placeholder_binary(double x, double y) {
- return static_cast<float>(x * y);
+ return LIBC_NAMESPACE::fputil::generic::mul<float>(x, y);
}
int main() {
>From 78a06b41edc80e87e8b400373f8c859b2cf351ee Mon Sep 17 00:00:00 2001
From: Job Hernandez Lara <hj93 at protonmail.com>
Date: Mon, 9 Sep 2024 19:30:34 -0700
Subject: [PATCH 7/7] format code
---
libc/test/src/math/fmul_test.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libc/test/src/math/fmul_test.cpp b/libc/test/src/math/fmul_test.cpp
index c134c3fa299d85..d1caca0c38de20 100644
--- a/libc/test/src/math/fmul_test.cpp
+++ b/libc/test/src/math/fmul_test.cpp
@@ -25,7 +25,6 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
0x1.00fdfep+23f,
};
-
constexpr size_t N = sizeof(RESULTS) / sizeof(RESULTS[0]);
for (size_t i = 0; i < N; ++i) {
@@ -34,7 +33,9 @@ TEST_F(LlvmLibcMulTest, SpecialInputs) {
for (int j = 0; j < 180; ++j) {
a *= 0.5;
mpfr::BinaryInput<double> input{INPUTS[i][0], INPUTS[i][1]};
- ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]), 0.5);
+ ASSERT_MPFR_MATCH_ALL_ROUNDING(
+ mpfr::Operation::Mul, input,
+ LIBC_NAMESPACE::fmul(INPUTS[i][0], INPUTS[i][1]), 0.5);
}
}
}
More information about the libc-commits
mailing list