[libc-commits] [libc] [libc] Refactor llogbl to be header-only and constexpr (PR #175376)

Mathew Joseph via libc-commits libc-commits at lists.llvm.org
Sat Jan 10 11:15:15 PST 2026


https://github.com/mathew1046 updated https://github.com/llvm/llvm-project/pull/175376

>From 7019db02d7eb906bf7b02a42b0d420cc3f2bcb9a Mon Sep 17 00:00:00 2001
From: Mathew Joseph <mathewjosephparakka at gmail.com>
Date: Sun, 11 Jan 2026 00:22:20 +0530
Subject: [PATCH 1/2] [libc] Refactor llogbl to be header-only and constexpr

Refactor the llogbl (log base 2 of absolute value for long double) function
to be header-only and marked constexpr, enabling compile-time evaluation and
inlining opportunities while maintaining binary compatibility.

Changes:
1. Move the implementation into libc/src/math/llogbl.h as an inline constexpr
   function that delegates to the existing fputil::intlogb<long> template
   (which is already constexpr-compatible).

2. Simplify libc/src/math/generic/llogbl.cpp to be a thin wrapper that exports
   the public C symbol via LLVM_LIBC_FUNCTION, ensuring binary compatibility
   with shipped libc libraries.

3. Add constexpr compile-time tests (static_assert) in the test file to verify
   that llogbl can be evaluated at compile time for normal numbers with various
   exponents (powers of 2 from 2^-1 to 2^10).

4. The underlying fputil::intlogb<long> already handles constexpr evaluation
   correctly for all cases (zero, NaN, infinity, subnormals) by using
   is_constant_evaluated() to skip errno/FE flag operations at compile time.

Benefits:
- Callers can now use constexpr long result = llogbl(2.0L); at compile time
- Compiler can inline the function for better optimization
- No ABI changes; binary compatibility is maintained
- No platform-specific issues; inherits robust handling from fputil

Fixes: https://github.com/llvm/llvm-project/issues/175361
Signed-off-by: Mathew Joseph <mathewjosephparakka at gmail.com>
---
 libc/src/math/generic/llogbl.cpp         |  9 +++----
 libc/src/math/llogbl.h                   |  7 ++++-
 libc/test/src/math/smoke/llogbl_test.cpp | 34 ++++++++++++++++++++++++
 3 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/libc/src/math/generic/llogbl.cpp b/libc/src/math/generic/llogbl.cpp
index 7ee3ac55653b6..73a104de57357 100644
--- a/libc/src/math/generic/llogbl.cpp
+++ b/libc/src/math/generic/llogbl.cpp
@@ -7,14 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/llogbl.h"
-#include "src/__support/FPUtil/ManipulationFunctions.h"
 #include "src/__support/common.h"
-#include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-LLVM_LIBC_FUNCTION(long, llogbl, (long double x)) {
-  return fputil::intlogb<long>(x);
-}
+// Export the public C symbol by wrapping the inline constexpr definition.
+// This maintains binary compatibility with the shipped libc while allowing
+// callers to evaluate llogbl at compile time or have it inlined.
+LLVM_LIBC_FUNCTION(long, llogbl, (long double x)) { return llogbl(x); }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/llogbl.h b/libc/src/math/llogbl.h
index bf502a1c0bc3b..4a45eb6f1d895 100644
--- a/libc/src/math/llogbl.h
+++ b/libc/src/math/llogbl.h
@@ -9,12 +9,17 @@
 #ifndef LLVM_LIBC_SRC_MATH_LLOGBL_H
 #define LLVM_LIBC_SRC_MATH_LLOGBL_H
 
+#include "src/__support/FPUtil/ManipulationFunctions.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/types.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-long llogbl(long double x);
+// Inline constexpr implementation: extract the unbiased exponent of a long double
+// by delegating to the existing constexpr template fputil::intlogb<long>.
+LIBC_INLINE constexpr long llogbl(long double x) {
+  return fputil::intlogb<long>(x);
+}
 
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/test/src/math/smoke/llogbl_test.cpp b/libc/test/src/math/smoke/llogbl_test.cpp
index c698210fc3de1..20332bfd6776b 100644
--- a/libc/test/src/math/smoke/llogbl_test.cpp
+++ b/libc/test/src/math/smoke/llogbl_test.cpp
@@ -11,3 +11,37 @@
 #include "src/math/llogbl.h"
 
 LIST_INTLOGB_TESTS(long, long double, LIBC_NAMESPACE::llogbl);
+
+// Constexpr tests: verify that llogbl can be evaluated at compile time.
+// These static_assert cases cover normal numbers with various exponents.
+namespace {
+class LLogblConstexprTest : public LIBC_NAMESPACE::testing::Test {
+public:
+  void RunTests() {
+    // Normal numbers: 2^0 = 1.0 => exponent 0
+    static_assert(LIBC_NAMESPACE::llogbl(1.0L) == 0);
+    static_assert(LIBC_NAMESPACE::llogbl(-1.0L) == 0);
+
+    // Normal numbers: 2^1 = 2.0 => exponent 1
+    static_assert(LIBC_NAMESPACE::llogbl(2.0L) == 1);
+    static_assert(LIBC_NAMESPACE::llogbl(-2.0L) == 1);
+
+    // Normal numbers: 2^2 = 4.0 => exponent 2
+    static_assert(LIBC_NAMESPACE::llogbl(4.0L) == 2);
+    static_assert(LIBC_NAMESPACE::llogbl(-4.0L) == 2);
+
+    // Normal numbers: 2^(-1) = 0.5 => exponent -1
+    static_assert(LIBC_NAMESPACE::llogbl(0.5L) == -1);
+    static_assert(LIBC_NAMESPACE::llogbl(-0.5L) == -1);
+
+    // Normal numbers: 2^3 = 8.0 => exponent 3
+    static_assert(LIBC_NAMESPACE::llogbl(8.0L) == 3);
+
+    // Normal numbers: 2^10 = 1024.0 => exponent 10
+    static_assert(LIBC_NAMESPACE::llogbl(1024.0L) == 10);
+  }
+};
+
+// Instantiate the test to trigger static_asserts at compile time.
+LLogblConstexprTest constexpr_test;
+} // anonymous namespace

>From 7386cfa52ed656f71d8c713873d9822c4d27f318 Mon Sep 17 00:00:00 2001
From: Mathew Joseph <69132893+mathew1046 at users.noreply.github.com>
Date: Sun, 11 Jan 2026 00:45:07 +0530
Subject: [PATCH 2/2] Update libc/test/src/math/smoke/llogbl_test.cpp

Co-authored-by: Copilot <175728472+Copilot at users.noreply.github.com>
---
 libc/test/src/math/smoke/llogbl_test.cpp | 51 ++++++++++--------------
 1 file changed, 22 insertions(+), 29 deletions(-)

diff --git a/libc/test/src/math/smoke/llogbl_test.cpp b/libc/test/src/math/smoke/llogbl_test.cpp
index 20332bfd6776b..5558960beabd1 100644
--- a/libc/test/src/math/smoke/llogbl_test.cpp
+++ b/libc/test/src/math/smoke/llogbl_test.cpp
@@ -15,33 +15,26 @@ LIST_INTLOGB_TESTS(long, long double, LIBC_NAMESPACE::llogbl);
 // Constexpr tests: verify that llogbl can be evaluated at compile time.
 // These static_assert cases cover normal numbers with various exponents.
 namespace {
-class LLogblConstexprTest : public LIBC_NAMESPACE::testing::Test {
-public:
-  void RunTests() {
-    // Normal numbers: 2^0 = 1.0 => exponent 0
-    static_assert(LIBC_NAMESPACE::llogbl(1.0L) == 0);
-    static_assert(LIBC_NAMESPACE::llogbl(-1.0L) == 0);
-
-    // Normal numbers: 2^1 = 2.0 => exponent 1
-    static_assert(LIBC_NAMESPACE::llogbl(2.0L) == 1);
-    static_assert(LIBC_NAMESPACE::llogbl(-2.0L) == 1);
-
-    // Normal numbers: 2^2 = 4.0 => exponent 2
-    static_assert(LIBC_NAMESPACE::llogbl(4.0L) == 2);
-    static_assert(LIBC_NAMESPACE::llogbl(-4.0L) == 2);
-
-    // Normal numbers: 2^(-1) = 0.5 => exponent -1
-    static_assert(LIBC_NAMESPACE::llogbl(0.5L) == -1);
-    static_assert(LIBC_NAMESPACE::llogbl(-0.5L) == -1);
-
-    // Normal numbers: 2^3 = 8.0 => exponent 3
-    static_assert(LIBC_NAMESPACE::llogbl(8.0L) == 3);
-
-    // Normal numbers: 2^10 = 1024.0 => exponent 10
-    static_assert(LIBC_NAMESPACE::llogbl(1024.0L) == 10);
-  }
-};
-
-// Instantiate the test to trigger static_asserts at compile time.
-LLogblConstexprTest constexpr_test;
+
+// Normal numbers: 2^0 = 1.0 => exponent 0
+static_assert(LIBC_NAMESPACE::llogbl(1.0L) == 0);
+static_assert(LIBC_NAMESPACE::llogbl(-1.0L) == 0);
+
+// Normal numbers: 2^1 = 2.0 => exponent 1
+static_assert(LIBC_NAMESPACE::llogbl(2.0L) == 1);
+static_assert(LIBC_NAMESPACE::llogbl(-2.0L) == 1);
+
+// Normal numbers: 2^2 = 4.0 => exponent 2
+static_assert(LIBC_NAMESPACE::llogbl(4.0L) == 2);
+static_assert(LIBC_NAMESPACE::llogbl(-4.0L) == 2);
+
+// Normal numbers: 2^(-1) = 0.5 => exponent -1
+static_assert(LIBC_NAMESPACE::llogbl(0.5L) == -1);
+static_assert(LIBC_NAMESPACE::llogbl(-0.5L) == -1);
+
+// Normal numbers: 2^3 = 8.0 => exponent 3
+static_assert(LIBC_NAMESPACE::llogbl(8.0L) == 3);
+
+// Normal numbers: 2^10 = 1024.0 => exponent 10
+static_assert(LIBC_NAMESPACE::llogbl(1024.0L) == 10);
 } // anonymous namespace



More information about the libc-commits mailing list