[libc-commits] [libc] [libc][math] Do not use __builtin_round* with clang on x86 by default. (PR #220739)

via libc-commits libc-commits at lists.llvm.org
Wed Sep 2 14:51:12 PDT 2026


https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/220739

>From 02a1b42fdc4790bf3639bc8b2d7dfc081f597675 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Wed, 2 Sep 2026 21:26:52 +0000
Subject: [PATCH 1/2] [libc][math] Do not use __builtin_round* with clang on
 x86 by default.

---
 libc/src/__support/math/CMakeLists.txt |  5 +-
 libc/src/__support/math/round.h        | 12 ++++-
 libc/src/__support/math/roundf.h       | 12 ++++-
 libc/test/src/math/smoke/RoundTest.h   | 66 +++++++++++++-------------
 4 files changed, 59 insertions(+), 36 deletions(-)

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 25489d60383a1..0f81197510ab3 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -2453,6 +2453,8 @@ add_header_library(
     libc.src.__support.FPUtil.nearest_integer_operations
     libc.src.__support.macros.attributes
     libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+    libc.src.__support.macros.properties.architectures
     libc.src.__support.macros.properties.compiler
     libc.src.__support.macros.properties.cpu_features
   FLAGS
@@ -2543,9 +2545,10 @@ add_header_library(
     roundf.h
   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.optimization
+    libc.src.__support.macros.properties.architectures
     libc.src.__support.macros.properties.compiler
     libc.src.__support.macros.properties.cpu_features
   FLAGS
diff --git a/libc/src/__support/math/round.h b/libc/src/__support/math/round.h
index d35c9f437a630..1f0d018957988 100644
--- a/libc/src/__support/math/round.h
+++ b/libc/src/__support/math/round.h
@@ -12,6 +12,8 @@
 #include "src/__support/FPUtil/NearestIntegerOperations.h"
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/properties/architectures.h"
 #include "src/__support/macros/properties/compiler.h"
 #include "src/__support/macros/properties/cpu_features.h"
 
@@ -38,12 +40,20 @@ namespace math {
 // still generate callback for ARM version < 8, and for x86-64 with
 // `-ffp-model=strict`.
 
+// Notes: `__builtin_round` expansion for x86-64 using SSE4.1 rounding
+// instruction by clang is only correct for the default rounding mode.
+// See https://github.com/llvm/llvm-project/issues/140252
+// So we will only use `__builtin_round` with clang on x86-64 if we assume
+// default rounding mode (FE_TONEAREST) only.
+
 LIBC_INLINE LIBC_CONSTEXPR double round(double x) {
 #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))))
+      (!defined(__ARM_ARCH) || (__ARM_ARCH >= 8)) &&                           \
+      (!defined(LIBC_TARGET_ARCH_IS_X86) ||                                    \
+       defined(LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY))))
   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 5abe9ebad15b0..e1cb4fc9c2e9e 100644
--- a/libc/src/__support/math/roundf.h
+++ b/libc/src/__support/math/roundf.h
@@ -12,6 +12,8 @@
 #include "src/__support/FPUtil/NearestIntegerOperations.h"
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/properties/architectures.h"
 #include "src/__support/macros/properties/compiler.h"
 #include "src/__support/macros/properties/cpu_features.h"
 
@@ -38,12 +40,20 @@ namespace math {
 // still generate callback for ARM version < 8, and for x86-64 with
 // `-ffp-model=strict`.
 
+// Notes: `__builtin_roundf` expansion for x86-64 using SSE4.1 rounding
+// instruction by clang is only correct for the default rounding mode.
+// See https://github.com/llvm/llvm-project/issues/140252
+// So we will only use `__builtin_round` with clang on x86-64 if we assume
+// default rounding mode (FE_TONEAREST) only.
+
 LIBC_INLINE LIBC_CONSTEXPR float roundf(float x) {
 #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))))
+      (!defined(__ARM_ARCH) || (__ARM_ARCH >= 8)) &&                           \
+      (!defined(LIBC_TARGET_ARCH_IS_X86) ||                                    \
+       defined(LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY))))
   return __builtin_roundf(x);
 #else
   return fputil::round(x);
diff --git a/libc/test/src/math/smoke/RoundTest.h b/libc/test/src/math/smoke/RoundTest.h
index 72889dada1378..82a557e77e90d 100644
--- a/libc/test/src/math/smoke/RoundTest.h
+++ b/libc/test/src/math/smoke/RoundTest.h
@@ -24,47 +24,47 @@ class RoundTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   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_ALL_ROUNDING(zero, func(zero));
+    EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(neg_zero));
 
-    EXPECT_FP_EQ(inf, func(inf));
-    EXPECT_FP_EQ(neg_inf, func(neg_inf));
+    EXPECT_FP_EQ_ALL_ROUNDING(inf, func(inf));
+    EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, func(neg_inf));
 
-    EXPECT_FP_EQ(aNaN, func(aNaN));
+    EXPECT_FP_EQ_ALL_ROUNDING(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)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(1.0), func(T(1.0)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-1.0), func(T(-1.0)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(10.0), func(T(10.0)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-10.0), func(T(-10.0)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(1234.0), func(T(1234.0)));
+    EXPECT_FP_EQ_ALL_ROUNDING(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(50.0), func(T(49.63)));
-    EXPECT_FP_EQ(T(-50.0), func(T(-50.31)));
-    EXPECT_FP_EQ(T(124.0), func(T(123.5)));
-    EXPECT_FP_EQ(T(-124.0), func(T(-123.5)));
-    EXPECT_FP_EQ(T(124.0), func(T(123.96)));
-    EXPECT_FP_EQ(T(-124.0), func(T(-123.96)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(1.0), func(T(0.5)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-1.0), func(T(-0.5)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(0.0), func(T(0.115)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-0.0), func(T(-0.115)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(1.0), func(T(0.715)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-1.0), func(T(-0.715)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(1.0), func(T(1.3)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-1.0), func(T(-1.3)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(2.0), func(T(1.5)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-2.0), func(T(-1.5)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(2.0), func(T(1.75)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-2.0), func(T(-1.75)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(10.0), func(T(10.32)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-10.0), func(T(-10.32)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(11.0), func(T(10.65)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-11.0), func(T(-10.65)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(50.0), func(T(49.63)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-50.0), func(T(-50.31)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(124.0), func(T(123.5)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-124.0), func(T(-123.5)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(124.0), func(T(123.96)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-124.0), func(T(-123.96)));
   }
 };
 

>From d793c8e87020bdd6a1de45f688490afb9e19fd52 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Wed, 2 Sep 2026 21:50:06 +0000
Subject: [PATCH 2/2] Adjust RoundTest to accommodate bf16.

---
 libc/test/src/math/smoke/RoundTest.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/test/src/math/smoke/RoundTest.h b/libc/test/src/math/smoke/RoundTest.h
index 82a557e77e90d..5459986db0451 100644
--- a/libc/test/src/math/smoke/RoundTest.h
+++ b/libc/test/src/math/smoke/RoundTest.h
@@ -60,7 +60,7 @@ class RoundTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
     EXPECT_FP_EQ_ALL_ROUNDING(T(11.0), func(T(10.65)));
     EXPECT_FP_EQ_ALL_ROUNDING(T(-11.0), func(T(-10.65)));
     EXPECT_FP_EQ_ALL_ROUNDING(T(50.0), func(T(49.63)));
-    EXPECT_FP_EQ_ALL_ROUNDING(T(-50.0), func(T(-50.31)));
+    EXPECT_FP_EQ_ALL_ROUNDING(T(-50.0), func(T(-50.25)));
     EXPECT_FP_EQ_ALL_ROUNDING(T(124.0), func(T(123.5)));
     EXPECT_FP_EQ_ALL_ROUNDING(T(-124.0), func(T(-123.5)));
     EXPECT_FP_EQ_ALL_ROUNDING(T(124.0), func(T(123.96)));



More information about the libc-commits mailing list