[libc-commits] [libc] e7635cc - [libc][math] Add some explicit macro checks to round and roundf. (#217822)

via libc-commits libc-commits at lists.llvm.org
Fri Aug 21 08:48:14 PDT 2026


Author: lntue
Date: 2026-08-21T11:48:09-04:00
New Revision: e7635cccfae4d34d861d76ac404127a24d7eb768

URL: https://github.com/llvm/llvm-project/commit/e7635cccfae4d34d861d76ac404127a24d7eb768
DIFF: https://github.com/llvm/llvm-project/commit/e7635cccfae4d34d861d76ac404127a24d7eb768.diff

LOG: [libc][math] Add some explicit macro checks to round and roundf. (#217822)

This will allow users to use them without going through our cmake build
checks or forcing the flag `__LIBC_USE_BUILTIN_ROUND`.

Added: 
    

Modified: 
    libc/src/__support/math/CMakeLists.txt
    libc/src/__support/math/round.h
    libc/src/__support/math/roundf.h
    libc/test/src/math/RoundTest.h

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 4f5889fd5ba4b..e9325bb17cfdb 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -2451,7 +2451,10 @@ add_header_library(
     round.h
   DEPENDS
     libc.src.__support.FPUtil.nearest_integer_operations
+    libc.src.__support.macros.attributes
     libc.src.__support.macros.config
+    libc.src.__support.macros.properties.compiler
+    libc.src.__support.macros.properties.cpu_features
   FLAGS
     ROUND_OPT
 )
@@ -2541,6 +2544,10 @@ add_header_library(
   DEPENDS
     libc.src.__support.FPUtil.nearest_integer_operations
     libc.src.__support.macros.config
+    libc.src.__support.macros.attributes
+    libc.src.__support.macros.config
+    libc.src.__support.macros.properties.compiler
+    libc.src.__support.macros.properties.cpu_features
   FLAGS
     ROUND_OPT
 )

diff  --git a/libc/src/__support/math/round.h b/libc/src/__support/math/round.h
index 8cbfa3ff79e9a..d35c9f437a630 100644
--- a/libc/src/__support/math/round.h
+++ b/libc/src/__support/math/round.h
@@ -10,13 +10,40 @@
 #define LLVM_LIBC_SRC___SUPPORT_MATH_ROUND_H
 
 #include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/compiler.h"
+#include "src/__support/macros/properties/cpu_features.h"
 
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
+// For the following targets, clang will generate rounding instructions
+// by default:
+//   - x86-64 with sse4.1 or after
+//   - ARM v8
+//   - RISC-V
+
+// Notes: gcc does not generate the instructions for x86-64 by default.
+
+// Notes: for x86-64, if `-ffp-model=strict` is set, `__builtin_round` will
+// generate a callback to `round` and it does not look like there is any way for
+// us to detect that just from the pre-defined macros.  The only way to really
+// detect the call back is to compile and link with nostdlib.
+// This also affects `__builtin_elementwise_round`, making it behave identical
+// to `__builtin_round`.
+
+// Notes: `__builtin_elementwise_round` is slightly better than
+// `__builtin_round` in that it is not defined for x86-64 pre-SSE4.1, but it
+// still generate callback for ARM version < 8, and for x86-64 with
+// `-ffp-model=strict`.
+
 LIBC_INLINE LIBC_CONSTEXPR double round(double x) {
-#if defined(__LIBC_USE_BUILTIN_ROUND) && !defined(LIBC_USE_CONSTEXPR)
+#if __has_builtin(__builtin_round) && !defined(LIBC_USE_CONSTEXPR) &&          \
+    (defined(__LIBC_USE_BUILTIN_ROUND) ||                                      \
+     (defined(LIBC_COMPILER_IS_CLANG) &&                                       \
+      defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE) &&                               \
+      (!defined(__ARM_ARCH) || (__ARM_ARCH >= 8))))
   return __builtin_round(x);
 #else
   return fputil::round(x);

diff  --git a/libc/src/__support/math/roundf.h b/libc/src/__support/math/roundf.h
index e20b9d2e7f763..5abe9ebad15b0 100644
--- a/libc/src/__support/math/roundf.h
+++ b/libc/src/__support/math/roundf.h
@@ -10,13 +10,40 @@
 #define LLVM_LIBC_SRC___SUPPORT_MATH_ROUNDF_H
 
 #include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/compiler.h"
+#include "src/__support/macros/properties/cpu_features.h"
 
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
+// For the following targets, clang will generate rounding instructions
+// by default:
+//   - x86-64 with sse4.1 or after
+//   - ARM v8
+//   - RISC-V
+
+// Notes: gcc does not generate the instructions for x86-64 by default.
+
+// Notes: for x86-64, if `-ffp-model=strict` is set, `__builtin_round` will
+// generate a callback to `round` and it does not look like there is any way for
+// us to detect that just from the pre-defined macros.  The only way to really
+// detect the call back is to compile and link with nostdlib.
+// This also affects `__builtin_elementwise_round`, making it behave identical
+// to `__builtin_round`.
+
+// Notes: `__builtin_elementwise_round` is slightly better than
+// `__builtin_round` in that it is not defined for x86-64 pre-SSE4.1, but it
+// still generate callback for ARM version < 8, and for x86-64 with
+// `-ffp-model=strict`.
+
 LIBC_INLINE LIBC_CONSTEXPR float roundf(float x) {
-#if defined(__LIBC_USE_BUILTIN_ROUND) && !defined(LIBC_USE_CONSTEXPR)
+#if __has_builtin(__builtin_roundf) && !defined(LIBC_USE_CONSTEXPR) &&         \
+    (defined(__LIBC_USE_BUILTIN_ROUND) ||                                      \
+     (defined(LIBC_COMPILER_IS_CLANG) &&                                       \
+      defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) &&                                \
+      (!defined(__ARM_ARCH) || (__ARM_ARCH >= 8))))
   return __builtin_roundf(x);
 #else
   return fputil::round(x);

diff  --git a/libc/test/src/math/RoundTest.h b/libc/test/src/math/RoundTest.h
index a32b24a7a7719..b82f3562c2f32 100644
--- a/libc/test/src/math/RoundTest.h
+++ b/libc/test/src/math/RoundTest.h
@@ -9,14 +9,13 @@
 #ifndef LLVM_LIBC_TEST_SRC_MATH_ROUNDTEST_H
 #define LLVM_LIBC_TEST_SRC_MATH_ROUNDTEST_H
 
+#include "hdr/math_macros.h"
 #include "src/__support/CPP/algorithm.h"
 #include "test/UnitTest/FEnvSafeTest.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include "hdr/math_macros.h"
-
 namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
 
 template <typename T>
@@ -27,48 +26,6 @@ class RoundTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
 public:
   typedef T (*RoundFunc)(T);
 
-  void testSpecialNumbers(RoundFunc func) {
-    EXPECT_FP_EQ(zero, func(zero));
-    EXPECT_FP_EQ(neg_zero, func(neg_zero));
-
-    EXPECT_FP_EQ(inf, func(inf));
-    EXPECT_FP_EQ(neg_inf, func(neg_inf));
-
-    EXPECT_FP_EQ(aNaN, func(aNaN));
-  }
-
-  void testRoundedNumbers(RoundFunc func) {
-    EXPECT_FP_EQ(T(1.0), func(T(1.0)));
-    EXPECT_FP_EQ(T(-1.0), func(T(-1.0)));
-    EXPECT_FP_EQ(T(10.0), func(T(10.0)));
-    EXPECT_FP_EQ(T(-10.0), func(T(-10.0)));
-    EXPECT_FP_EQ(T(1234.0), func(T(1234.0)));
-    EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0)));
-  }
-
-  void testFractions(RoundFunc func) {
-    EXPECT_FP_EQ(T(1.0), func(T(0.5)));
-    EXPECT_FP_EQ(T(-1.0), func(T(-0.5)));
-    EXPECT_FP_EQ(T(0.0), func(T(0.115)));
-    EXPECT_FP_EQ(T(-0.0), func(T(-0.115)));
-    EXPECT_FP_EQ(T(1.0), func(T(0.715)));
-    EXPECT_FP_EQ(T(-1.0), func(T(-0.715)));
-    EXPECT_FP_EQ(T(1.0), func(T(1.3)));
-    EXPECT_FP_EQ(T(-1.0), func(T(-1.3)));
-    EXPECT_FP_EQ(T(2.0), func(T(1.5)));
-    EXPECT_FP_EQ(T(-2.0), func(T(-1.5)));
-    EXPECT_FP_EQ(T(2.0), func(T(1.75)));
-    EXPECT_FP_EQ(T(-2.0), func(T(-1.75)));
-    EXPECT_FP_EQ(T(10.0), func(T(10.32)));
-    EXPECT_FP_EQ(T(-10.0), func(T(-10.32)));
-    EXPECT_FP_EQ(T(11.0), func(T(10.65)));
-    EXPECT_FP_EQ(T(-11.0), func(T(-10.65)));
-    EXPECT_FP_EQ(T(123.0), func(T(123.38)));
-    EXPECT_FP_EQ(T(-123.0), func(T(-123.38)));
-    EXPECT_FP_EQ(T(124.0), func(T(123.96)));
-    EXPECT_FP_EQ(T(-124.0), func(T(-123.96)));
-  }
-
   void testRange(RoundFunc func) {
     constexpr int COUNT = 1'231;
     constexpr StorageType STEP = LIBC_NAMESPACE::cpp::max(
@@ -87,9 +44,6 @@ class RoundTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
 
 #define LIST_ROUND_TESTS(T, func)                                              \
   using LlvmLibcRoundTest = RoundTest<T>;                                      \
-  TEST_F(LlvmLibcRoundTest, SpecialNumbers) { testSpecialNumbers(&func); }     \
-  TEST_F(LlvmLibcRoundTest, RoundedNubmers) { testRoundedNumbers(&func); }     \
-  TEST_F(LlvmLibcRoundTest, Fractions) { testFractions(&func); }               \
   TEST_F(LlvmLibcRoundTest, Range) { testRange(&func); }
 
 #endif // LLVM_LIBC_TEST_SRC_MATH_ROUNDTEST_H


        


More information about the libc-commits mailing list