-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[libc][math] Refactor expf16 implementation to header-only in src/__support/math folder. #147428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…upport/math folder.
@llvm/pr-subscribers-libc Author: Muhammad Bassiouni (bassiounix) ChangesPart of [https://github.com//issues/147386](#147386) in preparation for: https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450 @lntue @michaelrj-google @vonosmas @overmighty @jhuber6 Full diff: https://github.com/llvm/llvm-project/pull/147428.diff 8 Files Affected:
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 4ddc29c7ae834..9db53b69041d0 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -12,5 +12,6 @@
#include "libc_common.h"
#include "math/expf.h"
+#include "math/expf16.h"
#endif // LLVM_LIBC_SHARED_MATH_H
diff --git a/libc/shared/math/expf16.h b/libc/shared/math/expf16.h
new file mode 100644
index 0000000000000..4e6ab78b26467
--- /dev/null
+++ b/libc/shared/math/expf16.h
@@ -0,0 +1,23 @@
+//===-- Shared expf16 function ----------------------------------*- 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 LLVM_LIBC_SHARED_MATH_EXPF16_H
+#define LLVM_LIBC_SHARED_MATH_EXPF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/expf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::expf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_EXPF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 66c1d19a1cab0..6d4d548f2e48f 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -22,3 +22,31 @@ add_header_library(
libc.src.__support.macros.config
libc.src.__support.macros.optimization
)
+
+add_header_library(
+ exp_float16_constants
+ HDRS
+ exp_float16_constants.h
+ DEPENDS
+ libc.src.__support.FPUtil.except_value_utils
+)
+
+add_header_library(
+ expf16
+ HDRS
+ expf16.h
+ DEPENDS
+ .expxf16
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
+ libc.src.__support.CPP.array
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.except_value_utils
+ libc.src.__support.FPUtil.fenv_impl
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.nearest_integer
+ libc.src.__support.FPUtil.polyeval
+ libc.src.__support.FPUtil.rounding_mode
+ libc.src.__support.macros.optimization
+)
diff --git a/libc/src/__support/math/exp_float16_constants.h b/libc/src/__support/math/exp_float16_constants.h
new file mode 100644
index 0000000000000..9c3aa05e9551c
--- /dev/null
+++ b/libc/src/__support/math/exp_float16_constants.h
@@ -0,0 +1,38 @@
+//===-- High and Low Excepts for expf16 functions ---------------*- 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 LLVM_LIBC_SRC___SUPPORT_MATH_EXP_FLOAT16_CONSTANTS_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP_FLOAT16_CONSTANTS_H
+
+#include "src/__support/FPUtil/except_value_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+static constexpr fputil::ExceptValues<float16, 2> EXPF16_EXCEPTS_LO = {{
+ // (input, RZ output, RU offset, RD offset, RN offset)
+ // x = 0x1.de4p-8, expf16(x) = 0x1.01cp+0 (RZ)
+ {0x1f79U, 0x3c07U, 1U, 0U, 0U},
+ // x = 0x1.73cp-6, expf16(x) = 0x1.05cp+0 (RZ)
+ {0x25cfU, 0x3c17U, 1U, 0U, 0U},
+}};
+
+static constexpr fputil::ExceptValues<float16, 3> EXPF16_EXCEPTS_HI = {{
+ // (input, RZ output, RU offset, RD offset, RN offset)
+ // x = 0x1.c34p+0, expf16(x) = 0x1.74cp+2 (RZ)
+ {0x3f0dU, 0x45d3U, 1U, 0U, 1U},
+ // x = -0x1.488p-5, expf16(x) = 0x1.ebcp-1 (RZ)
+ {0xa922U, 0x3bafU, 1U, 0U, 0U},
+ // x = -0x1.55p-5, expf16(x) = 0x1.ebp-1 (RZ)
+ {0xa954U, 0x3bacU, 1U, 0U, 0U},
+}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP_FLOAT16_CONSTANTS_H
diff --git a/libc/src/__support/math/expf16.h b/libc/src/__support/math/expf16.h
new file mode 100644
index 0000000000000..29a8e44d373f5
--- /dev/null
+++ b/libc/src/__support/math/expf16.h
@@ -0,0 +1,116 @@
+//===-- Implementation header for expf16 ------------------------*- 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 LLVM_LIBC_SRC___SUPPORT_MATH_EXPF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_EXPF16_H
+
+#include "exp_float16_constants.h"
+
+#include "hdr/errno_macros.h"
+#include "src/math/generic/expxf16.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+static constexpr float16 expf16(float16 x) {
+ using FPBits = fputil::FPBits<float16>;
+ FPBits x_bits(x);
+
+ uint16_t x_u = x_bits.uintval();
+ uint16_t x_abs = x_u & 0x7fffU;
+
+ // When 0 < |x| <= 2^(-5), or |x| >= 12, or x is NaN.
+ if (LIBC_UNLIKELY(x_abs <= 0x2800U || x_abs >= 0x4a00U)) {
+ // exp(NaN) = NaN
+ if (x_bits.is_nan()) {
+ if (x_bits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+
+ return x;
+ }
+
+ // When x >= 12.
+ if (x_bits.is_pos() && x_abs >= 0x4a00U) {
+ // exp(+inf) = +inf
+ if (x_bits.is_inf())
+ return FPBits::inf().get_val();
+
+ switch (fputil::quick_get_round()) {
+ case FE_TONEAREST:
+ case FE_UPWARD:
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_OVERFLOW);
+ return FPBits::inf().get_val();
+ default:
+ return FPBits::max_normal().get_val();
+ }
+ }
+
+ // When x <= -18.
+ if (x_u >= 0xcc80U) {
+ // exp(-inf) = +0
+ if (x_bits.is_inf())
+ return FPBits::zero().get_val();
+
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
+
+ switch (fputil::quick_get_round()) {
+ case FE_UPWARD:
+ return FPBits::min_subnormal().get_val();
+ default:
+ return FPBits::zero().get_val();
+ }
+ }
+
+ // When 0 < |x| <= 2^(-5).
+ if (x_abs <= 0x2800U && !x_bits.is_zero()) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ if (auto r = EXPF16_EXCEPTS_LO.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ float xf = x;
+ // Degree-3 minimax polynomial generated by Sollya with the following
+ // commands:
+ // > display = hexadecimal;
+ // > P = fpminimax(expm1(x)/x, 2, [|SG...|], [-2^-5, 2^-5]);
+ // > 1 + x * P;
+ return fputil::cast<float16>(
+ fputil::polyeval(xf, 0x1p+0f, 0x1p+0f, 0x1.0004p-1f, 0x1.555778p-3f));
+ }
+ }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ if (auto r = EXPF16_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+ return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+ // exp(x) = exp(hi + mid) * exp(lo)
+ auto [exp_hi_mid, exp_lo] = exp_range_reduction(x);
+ return fputil::cast<float16>(exp_hi_mid * exp_lo);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXPF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index fd1e6c0d648aa..8d15c2879a8bf 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1332,19 +1332,7 @@ add_entrypoint_object(
HDRS
../expf16.h
DEPENDS
- .expxf16
- libc.hdr.errno_macros
- libc.hdr.fenv_macros
- libc.src.__support.CPP.array
- libc.src.__support.FPUtil.cast
- libc.src.__support.FPUtil.except_value_utils
- libc.src.__support.FPUtil.fenv_impl
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.multiply_add
- libc.src.__support.FPUtil.nearest_integer
- libc.src.__support.FPUtil.polyeval
- libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.macros.optimization
+ libc.src.__support.math.expf
)
add_entrypoint_object(
diff --git a/libc/src/math/generic/expf16.cpp b/libc/src/math/generic/expf16.cpp
index 1af9b3ec9ad6e..ad213e237f021 100644
--- a/libc/src/math/generic/expf16.cpp
+++ b/libc/src/math/generic/expf16.cpp
@@ -7,120 +7,11 @@
//===----------------------------------------------------------------------===//
#include "src/math/expf16.h"
-#include "expxf16.h"
-#include "hdr/errno_macros.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
-namespace LIBC_NAMESPACE_DECL {
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr fputil::ExceptValues<float16, 2> EXPF16_EXCEPTS_LO = {{
- // (input, RZ output, RU offset, RD offset, RN offset)
- // x = 0x1.de4p-8, expf16(x) = 0x1.01cp+0 (RZ)
- {0x1f79U, 0x3c07U, 1U, 0U, 0U},
- // x = 0x1.73cp-6, expf16(x) = 0x1.05cp+0 (RZ)
- {0x25cfU, 0x3c17U, 1U, 0U, 0U},
-}};
-
-static constexpr fputil::ExceptValues<float16, 3> EXPF16_EXCEPTS_HI = {{
- // (input, RZ output, RU offset, RD offset, RN offset)
- // x = 0x1.c34p+0, expf16(x) = 0x1.74cp+2 (RZ)
- {0x3f0dU, 0x45d3U, 1U, 0U, 1U},
- // x = -0x1.488p-5, expf16(x) = 0x1.ebcp-1 (RZ)
- {0xa922U, 0x3bafU, 1U, 0U, 0U},
- // x = -0x1.55p-5, expf16(x) = 0x1.ebp-1 (RZ)
- {0xa954U, 0x3bacU, 1U, 0U, 0U},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) {
- using FPBits = fputil::FPBits<float16>;
- FPBits x_bits(x);
-
- uint16_t x_u = x_bits.uintval();
- uint16_t x_abs = x_u & 0x7fffU;
-
- // When 0 < |x| <= 2^(-5), or |x| >= 12, or x is NaN.
- if (LIBC_UNLIKELY(x_abs <= 0x2800U || x_abs >= 0x4a00U)) {
- // exp(NaN) = NaN
- if (x_bits.is_nan()) {
- if (x_bits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
-
- return x;
- }
-
- // When x >= 12.
- if (x_bits.is_pos() && x_abs >= 0x4a00U) {
- // exp(+inf) = +inf
- if (x_bits.is_inf())
- return FPBits::inf().get_val();
+#include "src/__support/math/expf16.h"
- switch (fputil::quick_get_round()) {
- case FE_TONEAREST:
- case FE_UPWARD:
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_OVERFLOW);
- return FPBits::inf().get_val();
- default:
- return FPBits::max_normal().get_val();
- }
- }
-
- // When x <= -18.
- if (x_u >= 0xcc80U) {
- // exp(-inf) = +0
- if (x_bits.is_inf())
- return FPBits::zero().get_val();
-
- fputil::set_errno_if_required(ERANGE);
- fputil::raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
-
- switch (fputil::quick_get_round()) {
- case FE_UPWARD:
- return FPBits::min_subnormal().get_val();
- default:
- return FPBits::zero().get_val();
- }
- }
-
- // When 0 < |x| <= 2^(-5).
- if (x_abs <= 0x2800U && !x_bits.is_zero()) {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- if (auto r = EXPF16_EXCEPTS_LO.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
- float xf = x;
- // Degree-3 minimax polynomial generated by Sollya with the following
- // commands:
- // > display = hexadecimal;
- // > P = fpminimax(expm1(x)/x, 2, [|SG...|], [-2^-5, 2^-5]);
- // > 1 + x * P;
- return fputil::cast<float16>(
- fputil::polyeval(xf, 0x1p+0f, 0x1p+0f, 0x1.0004p-1f, 0x1.555778p-3f));
- }
- }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
- if (auto r = EXPF16_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
- return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+namespace LIBC_NAMESPACE_DECL {
- // exp(x) = exp(hi + mid) * exp(lo)
- auto [exp_hi_mid, exp_lo] = exp_range_reduction(x);
- return fputil::cast<float16>(exp_hi_mid * exp_lo);
-}
+LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) { return math::expf16(x); }
} // namespace LIBC_NAMESPACE_DECL
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 2484a2f1e2bd7..efba1eb640eb8 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2096,6 +2096,34 @@ libc_support_library(
],
)
+libc_support_library(
+ name = "__support_math_exp_float16_constants",
+ hdrs = ["src/__support/math/exp_float16_constants.h"],
+ deps = [
+ ":__support_FPUtil_except_value_utils"
+ ],
+)
+
+libc_support_library(
+ name = "__support_math_expf16",
+ hdrs = ["src/__support/math/expf16.h"],
+ deps = [
+ ":__support_common",
+ ":hdr_errno_macros",
+ ":hdr_fenv_macros",
+ ":__support_cpp_array",
+ ":__support_fputil_cast",
+ ":__support_fputil_except_value_utils",
+ ":__support_fputil_fenv_impl",
+ ":__support_fputil_fp_bits",
+ ":__support_fputil_multiply_add",
+ ":__support_fputil_nearest_integer",
+ ":__support_fputil_polyeval",
+ ":__support_fputil_rounding_mode",
+ ":__support_macros_optimization",
+ ],
+)
+
############################### complex targets ################################
libc_function(
@@ -2701,6 +2729,7 @@ libc_math_function(
libc_math_function(
name = "expf16",
additional_deps = [
+ ":__support_math_expf16",
":expxf16",
],
)
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Part of #147386
in preparation for: https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450
@lntue @michaelrj-google @vonosmas @overmighty @jhuber6