[libc-commits] [libc] a982431 - [libc] Add platform independent floating point rounding mode checks.

Tue Ly via libc-commits libc-commits at lists.llvm.org
Mon Jun 12 06:36:57 PDT 2023


Author: Tue Ly
Date: 2023-06-12T09:36:41-04:00
New Revision: a98243129530c852cbd42bffafc74ab635934d8a

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

LOG: [libc] Add platform independent floating point rounding mode checks.

Many math functions need to check for floating point rounding modes to
return correct values.  Currently most of them use the internal implementation
of `fegetround`, which is platform-dependent and blocking math functions to be
enabled on platforms with unimplemented `fegetround`.  In this change, we add
platform independent rounding mode checks and switching math functions to use
them instead. https://github.com/llvm/llvm-project/issues/63016

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D152280

Added: 
    libc/src/__support/FPUtil/rounding_mode.h
    libc/test/src/__support/FPUtil/rounding_mode_test.cpp

Modified: 
    libc/src/__support/CMakeLists.txt
    libc/src/__support/FPUtil/CMakeLists.txt
    libc/src/__support/FPUtil/Hypot.h
    libc/src/__support/FPUtil/NearestIntegerOperations.h
    libc/src/__support/FPUtil/except_value_utils.h
    libc/src/__support/FPUtil/generic/CMakeLists.txt
    libc/src/__support/FPUtil/generic/FMA.h
    libc/src/__support/FPUtil/generic/sqrt.h
    libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
    libc/src/__support/str_to_float.h
    libc/src/math/generic/CMakeLists.txt
    libc/src/math/generic/atanf.cpp
    libc/src/math/generic/coshf.cpp
    libc/src/math/generic/exp10f.cpp
    libc/src/math/generic/exp2f.cpp
    libc/src/math/generic/expf.cpp
    libc/src/math/generic/expm1f.cpp
    libc/src/math/generic/sincosf.cpp
    libc/src/math/generic/sinf.cpp
    libc/src/math/generic/sinhf.cpp
    libc/src/math/generic/tanhf.cpp
    libc/src/stdio/printf_core/CMakeLists.txt
    libc/src/stdio/printf_core/float_dec_converter.h
    libc/src/stdio/printf_core/float_hex_converter.h
    libc/test/src/__support/FPUtil/CMakeLists.txt
    utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index 676f1b98dba42..4a7b413697901 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -133,6 +133,7 @@ add_header_library(
     libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.builtin_wrappers
     libc.src.__support.common
     libc.src.errno.errno

diff  --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index b772b9d47ceec..3a6b6de1cfc89 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -2,6 +2,15 @@ add_header_library(
   fenv_impl
   HDRS
     FEnvImpl.h
+  DEPENDS
+    libc.include.fenv
+    libc.src.__support.macros.attributes
+)
+
+add_header_library(
+  rounding_mode
+  HDRS
+    rounding_mode.h
   DEPENDS
     libc.include.fenv
     libc.include.math
@@ -62,6 +71,7 @@ add_header_library(
   DEPENDS
     .fp_bits
     .fenv_impl
+    .rounding_mode
     libc.src.__support.CPP.type_traits
     libc.src.__support.common
     libc.include.math
@@ -124,6 +134,7 @@ add_header_library(
   DEPENDS
     .fp_bits
     .fenv_impl
+    .rounding_mode
     libc.src.__support.CPP.optional
     libc.src.__support.macros.optimization
 )
@@ -137,6 +148,7 @@ add_header_library(
     .basic_operations
     .fenv_impl
     .fp_bits
+    .rounding_mode
     libc.src.__support.builtin_wrappers
     libc.src.__support.CPP.bit
     libc.src.__support.CPP.type_traits

diff  --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 86817b7496541..61bf10bfc4f6c 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -12,6 +12,7 @@
 #include "BasicOperations.h"
 #include "FEnvImpl.h"
 #include "FPBits.h"
+#include "rounding_mode.h"
 #include "src/__support/CPP/bit.h"
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/UInt128.h"
@@ -190,7 +191,7 @@ LIBC_INLINE T hypot(T x, T y) {
       sum >>= 2;
       ++out_exp;
       if (out_exp >= FPBits_t::MAX_EXPONENT) {
-        if (int round_mode = get_round();
+        if (int round_mode = quick_get_round();
             round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
           return T(FPBits_t::inf());
         return T(FPBits_t(FPBits_t::MAX_NORMAL));
@@ -231,7 +232,7 @@ LIBC_INLINE T hypot(T x, T y) {
   y_new >>= 1;
 
   // Round to the nearest, tie to even.
-  int round_mode = get_round();
+  int round_mode = quick_get_round();
   switch (round_mode) {
   case FE_TONEAREST:
     // Round to nearest, ties to even

diff  --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 7081fc59057cf..96007ac5b7f57 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -11,6 +11,7 @@
 
 #include "FEnvImpl.h"
 #include "FPBits.h"
+#include "rounding_mode.h"
 
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/common.h"
@@ -162,7 +163,7 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) {
 
   bool is_neg = bits.get_sign();
   int exponent = bits.get_exponent();
-  int rounding_mode = get_round();
+  int rounding_mode = quick_get_round();
 
   // If the exponent is greater than the most negative mantissa
   // exponent, then x is already an integer.

diff  --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 8a5395fae12b1..df1b9c74aab28 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -11,6 +11,7 @@
 
 #include "FEnvImpl.h"
 #include "FPBits.h"
+#include "rounding_mode.h"
 #include "src/__support/CPP/optional.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
@@ -52,7 +53,7 @@ template <typename T, size_t N> struct ExceptValues {
     for (size_t i = 0; i < N; ++i) {
       if (LIBC_UNLIKELY(x_bits == values[i].input)) {
         UIntType out_bits = values[i].rnd_towardzero_result;
-        switch (fputil::get_round()) {
+        switch (fputil::quick_get_round()) {
         case FE_UPWARD:
           out_bits += values[i].rnd_upward_offset;
           break;
@@ -74,7 +75,7 @@ template <typename T, size_t N> struct ExceptValues {
     for (size_t i = 0; i < N; ++i) {
       if (LIBC_UNLIKELY(x_abs == values[i].input)) {
         UIntType out_bits = values[i].rnd_towardzero_result;
-        switch (fputil::get_round()) {
+        switch (fputil::quick_get_round()) {
         case FE_UPWARD:
           out_bits += sign ? values[i].rnd_downward_offset
                            : values[i].rnd_upward_offset;

diff  --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt
index 5b028839f5bb4..7f986d05adedf 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -9,6 +9,7 @@ add_header_library(
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.platform_defs
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.builtin_wrappers
     libc.src.__support.common
     libc.src.__support.uint128
@@ -25,6 +26,7 @@ add_header_library(
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.float_properties
     libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.builtin_wrappers
     libc.src.__support.macros.optimization
     libc.src.__support.uint128
@@ -40,6 +42,7 @@ add_header_library(
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.float_properties
     libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.builtin_wrappers
     libc.src.__support.macros.optimization
     libc.src.math.generic.math_utils

diff  --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 2af91c1289872..86cc40c808cd5 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -13,6 +13,7 @@
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/FloatProperties.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/UInt128.h"
 #include "src/__support/builtin_wrappers.h"
 #include "src/__support/macros/attributes.h"   // LIBC_INLINE
@@ -254,7 +255,7 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
   }
 
   // Finalize the result.
-  int round_mode = fputil::get_round();
+  int round_mode = fputil::quick_get_round();
   if (LIBC_UNLIKELY(r_exp >= FPBits::MAX_EXPONENT)) {
     if ((round_mode == FE_TOWARDZERO) ||
         (round_mode == FE_UPWARD && prod_sign) ||

diff  --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 1464056417d06..9e9896ed185fe 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -15,6 +15,7 @@
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PlatformDefs.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/UInt128.h"
 #include "src/__support/builtin_wrappers.h"
 #include "src/__support/common.h"
@@ -150,7 +151,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
 
       y = (y - ONE) | (static_cast<UIntType>(x_exp) << MantissaWidth<T>::VALUE);
 
-      switch (get_round()) {
+      switch (quick_get_round()) {
       case FE_TONEAREST:
         // Round to nearest, ties to even
         if (rb && (lsb || (r != 0)))

diff  --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index 17a1c25bc6407..3712012d3be8c 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -12,6 +12,7 @@
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PlatformDefs.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/UInt128.h"
 #include "src/__support/builtin_wrappers.h"
 #include "src/__support/common.h"
@@ -114,7 +115,7 @@ LIBC_INLINE long double sqrt(long double x) {
     y |= (static_cast<UIntType>(x_exp)
           << (MantissaWidth<long double>::VALUE + 1));
 
-    switch (get_round()) {
+    switch (quick_get_round()) {
     case FE_TONEAREST:
       // Round to nearest, ties to even
       if (rb && (lsb || (r != 0)))

diff  --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
new file mode 100644
index 0000000000000..28e2189ccb012
--- /dev/null
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -0,0 +1,79 @@
+//===---- Free-standing function to detect rounding mode --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_ROUNDING_MODE_H
+#define LLVM_LIBC_SRC_SUPPORT_FPUTIL_ROUNDING_MODE_H
+
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+
+#include <fenv.h>
+
+namespace __llvm_libc::fputil {
+
+// 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 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 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.
+// Using the following observation:
+//   1.5f + 2^-24 = 1.5f           for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
+//                = 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 bool fenv_is_round_to_nearest() {
+  static volatile float x = 0x1.0p-24f;
+  float y = x;
+  return (1.5f + y == 1.5f - y);
+}
+
+// Quick free-standing test whether fegetround() == FE_TOWARDZERO.
+// Using the following observation:
+//   1.0f + 2^-23 + 2^-24 = 0x1.000002p0f for FE_DOWNWARD, FE_TOWARDZERO
+//                        = 0x1.000004p0f for FE_TONEAREST, FE_UPWARD,
+//  -1.0f - 2^-24 = -1.0f          for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
+//                = -0x1.000002p0f for FE_DOWNWARD
+// So:
+// (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 __llvm_libc::fputil
+
+#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_ROUNDING_MODE_H

diff  --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index b36c73fbe8ef6..2ffa70f98f227 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -13,6 +13,7 @@
 #include "src/__support/CPP/optional.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/UInt128.h"
 #include "src/__support/builtin_wrappers.h"
 #include "src/__support/common.h"
@@ -1120,7 +1121,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
 
     RoundDirection round_direction = RoundDirection::Nearest;
 
-    switch (fputil::get_round()) {
+    switch (fputil::quick_get_round()) {
     case FE_TONEAREST:
       round_direction = RoundDirection::Nearest;
       break;

diff  --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index b2bde15b293ec..fc833a8a71383 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -109,6 +109,7 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.fma
     libc.src.__support.FPUtil.multiply_add
     libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
   COMPILE_OPTIONS
     -O3
@@ -130,6 +131,7 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.fma
     libc.src.__support.FPUtil.multiply_add
     libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
   COMPILE_OPTIONS
     -O3
@@ -542,6 +544,7 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.multiply_add
     libc.src.__support.FPUtil.nearest_integer
     libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
     libc.include.errno
     libc.src.errno.errno
@@ -563,6 +566,7 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.multiply_add
     libc.src.__support.FPUtil.nearest_integer
     libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
     libc.include.errno
     libc.src.errno.errno
@@ -584,6 +588,7 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.multiply_add
     libc.src.__support.FPUtil.nearest_integer
     libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
     libc.include.errno
     libc.src.errno.errno
@@ -606,6 +611,7 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.multiply_add
     libc.src.__support.FPUtil.nearest_integer
     libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
     libc.include.errno
     libc.src.errno.errno
@@ -1336,6 +1342,7 @@ add_entrypoint_object(
     .explogxf
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
   COMPILE_OPTIONS
     -O3
@@ -1350,6 +1357,7 @@ add_entrypoint_object(
   DEPENDS
     .explogxf
     libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
   COMPILE_OPTIONS
     -O3
@@ -1364,6 +1372,7 @@ add_entrypoint_object(
   DEPENDS
     .explogxf
     libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
   COMPILE_OPTIONS
     -O3
@@ -1483,6 +1492,7 @@ add_entrypoint_object(
     .inv_trigf_utils
     .math_utils
     libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.macros.optimization
   COMPILE_OPTIONS
     -O3

diff  --git a/libc/src/math/generic/atanf.cpp b/libc/src/math/generic/atanf.cpp
index ed7847adb15a1..9b0c11996a5b2 100644
--- a/libc/src/math/generic/atanf.cpp
+++ b/libc/src/math/generic/atanf.cpp
@@ -9,6 +9,7 @@
 #include "src/math/atanf.h"
 #include "math_utils.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/math/generic/inv_trigf_utils.h"
 
@@ -28,7 +29,7 @@ LLVM_LIBC_FUNCTION(float, atanf, (float x)) {
   }
   // |x| == 0.06905200332403183
   if (LIBC_UNLIKELY(xbits.uintval() == 0x3d8d6b23U)) {
-    if (fputil::get_round() == FE_TONEAREST) {
+    if (fputil::fenv_is_round_to_nearest()) {
       // 0.06894256919622421
       FPBits br(0x3d8d31c3U);
       br.set_sign(sign);
@@ -38,7 +39,7 @@ LLVM_LIBC_FUNCTION(float, atanf, (float x)) {
 
   // |x| == 1.8670953512191772
   if (LIBC_UNLIKELY(xbits.uintval() == 0x3feefcfbU)) {
-    int rounding_mode = fputil::get_round();
+    int rounding_mode = fputil::quick_get_round();
     if (sign) {
       if (rounding_mode == FE_DOWNWARD) {
         // -1.0790828466415405

diff  --git a/libc/src/math/generic/coshf.cpp b/libc/src/math/generic/coshf.cpp
index 1cf789a10a8ca..8b30d51c69dce 100644
--- a/libc/src/math/generic/coshf.cpp
+++ b/libc/src/math/generic/coshf.cpp
@@ -9,6 +9,7 @@
 #include "src/math/coshf.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/math/generic/explogxf.h"
 
@@ -32,7 +33,7 @@ LLVM_LIBC_FUNCTION(float, coshf, (float x)) {
     if (xbits.is_inf_or_nan())
       return x + FPBits::inf().get_val();
 
-    int rounding = fputil::get_round();
+    int rounding = fputil::quick_get_round();
     if (LIBC_UNLIKELY(rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO))
       return FPBits(FPBits::MAX_NORMAL).get_val();
 

diff  --git a/libc/src/math/generic/exp10f.cpp b/libc/src/math/generic/exp10f.cpp
index 9d07f2c5261ee..b0e93dd6fbca4 100644
--- a/libc/src/math/generic/exp10f.cpp
+++ b/libc/src/math/generic/exp10f.cpp
@@ -14,6 +14,7 @@
 #include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
@@ -38,7 +39,7 @@ LLVM_LIBC_FUNCTION(float, exp10f, (float x)) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-      if (fputil::get_round() == FE_UPWARD)
+      if (fputil::fenv_is_round_up())
         return static_cast<float>(FPBits(FPBits::MIN_SUBNORMAL));
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
@@ -48,7 +49,7 @@ LLVM_LIBC_FUNCTION(float, exp10f, (float x)) {
     if (!xbits.get_sign() && (x_u >= 0x421a'209bU)) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
-        int rounding = fputil::get_round();
+        int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
 
@@ -63,7 +64,7 @@ LLVM_LIBC_FUNCTION(float, exp10f, (float x)) {
   // When |x| <= log10(2)*2^-6
   if (LIBC_UNLIKELY(x_abs <= 0x3b9a'209bU)) {
     if (LIBC_UNLIKELY(x_u == 0xb25e'5bd9U)) { // x = -0x1.bcb7b2p-27f
-      if (fputil::get_round() == FE_TONEAREST)
+      if (fputil::fenv_is_round_to_nearest())
         return 0x1.fffffep-1f;
     }
     // |x| < 2^-25
@@ -77,7 +78,7 @@ LLVM_LIBC_FUNCTION(float, exp10f, (float x)) {
 
   // Exceptional value.
   if (LIBC_UNLIKELY(x_u == 0x3d14'd956U)) { // x = 0x1.29b2acp-5f
-    if (fputil::get_round() == FE_UPWARD)
+    if (fputil::fenv_is_round_up())
       return 0x1.1657c4p+0f;
   }
 

diff  --git a/libc/src/math/generic/exp2f.cpp b/libc/src/math/generic/exp2f.cpp
index f68d553c65deb..f2c005d5e00a0 100644
--- a/libc/src/math/generic/exp2f.cpp
+++ b/libc/src/math/generic/exp2f.cpp
@@ -12,6 +12,7 @@
 #include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
@@ -44,7 +45,7 @@ LLVM_LIBC_FUNCTION(float, exp2f, (float x)) {
     if (!xbits.get_sign()) {
       // x is finite
       if (x_u < 0x7f80'0000U) {
-        int rounding = fputil::get_round();
+        int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
 
@@ -62,7 +63,7 @@ LLVM_LIBC_FUNCTION(float, exp2f, (float x)) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-      if (fputil::get_round() == FE_UPWARD)
+      if (fputil::fenv_is_round_up())
         return FPBits(FPBits::MIN_SUBNORMAL).get_val();
       if (x != 0.0f) {
         fputil::set_errno_if_required(ERANGE);
@@ -75,10 +76,10 @@ LLVM_LIBC_FUNCTION(float, exp2f, (float x)) {
   // Check exceptional values.
   if (LIBC_UNLIKELY((x_u & EXVAL_MASK) == EXVAL_MASK)) {
     if (LIBC_UNLIKELY(x_u == EXVAL1)) { // x = 0x1.853a6ep-9f
-      if (fputil::get_round() == FE_TONEAREST)
+      if (fputil::fenv_is_round_to_nearest())
         return 0x1.00870ap+0f;
     } else if (LIBC_UNLIKELY(x_u == EXVAL2)) { // x = -0x1.e7526ep-6f
-      if (fputil::get_round() == FE_TONEAREST)
+      if (fputil::fenv_is_round_to_nearest())
         return 0x1.f58d62p-1f;
     }
   }

diff  --git a/libc/src/math/generic/expf.cpp b/libc/src/math/generic/expf.cpp
index cbee8a1ec4640..2cc8406c095ae 100644
--- a/libc/src/math/generic/expf.cpp
+++ b/libc/src/math/generic/expf.cpp
@@ -14,6 +14,7 @@
 #include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
@@ -48,7 +49,7 @@ LLVM_LIBC_FUNCTION(float, expf, (float x)) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-      if (fputil::get_round() == FE_UPWARD)
+      if (fputil::fenv_is_round_up())
         return static_cast<float>(FPBits(FPBits::MIN_SUBNORMAL));
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_UNDERFLOW);
@@ -58,7 +59,7 @@ LLVM_LIBC_FUNCTION(float, expf, (float x)) {
     if (!xbits.get_sign() && (xbits.uintval() >= 0x42b2'0000)) {
       // x is finite
       if (xbits.uintval() < 0x7f80'0000U) {
-        int rounding = fputil::get_round();
+        int rounding = fputil::quick_get_round();
         if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
           return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
 

diff  --git a/libc/src/math/generic/expm1f.cpp b/libc/src/math/generic/expm1f.cpp
index 33e408cd7861a..811baec0e9103 100644
--- a/libc/src/math/generic/expm1f.cpp
+++ b/libc/src/math/generic/expm1f.cpp
@@ -15,6 +15,7 @@
 #include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/optimization.h"            // LIBC_UNLIKELY
 #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
@@ -32,7 +33,7 @@ LLVM_LIBC_FUNCTION(float, expm1f, (float x)) {
 
   // Exceptional value
   if (LIBC_UNLIKELY(x_u == 0x3e35'bec5U)) { // x = 0x1.6b7d8ap-3f
-    int round_mode = fputil::get_round();
+    int round_mode = fputil::quick_get_round();
     if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
       return 0x1.8dbe64p-3f;
     return 0x1.8dbe62p-3f;
@@ -40,7 +41,7 @@ LLVM_LIBC_FUNCTION(float, expm1f, (float x)) {
 
 #if !defined(LIBC_TARGET_CPU_HAS_FMA)
   if (LIBC_UNLIKELY(x_u == 0xbdc1'c6cbU)) { // x = -0x1.838d96p-4f
-    int round_mode = fputil::get_round();
+    int round_mode = fputil::quick_get_round();
     if (round_mode == FE_TONEAREST || round_mode == FE_DOWNWARD)
       return -0x1.71c884p-4f;
     return -0x1.71c882p-4f;
@@ -57,7 +58,7 @@ LLVM_LIBC_FUNCTION(float, expm1f, (float x)) {
       // exp(nan) = nan
       if (xbits.is_nan())
         return x;
-      int round_mode = fputil::get_round();
+      int round_mode = fputil::quick_get_round();
       if (round_mode == FE_UPWARD || round_mode == FE_TOWARDZERO)
         return -0x1.ffff'fep-1f; // -1.0f + 0x1.0p-24f
       return -1.0f;
@@ -65,7 +66,7 @@ LLVM_LIBC_FUNCTION(float, expm1f, (float x)) {
       // x >= 89 or nan
       if (xbits.uintval() >= 0x42b2'0000) {
         if (xbits.uintval() < 0x7f80'0000U) {
-          int rounding = fputil::get_round();
+          int rounding = fputil::quick_get_round();
           if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
             return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
 

diff  --git a/libc/src/math/generic/sincosf.cpp b/libc/src/math/generic/sincosf.cpp
index 277126bdc89db..1611567eef977 100644
--- a/libc/src/math/generic/sincosf.cpp
+++ b/libc/src/math/generic/sincosf.cpp
@@ -11,6 +11,7 @@
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/optimization.h"            // LIBC_UNLIKELY
 #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
@@ -159,7 +160,7 @@ LLVM_LIBC_FUNCTION(void, sincosf, (float x, float *sinp, float *cosp)) {
       uint32_t s = EXCEPT_OUTPUTS_SIN[i][0]; // FE_TOWARDZERO
       uint32_t c = EXCEPT_OUTPUTS_COS[i][0]; // FE_TOWARDZERO
       bool x_sign = x < 0;
-      switch (fputil::get_round()) {
+      switch (fputil::quick_get_round()) {
       case FE_UPWARD:
         s += x_sign ? EXCEPT_OUTPUTS_SIN[i][2] : EXCEPT_OUTPUTS_SIN[i][1];
         c += EXCEPT_OUTPUTS_COS[i][1];

diff  --git a/libc/src/math/generic/sinf.cpp b/libc/src/math/generic/sinf.cpp
index 697c438c2c67b..01d2f70e73568 100644
--- a/libc/src/math/generic/sinf.cpp
+++ b/libc/src/math/generic/sinf.cpp
@@ -13,6 +13,7 @@
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/optimization.h"            // LIBC_UNLIKELY
 #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
@@ -126,7 +127,7 @@ LLVM_LIBC_FUNCTION(float, sinf, (float x)) {
 
   if (LIBC_UNLIKELY(x_abs == 0x4619'9998U)) { // x = 0x1.33333p13
     float r = -0x1.63f4bap-2f;
-    int rounding = fputil::get_round();
+    int rounding = fputil::quick_get_round();
     bool sign = xbits.get_sign();
     if ((rounding == FE_DOWNWARD && !sign) || (rounding == FE_UPWARD && sign))
       r = -0x1.63f4bcp-2f;

diff  --git a/libc/src/math/generic/sinhf.cpp b/libc/src/math/generic/sinhf.cpp
index 92edd4ea6a98f..7f4d0d6e3af2e 100644
--- a/libc/src/math/generic/sinhf.cpp
+++ b/libc/src/math/generic/sinhf.cpp
@@ -8,6 +8,7 @@
 
 #include "src/math/sinhf.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/math/generic/explogxf.h"
 
@@ -33,7 +34,7 @@ LLVM_LIBC_FUNCTION(float, sinhf, (float x)) {
     if (xbits.is_inf())
       return x;
 
-    int rounding = fputil::get_round();
+    int rounding = fputil::quick_get_round();
     if (sign) {
       if (LIBC_UNLIKELY(rounding == FE_UPWARD || rounding == FE_TOWARDZERO))
         return FPBits(FPBits::MAX_NORMAL | FPBits::FloatProp::SIGN_MASK)
@@ -53,7 +54,7 @@ LLVM_LIBC_FUNCTION(float, sinhf, (float x)) {
   if (LIBC_UNLIKELY(x_abs <= 0x3da0'0000U)) {
     // |x| = 0.0005589424981735646724700927734375
     if (LIBC_UNLIKELY(x_abs == 0x3a12'85ffU)) {
-      if (fputil::get_round() == FE_TONEAREST)
+      if (fputil::fenv_is_round_to_nearest())
         return x;
     }
 

diff  --git a/libc/src/math/generic/tanhf.cpp b/libc/src/math/generic/tanhf.cpp
index 8f2ba8852e4a0..eb6b50a64b014 100644
--- a/libc/src/math/generic/tanhf.cpp
+++ b/libc/src/math/generic/tanhf.cpp
@@ -8,6 +8,7 @@
 
 #include "src/math/tanhf.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/macros/optimization.h"            // LIBC_UNLIKELY
 #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA
 #include "src/math/generic/explogxf.h"
@@ -52,7 +53,7 @@ LLVM_LIBC_FUNCTION(float, tanhf, (float x)) {
   }
 
   if (LIBC_UNLIKELY(xbits.bits == 0x4058'e0a3U)) {
-    if (fputil::get_round() == FE_DOWNWARD)
+    if (fputil::fenv_is_round_down())
       return FPBits(0x3f7f'6ad9U).get_val();
   }
 

diff  --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index bcadc05270717..b124a11bc0a54 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -93,6 +93,7 @@ add_object_library(
     libc.src.__support.CPP.string_view
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.rounding_mode
     libc.src.__support.common
     libc.src.__support.libc_assert
     libc.src.__support.uint

diff  --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h
index 8d220ceeebb02..be4b2831d8063 100644
--- a/libc/src/stdio/printf_core/float_dec_converter.h
+++ b/libc/src/stdio/printf_core/float_dec_converter.h
@@ -13,6 +13,7 @@
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/FloatProperties.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/UInt.h"
 #include "src/__support/UInt128.h"
 #include "src/__support/common.h"
@@ -600,7 +601,7 @@ LIBC_INLINE int convert_float_decimal_typed(Writer *writer,
             (requiredTwos < 60 &&
              multiple_of_power_of_2(float_bits.get_explicit_mantissa(),
                                     static_cast<uint32_t>(requiredTwos)));
-        switch (fputil::get_round()) {
+        switch (fputil::quick_get_round()) {
         case FE_TONEAREST:
           // Round to nearest, if it's exactly halfway then round to even.
           if (last_digit != 5) {
@@ -774,7 +775,7 @@ LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer,
       (requiredTwos < 60 &&
        multiple_of_power_of_2(float_bits.get_explicit_mantissa(),
                               static_cast<uint32_t>(requiredTwos)));
-  switch (fputil::get_round()) {
+  switch (fputil::quick_get_round()) {
   case FE_TONEAREST:
     // Round to nearest, if it's exactly halfway then round to even.
     if (last_digit != 5) {
@@ -1022,7 +1023,7 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer,
       (requiredTwos < 60 &&
        multiple_of_power_of_2(float_bits.get_explicit_mantissa(),
                               static_cast<uint32_t>(requiredTwos)));
-  switch (fputil::get_round()) {
+  switch (fputil::quick_get_round()) {
   case FE_TONEAREST:
     // Round to nearest, if it's exactly halfway then round to even.
     if (last_digit != 5) {

diff  --git a/libc/src/stdio/printf_core/float_hex_converter.h b/libc/src/stdio/printf_core/float_hex_converter.h
index a26a3e796e4df..ae5efbabb7045 100644
--- a/libc/src/stdio/printf_core/float_hex_converter.h
+++ b/libc/src/stdio/printf_core/float_hex_converter.h
@@ -12,6 +12,7 @@
 #include "src/__support/CPP/string_view.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
 #include "src/__support/common.h"
 #include "src/stdio/printf_core/converter_utils.h"
 #include "src/stdio/printf_core/core_structs.h"
@@ -113,7 +114,7 @@ LIBC_INLINE int convert_float_hex_exp(Writer *writer,
 
     mantissa >>= shift_amount;
 
-    switch (fputil::get_round()) {
+    switch (fputil::quick_get_round()) {
     case FE_TONEAREST:
       // Round to nearest, if it's exactly halfway then round to even.
       if (truncated_bits > halfway_const)

diff  --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index a28c89a87bbbf..411b8281470cf 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -21,3 +21,13 @@ add_libc_test(
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fpbits_str
 )
+
+add_fp_unittest(
+  rounding_mode_test
+  SUITE
+    libc-fputil-tests
+  SRCS
+    rounding_mode_test.cpp
+  DEPENDS
+    libc.src.__support.FPUtil.rounding_mode
+)

diff  --git a/libc/test/src/__support/FPUtil/rounding_mode_test.cpp b/libc/test/src/__support/FPUtil/rounding_mode_test.cpp
new file mode 100644
index 0000000000000..8d3332f142ccf
--- /dev/null
+++ b/libc/test/src/__support/FPUtil/rounding_mode_test.cpp
@@ -0,0 +1,116 @@
+//===-- Unittests for the quick rounding mode checks ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+#include <fenv.h>
+
+using __llvm_libc::testing::mpfr::ForceRoundingMode;
+using __llvm_libc::testing::mpfr::RoundingMode;
+
+TEST(LlvmLibcFEnvImplTest, QuickRoundingUpTest) {
+  using __llvm_libc::fputil::fenv_is_round_up;
+  {
+    ForceRoundingMode __r(RoundingMode::Upward);
+    ASSERT_TRUE(fenv_is_round_up());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Downward);
+    ASSERT_FALSE(fenv_is_round_up());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Nearest);
+    ASSERT_FALSE(fenv_is_round_up());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::TowardZero);
+    ASSERT_FALSE(fenv_is_round_up());
+  }
+}
+
+TEST(LlvmLibcFEnvImplTest, QuickRoundingDownTest) {
+  using __llvm_libc::fputil::fenv_is_round_down;
+  {
+    ForceRoundingMode __r(RoundingMode::Upward);
+    ASSERT_FALSE(fenv_is_round_down());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Downward);
+    ASSERT_TRUE(fenv_is_round_down());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Nearest);
+    ASSERT_FALSE(fenv_is_round_down());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::TowardZero);
+    ASSERT_FALSE(fenv_is_round_down());
+  }
+}
+
+TEST(LlvmLibcFEnvImplTest, QuickRoundingNearestTest) {
+  using __llvm_libc::fputil::fenv_is_round_to_nearest;
+  {
+    ForceRoundingMode __r(RoundingMode::Upward);
+    ASSERT_FALSE(fenv_is_round_to_nearest());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Downward);
+    ASSERT_FALSE(fenv_is_round_to_nearest());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Nearest);
+    ASSERT_TRUE(fenv_is_round_to_nearest());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::TowardZero);
+    ASSERT_FALSE(fenv_is_round_to_nearest());
+  }
+}
+
+TEST(LlvmLibcFEnvImplTest, QuickRoundingTowardZeroTest) {
+  using __llvm_libc::fputil::fenv_is_round_to_zero;
+  {
+    ForceRoundingMode __r(RoundingMode::Upward);
+    ASSERT_FALSE(fenv_is_round_to_zero());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Downward);
+    ASSERT_FALSE(fenv_is_round_to_zero());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Nearest);
+    ASSERT_FALSE(fenv_is_round_to_zero());
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::TowardZero);
+    ASSERT_TRUE(fenv_is_round_to_zero());
+  }
+}
+
+TEST(LlvmLibcFEnvImplTest, QuickGetRoundTest) {
+  using __llvm_libc::fputil::quick_get_round;
+  {
+    ForceRoundingMode __r(RoundingMode::Upward);
+    ASSERT_EQ(quick_get_round(), FE_UPWARD);
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Downward);
+    ASSERT_EQ(quick_get_round(), FE_DOWNWARD);
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::Nearest);
+    ASSERT_EQ(quick_get_round(), FE_TONEAREST);
+  }
+  {
+    ForceRoundingMode __r(RoundingMode::TowardZero);
+    ASSERT_EQ(quick_get_round(), FE_TOWARDZERO);
+  }
+}

diff  --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index f62e5393c6eaa..d7439d4238825 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -444,6 +444,7 @@ libc_support_library(
         ":__support_ctype_utils",
         ":__support_fputil_fenv_impl",
         ":__support_fputil_fp_bits",
+        ":__support_fputil_rounding_mode",
         ":__support_str_to_integer",
         ":__support_str_to_num_result",
         ":__support_uint128",
@@ -529,6 +530,7 @@ libc_support_library(
         ":__support_cpp_optional",
         ":__support_fputil_fenv_impl",
         ":__support_fputil_fp_bits",
+        ":__support_fputil_rounding_mode",
         ":libc_root",
     ],
 )
@@ -551,6 +553,15 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_fputil_rounding_mode",
+    hdrs = ["src/__support/FPUtil/rounding_mode.h"],
+    deps = [
+        ":__support_macros_attributes",
+        ":libc_root",
+    ],
+)
+
 libc_support_library(
     name = "__support_fputil_float_properties",
     hdrs = ["src/__support/FPUtil/FloatProperties.h"],
@@ -604,6 +615,7 @@ libc_support_library(
         ":__support_fputil_basic_operations",
         ":__support_fputil_fenv_impl",
         ":__support_fputil_fp_bits",
+        ":__support_fputil_rounding_mode",
         ":__support_uint128",
         ":libc_root",
     ],
@@ -635,6 +647,7 @@ libc_support_library(
         ":__support_cpp_type_traits",
         ":__support_fputil_fenv_impl",
         ":__support_fputil_fp_bits",
+        ":__support_fputil_rounding_mode",
         ":libc_root",
     ],
 )
@@ -686,6 +699,7 @@ libc_support_library(
         ":__support_fputil_fenv_impl",
         ":__support_fputil_fp_bits",
         ":__support_fputil_platform_defs",
+        ":__support_fputil_rounding_mode",
         ":__support_uint128",
         ":libc_root",
     ],
@@ -714,6 +728,7 @@ libc_support_library(
         ":__support_fputil_fenv_impl",
         ":__support_fputil_float_properties",
         ":__support_fputil_fp_bits",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_attributes",
         ":__support_macros_optimization",
         ":__support_macros_properties_cpu_features",
@@ -1137,6 +1152,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":__support_macros_properties_cpu_features",
         ":common_constants",
@@ -1150,6 +1166,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":common_constants",
     ],
@@ -1162,6 +1179,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":common_constants",
         ":explogxf",
@@ -1175,6 +1193,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":explogxf",
     ],
@@ -1293,6 +1312,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":common_constants",
         ":explogxf",
@@ -1306,6 +1326,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":common_constants",
         ":explogxf",
@@ -1319,6 +1340,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":__support_macros_properties_cpu_features",
         ":common_constants",
@@ -1401,6 +1423,7 @@ libc_math_function(
         ":__support_fputil_multiply_add",
         ":__support_fputil_nearest_integer",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":inv_trigf_utils",
         ":math_utils",
@@ -1583,6 +1606,7 @@ libc_math_function(
     additional_deps = [
         ":__support_fputil_fma",
         ":__support_fputil_multiply_add",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":__support_macros_properties_cpu_features",
         ":sincosf_utils",
@@ -1595,6 +1619,7 @@ libc_math_function(
         ":__support_fputil_fma",
         ":__support_fputil_multiply_add",
         ":__support_fputil_polyeval",
+        ":__support_fputil_rounding_mode",
         ":__support_macros_optimization",
         ":__support_macros_properties_cpu_features",
         ":range_reduction",
@@ -2552,6 +2577,7 @@ libc_support_library(
         ":__support_fputil_fenv_impl",
         ":__support_fputil_float_properties",
         ":__support_fputil_fp_bits",
+        ":__support_fputil_rounding_mode",
         ":__support_integer_to_string",
         ":__support_libc_assert",
         ":__support_uint",


        


More information about the libc-commits mailing list