Skip to content

Conversation

@bassiounix
Copy link
Contributor

@bassiounix bassiounix commented Oct 5, 2025

@bassiounix bassiounix added bazel "Peripheral" support tier build system: utils/bazel libc labels Oct 5, 2025 — with Graphite App
@bassiounix bassiounix requested a review from lntue October 5, 2025 03:49
@bassiounix bassiounix marked this pull request as ready for review October 5, 2025 03:49
@bassiounix bassiounix removed the request for review from aaronmondal October 5, 2025 03:49
@llvmbot
Copy link
Member

llvmbot commented Oct 5, 2025

@llvm/pr-subscribers-libc

Author: Muhammad Bassiouni (bassiounix)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/161993.diff

9 Files Affected:

  • (modified) libc/shared/math.h (+1)
  • (added) libc/shared/math/exp2f16.h (+29)
  • (modified) libc/src/__support/math/CMakeLists.txt (+14)
  • (added) libc/src/__support/math/exp2f16.h (+111)
  • (modified) libc/src/math/generic/CMakeLists.txt (+1-9)
  • (modified) libc/src/math/generic/exp2f16.cpp (+2-84)
  • (modified) libc/test/shared/CMakeLists.txt (+1)
  • (modified) libc/test/shared/shared_math_test.cpp (+1-1)
  • (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+17-1)
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 1262fa6f682d0..8bff70f1c5336 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -49,6 +49,7 @@
 #include "math/exp10m1f16.h"
 #include "math/exp2.h"
 #include "math/exp2f.h"
+#include "math/exp2f16.h"
 #include "math/expf.h"
 #include "math/expf16.h"
 #include "math/frexpf.h"
diff --git a/libc/shared/math/exp2f16.h b/libc/shared/math/exp2f16.h
new file mode 100644
index 0000000000000..f799511efb0d7
--- /dev/null
+++ b/libc/shared/math/exp2f16.h
@@ -0,0 +1,29 @@
+//===-- Shared exp2f16 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_EXP2F16_H
+#define LLVM_LIBC_SHARED_MATH_EXP2F16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+#include "shared/libc_common.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/math/exp2f16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::exp2f16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SHARED_MATH_EXP2F16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 203ebb4bf1760..185900efa7354 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -753,6 +753,20 @@ add_header_library(
     libc.src.errno.errno
 )
 
