[libc-commits] [PATCH] D134917: [libc] Resolve NaN/implementation-defined behavior of floating-point tests

Dominic Chen via Phabricator via libc-commits libc-commits at lists.llvm.org
Thu Sep 29 15:33:14 PDT 2022


ddcc created this revision.
ddcc added reviewers: sivachandra, lntue.
Herald added subscribers: ecnelises, tschuett.
Herald added projects: libc-project, All.
ddcc requested review of this revision.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134917

Files:
  libc/src/__support/FPUtil/FPBits.h
  libc/test/src/math/RoundToIntegerTest.h
  libc/utils/UnitTest/FPMatcher.h


Index: libc/utils/UnitTest/FPMatcher.h
===================================================================
--- libc/utils/UnitTest/FPMatcher.h
+++ libc/utils/UnitTest/FPMatcher.h
@@ -67,12 +67,22 @@
 } // namespace fputil
 } // namespace __llvm_libc
 
+// Always generate quiet NaNs to avoid transformation of signaling NaNs:
+// C17 F10.9.2: "if just one argument is a NaN, the [fmin/fmax] functions return
+// the other argument"
+// IEEE 754-2019 6.2, 9.6: "if either operand is a signaling NaN, an invalid
+// operation exception is signaled.. under default exception handling, any
+// operation signaling an invalid operation exception and for which a
+// floating-point result is to be delivered, except as stated otherwise, shall
+// deliver a quiet NaN."
 #define DECLARE_SPECIAL_CONSTANTS(T)                                           \
   using FPBits = __llvm_libc::fputil::FPBits<T>;                               \
+  using MantissaWidth = __llvm_libc::fputil::MantissaWidth<T>;                 \
   using UIntType = typename FPBits::UIntType;                                  \
   const T zero = T(FPBits::zero());                                            \
   const T neg_zero = T(FPBits::neg_zero());                                    \
-  const T aNaN = T(FPBits::build_nan(1));                                      \
+  const T aNaN =                                                               \
+      T(FPBits::build_nan((1UL << (MantissaWidth::VALUE - 1)) | 1));           \
   const T inf = T(FPBits::inf());                                              \
   const T neg_inf = T(FPBits::neg_inf());
 
Index: libc/test/src/math/RoundToIntegerTest.h
===================================================================
--- libc/test/src/math/RoundToIntegerTest.h
+++ libc/test/src/math/RoundToIntegerTest.h
@@ -84,7 +84,10 @@
   void do_infinity_and_na_n_test(RoundToIntegerFunc func) {
     test_one_input(func, inf, INTEGER_MAX, true);
     test_one_input(func, neg_inf, INTEGER_MIN, true);
+#ifndef LLVM_LIBC_NO_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
+    // Result is not well-defined, we always returns INTEGER_MAX
     test_one_input(func, nan, INTEGER_MAX, true);
+#endif
   }
 
   void testInfinityAndNaN(RoundToIntegerFunc func) {
Index: libc/src/__support/FPUtil/FPBits.h
===================================================================
--- libc/src/__support/FPUtil/FPBits.h
+++ libc/src/__support/FPUtil/FPBits.h
@@ -90,8 +90,13 @@
   static_assert(sizeof(T) == sizeof(UIntType),
                 "Data type and integral representation have different sizes.");
 
-  static constexpr int EXPONENT_BIAS = (1 << (ExponentWidth<T>::VALUE - 1)) - 1;
-  static constexpr int MAX_EXPONENT = (1 << ExponentWidth<T>::VALUE) - 1;
+  static constexpr int EXPONENT_BIAS =
+      (UIntType(1) << (ExponentWidth<T>::VALUE - 1)) - 1;
+  static constexpr int MAX_EXPONENT =
+      (UIntType(1) << ExponentWidth<T>::VALUE) - 1;
+
+  static constexpr UIntType QUIET_BIT =
+      (UIntType(1) << (MantissaWidth<T>::VALUE - 1));
 
   static constexpr UIntType MIN_SUBNORMAL = UIntType(1);
   static constexpr UIntType MAX_SUBNORMAL =
@@ -164,9 +169,17 @@
     return bits;
   }
 
+  // Always generate quiet NaNs to avoid transformation of signaling NaNs:
+  // C17 F10.9.2: "if just one argument is a NaN, the [fmin/fmax] functions
+  // return the other argument"
+  // IEEE 754-2019 6.2, 9.6: "if either operand is a signaling NaN, an invalid
+  // operation exception is signaled... under default exception handling, any
+  // operation signaling an invalid operation exception and for which a
+  // floating-point result is to be delivered, except as stated otherwise,
+  // shall deliver a quiet NaN."
   static constexpr T build_nan(UIntType v) {
     FPBits<T> bits = inf();
-    bits.set_mantissa(v);
+    bits.set_mantissa(QUIET_BIT | v);
     return T(bits);
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D134917.464069.patch
Type: text/x-patch
Size: 3894 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20220929/7b5bb547/attachment.bin>


More information about the libc-commits mailing list