[libc-commits] [libc] [libc] Fix constexpr FPUtils rounding_mode.h functions. (PR #152342)

via libc-commits libc-commits at lists.llvm.org
Wed Aug 6 12:59:21 PDT 2025


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

>From 9ad6987774022edb63054df17d534c4610e1a421 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Wed, 6 Aug 2025 17:10:21 +0000
Subject: [PATCH 1/2] [libc] Fix constexpr FPUtils rounding_mode.h functions.

---
 libc/src/__support/FPUtil/rounding_mode.h | 93 ++++++++++++++---------
 1 file changed, 59 insertions(+), 34 deletions(-)

diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 4ee0a0b0490fc..69b6a63a59c5a 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -17,30 +17,24 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
 
+namespace generic {
+
 // Quick free-standing test whether fegetround() == FE_UPWARD.
 // Using the following observation:
 //   1.0f + 2^-25 = 1.0f        for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
 //                = 0x1.000002f for FE_UPWARD.
-LIBC_INLINE static constexpr bool fenv_is_round_up() {
-  if (cpp::is_constant_evaluated()) {
-    return false;
-  } else {
-    volatile float x = 0x1.0p-25f;
-    return (1.0f + x != 1.0f);
-  }
+LIBC_INLINE bool fenv_is_round_up() {
+  volatile float x = 0x1.0p-25f;
+  return (1.0f + x != 1.0f);
 }
 
 // Quick free-standing test whether fegetround() == FE_DOWNWARD.
 // Using the following observation:
 //   -1.0f - 2^-25 = -1.0f        for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
 //                 = -0x1.000002f for FE_DOWNWARD.
-LIBC_INLINE static constexpr bool fenv_is_round_down() {
-  if (cpp::is_constant_evaluated()) {
-    return false;
-  } else {
-    volatile float x = 0x1.0p-25f;
-    return (-1.0f - x != -1.0f);
-  }
+LIBC_INLINE bool fenv_is_round_down() {
+  volatile float x = 0x1.0p-25f;
+  return (-1.0f - x != -1.0f);
 }
 
 // Quick free-standing test whether fegetround() == FE_TONEAREST.
@@ -49,14 +43,10 @@ LIBC_INLINE static constexpr bool fenv_is_round_down() {
 //                = 0x1.100002p0f  for FE_UPWARD,
 //   1.5f - 2^-24 = 1.5f           for FE_TONEAREST, FE_UPWARD
 //                = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
-LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
-  if (cpp::is_constant_evaluated()) {
-    return true;
-  } else {
-    volatile float x = 0x1.0p-24f;
-    float y = 1.5f + x;
-    return (y == 1.5f - x);
-  }
+LIBC_INLINE bool fenv_is_round_to_nearest() {
+  static volatile float x = 0x1.0p-24f;
+  float y = 1.5f + x;
+  return (y == 1.5f - x);
 }
 
 // Quick free-standing test whether fegetround() == FE_TOWARDZERO.
@@ -69,13 +59,56 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
 // (0x1.000002p0f + 2^-24) + (-1.0f - 2^-24) = 2^-23 for FE_TOWARDZERO
 //                                           = 2^-22 for FE_TONEAREST, FE_UPWARD
 //                                           = 0 for FE_DOWNWARD
+LIBC_INLINE bool fenv_is_round_to_zero() {
+  static volatile float x = 0x1.0p-24f;
+  float y = x;
+  return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
+}
+
+// Quick free standing get rounding mode based on the above observations.
+LIBC_INLINE int quick_get_round() {
+  static volatile float x = 0x1.0p-24f;
+  float y = x;
+  float z = (0x1.000002p0f + y) + (-1.0f - y);
+
+  if (z == 0.0f)
+    return FE_DOWNWARD;
+  if (z == 0x1.0p-23f)
+    return FE_TOWARDZERO;
+  return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
+}
+
+} // namespace generic
+
+LIBC_INLINE static constexpr bool fenv_is_round_up() {
+  if (cpp::is_constant_evaluated()) {
+    return false;
+  } else {
+    return generic::fenv_is_round_up();
+  }
+}
+
+LIBC_INLINE static constexpr bool fenv_is_round_down() {
+  if (cpp::is_constant_evaluated()) {
+    return false;
+  } else {
+    return generic::fenv_is_round_down();
+  }
+}
+
+LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
+  if (cpp::is_constant_evaluated()) {
+    return true;
+  } else {
+    return generic::fenv_is_round_to_nearest();
+  }
+}
+
 LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
   if (cpp::is_constant_evaluated()) {
     return false;
   } else {
-    volatile float x = 0x1.0p-24f;
-    volatile float y = 0x1.000002p0f + x;
-    return (y + (-1.0f - x) == 0x1.0p-23f);
+    return generic::fenv_is_round_to_zero();
   }
 }
 
@@ -84,15 +117,7 @@ LIBC_INLINE static constexpr int quick_get_round() {
   if (cpp::is_constant_evaluated()) {
     return FE_TONEAREST;
   } else {
-    volatile float x = 0x1.0p-24f;
-    volatile float y = 0x1.000002p0f + x;
-    float z = y + (-1.0f - x);
-
-    if (z == 0.0f)
-      return FE_DOWNWARD;
-    if (z == 0x1.0p-23f)
-      return FE_TOWARDZERO;
-    return (2.0f + x == 2.0f) ? FE_TONEAREST : FE_UPWARD;
+    return generic::quick_get_round();
   }
 }
 

>From c1b92ab214973647131acd85b818354a977b40f4 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Wed, 6 Aug 2025 19:58:55 +0000
Subject: [PATCH 2/2] Also use static volatile for round_up and round_down.

---
 libc/src/__support/FPUtil/rounding_mode.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 69b6a63a59c5a..fdc84986a4781 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -24,7 +24,7 @@ namespace generic {
 //   1.0f + 2^-25 = 1.0f        for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
 //                = 0x1.000002f for FE_UPWARD.
 LIBC_INLINE bool fenv_is_round_up() {
-  volatile float x = 0x1.0p-25f;
+  static volatile float x = 0x1.0p-25f;
   return (1.0f + x != 1.0f);
 }
 
@@ -33,7 +33,7 @@ LIBC_INLINE bool fenv_is_round_up() {
 //   -1.0f - 2^-25 = -1.0f        for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
 //                 = -0x1.000002f for FE_DOWNWARD.
 LIBC_INLINE bool fenv_is_round_down() {
-  volatile float x = 0x1.0p-25f;
+  static volatile float x = 0x1.0p-25f;
   return (-1.0f - x != -1.0f);
 }
 



More information about the libc-commits mailing list