+add_header_library(
+  exp2f16
+  HDRS
+    exp2f16.h
+  DEPENDS
+    .expxf16_utils
+    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.rounding_mode
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   exp10
   HDRS
diff --git a/libc/src/__support/math/exp2f16.h b/libc/src/__support/math/exp2f16.h
new file mode 100644
index 0000000000000..599ba0f5411bd
--- /dev/null
+++ b/libc/src/__support/math/exp2f16.h
@@ -0,0 +1,111 @@
+//===-- Implementation header for exp2f16 -----------------------*- 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_EXP2F16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP2F16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "expxf16_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.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 {
+
+namespace math {
+
+LIBC_INLINE static constexpr float16 exp2f16(float16 x) {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+  constexpr fputil::ExceptValues<float16, 3> EXP2F16_EXCEPTS = {{
+      // (input, RZ output, RU offset, RD offset, RN offset)
+      // x = 0x1.714p-11, exp2f16(x) = 0x1p+0 (RZ)
+      {0x11c5U, 0x3c00U, 1U, 0U, 1U},
+      // x = -0x1.558p-4, exp2f16(x) = 0x1.e34p-1 (RZ)
+      {0xad56U, 0x3b8dU, 1U, 0U, 0U},
+      // x = -0x1.d5cp-4, exp2f16(x) = 0x1.d8cp-1 (RZ)
+      {0xaf57U, 0x3b63U, 1U, 0U, 0U},
+  }};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+  using namespace math::expxf16_internal;
+  using FPBits = fputil::FPBits<float16>;
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+  uint16_t x_abs = x_u & 0x7fffU;
+
+  // When |x| >= 16, or x is NaN.
+  if (LIBC_UNLIKELY(x_abs >= 0x4c00U)) {
+    // exp2(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 >= 16.
+    if (x_bits.is_pos()) {
+      // exp2(+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 <= -25.
+    if (x_u >= 0xce40U) {
+      // exp2(-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);
+
+      if (fputil::fenv_is_round_up())
+        return FPBits::min_subnormal().get_val();
+      return FPBits::zero().get_val();
+    }
+  }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+  if (auto r = EXP2F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+    return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+  // exp2(x) = exp2(hi + mid) * exp2(lo)
+  auto [exp2_hi_mid, exp2_lo] = exp2_range_reduction(x);
+  return fputil::cast<float16>(exp2_hi_mid * exp2_lo);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP2F16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 5738fe86f6c7b..8e969de5a8031 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1468,15 +1468,7 @@ add_entrypoint_object(
   HDRS
     ../exp2f16.h
   DEPENDS
-    libc.hdr.errno_macros
-    libc.hdr.fenv_macros
-    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.rounding_mode
-    libc.src.__support.macros.optimization
-    libc.src.__support.math.expxf16_utils
+    libc.src.__support.math.exp2f16
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/exp2f16.cpp b/libc/src/math/generic/exp2f16.cpp
index 5db0c3a9de08d..80799d49c20c1 100644
--- a/libc/src/math/generic/exp2f16.cpp
+++ b/libc/src/math/generic/exp2f16.cpp
@@ -7,92 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/exp2f16.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/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"
-#include "src/__support/math/expxf16_utils.h"
+#include "src/__support/math/exp2f16.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr fputil::ExceptValues<float16, 3> EXP2F16_EXCEPTS = {{
-    // (input, RZ output, RU offset, RD offset, RN offset)
-    // x = 0x1.714p-11, exp2f16(x) = 0x1p+0 (RZ)
-    {0x11c5U, 0x3c00U, 1U, 0U, 1U},
-    // x = -0x1.558p-4, exp2f16(x) = 0x1.e34p-1 (RZ)
-    {0xad56U, 0x3b8dU, 1U, 0U, 0U},
-    // x = -0x1.d5cp-4, exp2f16(x) = 0x1.d8cp-1 (RZ)
-    {0xaf57U, 0x3b63U, 1U, 0U, 0U},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) {
-  using namespace math::expxf16_internal;
-  using FPBits = fputil::FPBits<float16>;
-  FPBits x_bits(x);
-
-  uint16_t x_u = x_bits.uintval();
-  uint16_t x_abs = x_u & 0x7fffU;
-
-  // When |x| >= 16, or x is NaN.
-  if (LIBC_UNLIKELY(x_abs >= 0x4c00U)) {
-    // exp2(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 >= 16.
-    if (x_bits.is_pos()) {
-      // exp2(+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 <= -25.
-    if (x_u >= 0xce40U) {
-      // exp2(-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);
-
-      if (fputil::fenv_is_round_up())
-        return FPBits::min_subnormal().get_val();
-      return FPBits::zero().get_val();
-    }
-  }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-  if (auto r = EXP2F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
-    return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-  // exp2(x) = exp2(hi + mid) * exp2(lo)
-  auto [exp2_hi_mid, exp2_lo] = exp2_range_reduction(x);
-  return fputil::cast<float16>(exp2_hi_mid * exp2_lo);
-}
+LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) { return math::exp2f16(x); }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index dbc3889c76471..685b954c1f306 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -42,6 +42,7 @@ add_fp_unittest(
     libc.src.__support.math.exp
     libc.src.__support.math.exp2
     libc.src.__support.math.exp2f
+    libc.src.__support.math.exp2f16
     libc.src.__support.math.exp10
     libc.src.__support.math.exp10f
     libc.src.__support.math.exp10f16
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index d118d96da69dd..b114eefccbf77 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -28,7 +28,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::cospif16(0.0f16));
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp10f16(0.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::exp10m1f16(0.0f16));
-
+  EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp2f16(0.0f16));
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::expf16(0.0f16));
 
   ASSERT_FP_EQ(float16(8 << 5), LIBC_NAMESPACE::shared::ldexpf16(8.0f16, 5));
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 00db514beaf34..d47e5feb7eff8 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2895,6 +2895,22 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_exp2f16",
+    hdrs = ["src/__support/math/exp2f16.h"],
+    deps = [
+        ":__support_fputil_except_value_utils",
+        ":__support_fputil_fma",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_nearest_integer",
+        ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
+        ":__support_macros_optimization",
+        ":__support_math_common_constants",
+        ":__support_math_expxf16_utils",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_exp10",
     hdrs = ["src/__support/math/exp10.h"],
@@ -3683,7 +3699,7 @@ libc_math_function(
 libc_math_function(
     name = "exp2f16",
     additional_deps = [
-        ":__support_math_expxf16_utils",
+        ":__support_math_exp2f16",
     ],
 )
 

@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f_implementation_to_header-only_in_src___support_math_folder branch 6 times, most recently from a0d0c67 to fbb9605 Compare October 6, 2025 17:42
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f16_implementation_to_header-only_in_src___support_math_folder branch from 8bf9344 to ce1bed7 Compare October 6, 2025 17:42
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f_implementation_to_header-only_in_src___support_math_folder branch from fbb9605 to 93383ba Compare October 6, 2025 17:42
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f_implementation_to_header-only_in_src___support_math_folder branch 2 times, most recently from e9afac5 to a6a49dd Compare October 6, 2025 17:59
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f16_implementation_to_header-only_in_src___support_math_folder branch from ce1bed7 to 7f96a60 Compare October 6, 2025 18:03
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f_implementation_to_header-only_in_src___support_math_folder branch from a6a49dd to 4c05856 Compare October 6, 2025 18:03
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f_implementation_to_header-only_in_src___support_math_folder branch 2 times, most recently from 49a99a9 to 20f4f60 Compare October 6, 2025 18:16
Base automatically changed from users/bassiounix/spr/10-05-_libc_math_refactor_exp2f_implementation_to_header-only_in_src___support_math_folder to main October 6, 2025 18:23
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f16_implementation_to_header-only_in_src___support_math_folder branch from 7f96a60 to f948445 Compare October 6, 2025 18:25
@bassiounix bassiounix force-pushed the users/bassiounix/spr/10-05-_libc_math_refactor_exp2f16_implementation_to_header-only_in_src___support_math_folder branch from f948445 to d4c0678 Compare October 6, 2025 18:28
Copy link
Contributor Author

bassiounix commented Oct 11, 2025

Merge activity

  • Oct 11, 8:25 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Oct 11, 8:27 PM UTC: @bassiounix merged this pull request with Graphite.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bazel "Peripheral" support tier build system: utils/bazel libc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants