[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