[libc-commits] [libc] [libc][mathvec] Vectorise logf (PR #231190)
via libc-commits
libc-commits at lists.llvm.org
Wed Oct 21 06:55:55 PDT 2026
https://github.com/DylanFleming-arm updated https://github.com/llvm/llvm-project/pull/231190
>From 0e21f7e2f001a8fdf59b56ec7c9b27145d33f485 Mon Sep 17 00:00:00 2001
From: Dylan Fleming <Dylan.Fleming at arm.com>
Date: Mon, 12 Oct 2026 14:37:15 +0000
Subject: [PATCH 1/3] [libc][mathvec] Vectorise logf
Replaces loop over scalar logf with a fully vectorised implementation.
---
libc/src/__support/mathvec/common_constants.h | 48 ++++++++
libc/src/__support/mathvec/logf.h | 104 ++++++++++++++++--
libc/test/src/mathvec/logf_test.cpp | 6 +-
3 files changed, 147 insertions(+), 11 deletions(-)
diff --git a/libc/src/__support/mathvec/common_constants.h b/libc/src/__support/mathvec/common_constants.h
index 89d9c3903d282..e630ffa9eb8eb 100644
--- a/libc/src/__support/mathvec/common_constants.h
+++ b/libc/src/__support/mathvec/common_constants.h
@@ -38,6 +38,54 @@ LIBC_INLINE_VAR constexpr uint64_t EXP_MANTISSA[64] = {
0xea4afa2a490da, 0xefa1bee615a27, 0xf50765b6e4540, 0xfa7c1819e90d8,
};
+// Lookup table for ln(1 / R[i]), where R is the reciprocal from the table
+// found in libc/src/__support/math/common_constants.h, specifically optimised
+// for mathvec RN.
+LIBC_INLINE_VAR constexpr double LOG_TABLE[128] = {
+ 0x0.0000000000000p+0, 0x1.010157588de71p-7, 0x1.0205658935847p-6,
+ 0x1.8492528c8cabfp-6, 0x1.0415d89e74444p-5, 0x1.466aed42de3eap-5,
+ 0x1.894aa149fb343p-5, 0x1.ccb73cdddb2ccp-5, 0x1.08598b59e3a07p-4,
+ 0x1.1973bd1465567p-4, 0x1.3bdf5a7d1ee64p-4, 0x1.5e95a4d9791cbp-4,
+ 0x1.700d30aeac0e1p-4, 0x1.9335e5d594989p-4, 0x1.b6ac88dad5b1cp-4,
+ 0x1.c885801bc4b23p-4, 0x1.ec739830a1120p-4, 0x1.fe89139dbd566p-4,
+ 0x1.1178e8227e47cp-3, 0x1.1aa2b7e23f72ap-3, 0x1.2d1610c86813ap-3,
+ 0x1.365fcb0159016p-3, 0x1.4913d8333b561p-3, 0x1.527e5e4a1b57ep-3,
+ 0x1.6574ebe8c133ap-3, 0x1.6f0128b756abcp-3, 0x1.823c16551a3c2p-3,
+ 0x1.8beafeb38fe8cp-3, 0x1.95a5adcf7017fp-3, 0x1.a93ed3c8ad9e3p-3,
+ 0x1.b31d8575bce3dp-3, 0x1.bd087383bd8adp-3, 0x1.d1037f2655e7bp-3,
+ 0x1.db13db0d48940p-3, 0x1.e530effe71012p-3, 0x1.ef5ade4dcffe6p-3,
+ 0x1.f991c6cb3b379p-3, 0x1.07138604d5862p-2, 0x1.0c42d676162e3p-2,
+ 0x1.1178e8227e47cp-2, 0x1.16b5ccbacfb73p-2, 0x1.1bf99635a6b95p-2,
+ 0x1.269621134db92p-2, 0x1.2bef07cdc9354p-2, 0x1.314f1e1d35ce4p-2,
+ 0x1.36b6776be1117p-2, 0x1.3c25277333184p-2, 0x1.419b423d5e8c7p-2,
+ 0x1.4718dc271c41bp-2, 0x1.4c9e09e172c6bp-2, 0x1.522ae0738a3d8p-2,
+ 0x1.57bf753c8d1fbp-2, 0x1.5d5bddf595f30p-2, 0x1.630030b3aac49p-2,
+ 0x1.68ac83e9c6a14p-2, 0x1.6e60ee6af1972p-2, 0x1.741d876c67bb1p-2,
+ 0x1.79e26687cfb3ep-2, 0x1.7fafa3bd8151cp-2, 0x1.85855776dcbfbp-2,
+ 0x1.8b639a88b2df5p-2, 0x1.914a8635bf68ap-2, 0x1.973a3431356aep-2,
+ 0x1.9d32bea15ed3bp-2, 0x1.a33440224fa79p-2, 0x1.a33440224fa7bp-2,
+ 0x1.a93ed3c8ad9e3p-2, 0x1.af5295248cdd0p-2, 0x1.b56fa04462909p-2,
+ 0x1.bb9611b80e2fbp-2, 0x1.c1c60693fa39ep-2, 0x1.c1c60693fa39ep-2,
+ 0x1.c7ff9c74554c9p-2, 0x1.ce42f18064743p-2, 0x1.d490246defa6bp-2,
+ 0x1.dae75484c9616p-2, 0x1.e148a1a2726cep-2, 0x1.e148a1a2726cep-2,
+ 0x1.e7b42c3ddad73p-2, 0x1.ee2a156b413e5p-2, 0x1.f4aa7ee03192dp-2,
+ 0x1.f4aa7ee03192dp-2, 0x1.fb358af7a4884p-2, 0x1.00e5ae5b207abp-1,
+ 0x1.04360be7603adp-1, 0x1.04360be7603adp-1, 0x1.078bf0533c568p-1,
+ 0x1.0ae76e2d054fap-1, 0x1.0ae76e2d0552dp-1, 0x1.0e4898611cce1p-1,
+ 0x1.11af823c75aa8p-1, 0x1.11af823c75aa8p-1, 0x1.151c3f6f29612p-1,
+ 0x1.188ee40f23cbbp-1, 0x1.188ee40f23ca6p-1, 0x1.1c07849ae6007p-1,
+ 0x1.1f8635fc6165cp-1, 0x1.1f8635fc61659p-1, 0x1.230b0d8bebc98p-1,
+ 0x1.269621134db92p-1, 0x1.269621134db92p-1, 0x1.2a2786d0ec105p-1,
+ 0x1.2dbf557b0df43p-1, 0x1.2dbf557b0df43p-1, 0x1.315da4434068bp-1,
+ 0x1.315da4434068bp-1, 0x1.35028ad9d8c86p-1, 0x1.38ae2171976e7p-1,
+ 0x1.38ae2171976e7p-1, 0x1.3c6080c36bfb5p-1, 0x1.3c6080c36bfb5p-1,
+ 0x1.4019c2125ca93p-1, 0x1.43d9ff2f923c5p-1, 0x1.43d9ff2f923c5p-1,
+ 0x1.47a1527e8a2d3p-1, 0x1.47a1527e8a2d3p-1, 0x1.4b6fd6f970c1fp-1,
+ 0x1.4b6fd6f970c1fp-1, 0x1.4f45a835a4e19p-1, 0x1.4f45a835a4e19p-1,
+ 0x1.5322e26867857p-1, 0x1.5322e26867857p-1, 0x1.5707a26bb8c66p-1,
+ 0x1.5707a26bb8c66p-1, 0x1.5af405c3649e0p-1, 0x1.5af405c3649e0p-1,
+ 0x1.5ee82aa241920p-1, 0x1.62e42fefa39eep-1};
+
} // namespace mathvec
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/mathvec/logf.h b/libc/src/__support/mathvec/logf.h
index 0ff0c22fe59af..fe4e727bf4373 100644
--- a/libc/src/__support/mathvec/logf.h
+++ b/libc/src/__support/mathvec/logf.h
@@ -7,30 +7,118 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// This file contains the implemenation for single-precision SIMD log.
+/// This file contains the implementation for single-precision SIMD log.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_MATHVEC_LOGF_H
#define LLVM_LIBC_SRC___SUPPORT_MATHVEC_LOGF_H
+#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/simd.h"
-#define LIBC_MATH_HAS_NO_ERRNO
-#define LIBC_MATH_HAS_NO_EXCEPT
-#define LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
-#include "src/__support/math/logf.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/properties/cpu_features.h"
+#include "src/__support/math/common_constants.h"
+#include "src/__support/mathvec/common_constants.h"
namespace LIBC_NAMESPACE_DECL {
namespace mathvec {
template <size_t N>
-LIBC_INLINE cpp::simd<float, N> logf(cpp::simd<float, N> x) {
- return cpp::map(x, [](float a) { return math::logf(a); });
+LIBC_INLINE cpp::simd<float, N>
+inline_logf(cpp::simd<uint32_t, N> ux, cpp::simd<int32_t, N> exponent_bias) {
+ using namespace common_constants_internal;
+
+ // Extract the 7 leading bits of the mantissa
+ cpp::simd<uint32_t, N> index = (ux >> 16) & 0x7fU;
+
+ // Compute unbiased exponent
+ cpp::simd<int32_t, N> m = cpp::simd_cast<int32_t>(ux >> 23);
+ m += exponent_bias;
+
+ // Sets the exponent such that 1 <= u < 2
+ cpp::simd<float, N> u =
+ cpp::bit_cast<cpp::simd<float, N>>((ux & 0x007f'ffffU) | 0x3f80'0000U);
+
+ cpp::simd<double, N> log_r =
+ cpp::gather<cpp::simd<double, N>>(true, index, LOG_TABLE);
+
+#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+ cpp::simd<float, N> r = cpp::gather<cpp::simd<float, N>>(true, index, R);
+ cpp::simd<double, N> v = cpp::simd_cast<double>(
+ cpp::multiply_add(u, r, cpp::simd<float, N>(-1.0f)));
+#else
+ cpp::simd<double, N> r = cpp::gather<cpp::simd<double, N>>(true, index, RD);
+ cpp::simd<double, N> v = cpp::simd_cast<double>(u) * r - 1.0;
+#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
+
+ // Degree-5 polynomial approximation of log generated by Sollya with:
+ // > P = fpminimax(log(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]);
+ constexpr cpp::simd<double, N> c0 = -0x1.000000000fe63p-1;
+ constexpr cpp::simd<double, N> c1 = 0x1.555556e963c16p-2;
+ constexpr cpp::simd<double, N> c2 = -0x1.000028dedf986p-2;
+ constexpr cpp::simd<double, N> c3 = 0x1.966681bfda7f7p-3;
+ constexpr cpp::simd<double, N> log2 = 0x1.62e42fefa39efp-1;
+
+ // Evaluate log(1 + v) in double precision.
+ cpp::simd<double, N> v_squared = v * v;
+ cpp::simd<double, N> p2 = cpp::multiply_add(v, c3, c2);
+ cpp::simd<double, N> p1 = cpp::multiply_add(v, c1, c0);
+
+ // Accumulate the exponent independently of the polynomial's FMA chain.
+ cpp::simd<double, N> exponent = cpp::simd_cast<double>(m);
+ cpp::simd<double, N> p0 = cpp::multiply_add(exponent, log2, log_r) + v;
+ cpp::simd<double, N> y_d =
+ cpp::multiply_add(v_squared, cpp::multiply_add(v_squared, p2, p1), p0);
+ cpp::simd<float, N> y = cpp::simd_cast<float>(y_d);
+
+#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ y = (ux == 0x6f31a8ec) ? 0x1.08b512p+6 : y;
+ y = (ux == 0x79e7ec37) ? 0x1.43ff6ep+6 : y;
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#endif // !LIBC_TARGET_CPU_HAS_FMA_FLOAT
+
+ return y;
}
-} // namespace mathvec
+template <size_t N>
+LIBC_INLINE cpp::simd<float, N> special_case(cpp::simd<float, N> x) {
+ using FPBits = fputil::FPBits<float>;
+ cpp::simd<uint32_t, N> ux = cpp::bit_cast<cpp::simd<uint32_t, N>>(x);
+
+ // If x is subnormal, multiply by 23 to produce a normalised x,
+ // and subtract 23 from the exponent_bias to account for this scaling.
+ cpp::simd<bool, N> is_subnormal = (ux < 0x0080'0000U);
+ cpp::simd<uint32_t, N> normalized =
+ cpp::bit_cast<cpp::simd<uint32_t, N>>(x * 0x1.0p23f);
+ cpp::simd<int32_t, N> exponent_bias = is_subnormal ? -150 : -127;
+ ux = is_subnormal ? normalized : ux;
+
+ // Compute logf with the normalised input.
+ cpp::simd<float, N> y = inline_logf(ux, exponent_bias);
+
+ // Handle remaining specialc cases.
+ cpp::simd<bool, N> is_negative = x < 0;
+ cpp::simd<float, N> special = is_negative ? FPBits::quiet_nan().get_val() : x;
+ special = x == 0 ? -FPBits::inf().get_val() : special;
+
+ return ((ux >= 0x7f80'0000U) || (x == 0)) ? special : y;
+}
+template <size_t N>
+LIBC_INLINE cpp::simd<float, N> logf(cpp::simd<float, N> x) {
+ cpp::simd<uint32_t, N> ux = cpp::bit_cast<cpp::simd<uint32_t, N>>(x);
+
+ // Handle zero, inf, nan, and subnormals
+ cpp::simd<bool, N> is_special = (ux < 0x0080'0000U) || (ux >= 0x7f80'0000U);
+ if (LIBC_UNLIKELY(cpp::any_of(is_special)))
+ return special_case(x);
+
+ return inline_logf(ux, cpp::simd<int32_t, N>(-127));
+}
+} // namespace mathvec
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_MATHVEC_LOGF_H
diff --git a/libc/test/src/mathvec/logf_test.cpp b/libc/test/src/mathvec/logf_test.cpp
index 7e5087897de3e..25ca9b78d1d6e 100644
--- a/libc/test/src/mathvec/logf_test.cpp
+++ b/libc/test/src/mathvec/logf_test.cpp
@@ -12,15 +12,15 @@
//===----------------------------------------------------------------------===//
#include "hdr/math_macros.h"
+#include "hdr/stdint_proxy.h"
#include "src/__support/CPP/simd.h"
#include "src/__support/FPUtil/FPBits.h"
-#include "src/math/logf.h"
#include "src/mathvec/logf.h"
#include "test/UnitTest/SIMDMatcher.h"
#include "test/UnitTest/Test.h"
#include "test/src/mathvec/UnitTestWrappers.h"
-
-#include "hdr/stdint_proxy.h"
+#undef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#include "src/math/logf.h"
using LlvmLibcVecLogfTest = LIBC_NAMESPACE::testing::FPTest<float>;
>From 247000d04a7472ca70f78f3a615b781e7c4b9e6c Mon Sep 17 00:00:00 2001
From: Dylan Fleming <Dylan.Fleming at arm.com>
Date: Wed, 21 Oct 2026 13:13:13 +0000
Subject: [PATCH 2/3] Cleaned up testing and added table comment
Changed logf_test.cpp to use ULP tolerance rather than undefing
LIBC_MATH_HAS_SKIP_ACCURATE_PASS for the reference.
Added further details for LOG_TABLE tuning.
---
libc/src/__support/mathvec/common_constants.h | 16 ++++++++++++++--
libc/src/__support/mathvec/logf.h | 7 +++----
libc/test/src/mathvec/exhaustive/logf_test.cpp | 9 ++++++++-
libc/test/src/mathvec/logf_test.cpp | 17 +++++++++++++----
4 files changed, 38 insertions(+), 11 deletions(-)
diff --git a/libc/src/__support/mathvec/common_constants.h b/libc/src/__support/mathvec/common_constants.h
index e630ffa9eb8eb..e0e41cfd5fb4c 100644
--- a/libc/src/__support/mathvec/common_constants.h
+++ b/libc/src/__support/mathvec/common_constants.h
@@ -38,9 +38,21 @@ LIBC_INLINE_VAR constexpr uint64_t EXP_MANTISSA[64] = {
0xea4afa2a490da, 0xefa1bee615a27, 0xf50765b6e4540, 0xfa7c1819e90d8,
};
-// Lookup table for ln(1 / R[i]), where R is the reciprocal from the table
+// Lookup table for log(1 / R[i]), where R is the reciprocal from the table
// found in libc/src/__support/math/common_constants.h, specifically optimised
-// for mathvec RN.
+// for mathvec RN. There are two main differences:
+// 1. The final entry has LOG_TABLE[127] = log(2), rather than 0 in the scalar
+// table.
+// 2. Some values in the table are adjusted to remove hard-to-round cases,
+// making the main computation path branchless.
+// The following adjustments are made, in FP64 ULP:
+// LOG_TABLE[23] -15
+// LOG_TABLE[49] +47
+// LOG_TABLE[65] +2
+// LOG_TABLE[88] +51
+// LOG_TABLE[93] +21
+// LOG_TABLE[96] +3
+// LOG_TABLE[101] -2
LIBC_INLINE_VAR constexpr double LOG_TABLE[128] = {
0x0.0000000000000p+0, 0x1.010157588de71p-7, 0x1.0205658935847p-6,
0x1.8492528c8cabfp-6, 0x1.0415d89e74444p-5, 0x1.466aed42de3eap-5,
diff --git a/libc/src/__support/mathvec/logf.h b/libc/src/__support/mathvec/logf.h
index fe4e727bf4373..9a81550f866e8 100644
--- a/libc/src/__support/mathvec/logf.h
+++ b/libc/src/__support/mathvec/logf.h
@@ -73,12 +73,11 @@ inline_logf(cpp::simd<uint32_t, N> ux, cpp::simd<int32_t, N> exponent_bias) {
cpp::multiply_add(v_squared, cpp::multiply_add(v_squared, p2, p1), p0);
cpp::simd<float, N> y = cpp::simd_cast<float>(y_d);
-#ifndef LIBC_TARGET_CPU_HAS_FMA_FLOAT
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT) && \
+ defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS)
y = (ux == 0x6f31a8ec) ? 0x1.08b512p+6 : y;
y = (ux == 0x79e7ec37) ? 0x1.43ff6ep+6 : y;
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-#endif // !LIBC_TARGET_CPU_HAS_FMA_FLOAT
+#endif // !(LIBC_TARGET_CPU_HAS_FMA_FLOAT && LIBC_MATH_HAS_SKIP_ACCURATE_PASS)
return y;
}
diff --git a/libc/test/src/mathvec/exhaustive/logf_test.cpp b/libc/test/src/mathvec/exhaustive/logf_test.cpp
index cf47d4309e3a2..cf9efa5f8e957 100644
--- a/libc/test/src/mathvec/exhaustive/logf_test.cpp
+++ b/libc/test/src/mathvec/exhaustive/logf_test.cpp
@@ -13,12 +13,19 @@
#include "exhaustive_test.h"
#include "src/__support/CPP/simd.h"
+#include "src/__support/macros/optimization.h"
#include "src/math/logf.h"
#include "src/mathvec/logf.h"
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#define MATHVEC_TOL 1
+#else
+#define MATHVEC_TOL 0
+#endif
+
using LlvmLibcLogfExhaustiveTest =
LlvmLibcUnaryOpExhaustiveMathvecTest<float, LIBC_NAMESPACE::logf,
- LIBC_NAMESPACE::logf>;
+ LIBC_NAMESPACE::logf, MATHVEC_TOL>;
// Tests all possible 32-bit input patterns
TEST_F(LlvmLibcLogfExhaustiveTest, EntireRange) { test_full_range_RN(); }
diff --git a/libc/test/src/mathvec/logf_test.cpp b/libc/test/src/mathvec/logf_test.cpp
index 25ca9b78d1d6e..062b4ac97e593 100644
--- a/libc/test/src/mathvec/logf_test.cpp
+++ b/libc/test/src/mathvec/logf_test.cpp
@@ -15,12 +15,18 @@
#include "hdr/stdint_proxy.h"
#include "src/__support/CPP/simd.h"
#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/optimization.h"
+#include "src/math/logf.h"
#include "src/mathvec/logf.h"
#include "test/UnitTest/SIMDMatcher.h"
#include "test/UnitTest/Test.h"
#include "test/src/mathvec/UnitTestWrappers.h"
-#undef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-#include "src/math/logf.h"
+
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#define MATHVEC_TOL 1
+#else
+#define MATHVEC_TOL 0
+#endif
using LlvmLibcVecLogfTest = LIBC_NAMESPACE::testing::FPTest<float>;
@@ -85,8 +91,11 @@ TEST_F(LlvmLibcVecLogfTest, TrickyInputs) {
for (int i = 0; i < N; ++i) {
float x = FPBits(INPUTS[i]).get_val();
- EXPECT_SIMD_EQ(wrap_ref<LogfOp>(x, -x), wrap_vector<LogfOp>(x, -x));
+ EXPECT_SIMD_EQ(wrap_ref<LogfOp>(x, -x), wrap_vector<LogfOp>(x, -x),
+ MATHVEC_TOL);
}
}
-TEST_F(LlvmLibcVecLogfTest, InFloatRange) { TEST_MATHVEC_FLOAT_RANGE(LogfOp); }
+TEST_F(LlvmLibcVecLogfTest, InFloatRange) {
+ TEST_MATHVEC_FLOAT_RANGE_TOL(LogfOp, MATHVEC_TOL);
+}
>From dd803514069d281f51f2876aeceb011c24010988 Mon Sep 17 00:00:00 2001
From: Dylan Fleming <Dylan.Fleming at arm.com>
Date: Wed, 21 Oct 2026 13:52:00 +0000
Subject: [PATCH 3/3] Fixed logical error in preprocessor
---
libc/src/__support/mathvec/logf.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/__support/mathvec/logf.h b/libc/src/__support/mathvec/logf.h
index 9a81550f866e8..e0c30f6107b9f 100644
--- a/libc/src/__support/mathvec/logf.h
+++ b/libc/src/__support/mathvec/logf.h
@@ -73,11 +73,11 @@ inline_logf(cpp::simd<uint32_t, N> ux, cpp::simd<int32_t, N> exponent_bias) {
cpp::multiply_add(v_squared, cpp::multiply_add(v_squared, p2, p1), p0);
cpp::simd<float, N> y = cpp::simd_cast<float>(y_d);
-#if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT) && \
- defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS)
+#if !(defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT) || \
+ defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS))
y = (ux == 0x6f31a8ec) ? 0x1.08b512p+6 : y;
y = (ux == 0x79e7ec37) ? 0x1.43ff6ep+6 : y;
-#endif // !(LIBC_TARGET_CPU_HAS_FMA_FLOAT && LIBC_MATH_HAS_SKIP_ACCURATE_PASS)
+#endif // !(LIBC_TARGET_CPU_HAS_FMA_FLOAT || LIBC_MATH_HAS_SKIP_ACCURATE_PASS)
return y;
}
More information about the libc-commits
mailing list