[libc-commits] [libc] [libc][math] Add tests and fix some issues with FTZ/DAZ modes. (PR #113744)

via libc-commits libc-commits at lists.llvm.org
Fri Oct 25 16:38:48 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: None (lntue)

<details>
<summary>Changes</summary>



---

Patch is 54.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113744.diff


56 Files Affected:

- (modified) libc/src/math/generic/atan2.cpp (+2-2) 
- (modified) libc/src/math/generic/cbrt.cpp (+3-2) 
- (modified) libc/src/math/generic/cbrtf.cpp (+3-2) 
- (modified) libc/src/math/generic/log.cpp (+1-1) 
- (modified) libc/src/math/generic/log10.cpp (+1-1) 
- (modified) libc/src/math/generic/log10f.cpp (+1-1) 
- (modified) libc/src/math/generic/log1p.cpp (+3-3) 
- (modified) libc/src/math/generic/log2.cpp (+1-1) 
- (modified) libc/src/math/generic/log2f.cpp (+1-1) 
- (modified) libc/src/math/generic/logf.cpp (+1-1) 
- (modified) libc/src/math/generic/pow.cpp (+9-7) 
- (modified) libc/src/math/generic/powf.cpp (+14-11) 
- (modified) libc/src/math/generic/sin.cpp (+1-1) 
- (modified) libc/src/math/generic/tan.cpp (+1-1) 
- (modified) libc/test/src/math/smoke/HypotTest.h (+1-3) 
- (modified) libc/test/src/math/smoke/acosf_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/acoshf_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/asinf_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/asinhf_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/atan2_test.cpp (+37) 
- (modified) libc/test/src/math/smoke/atanf_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/atanhf_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/cbrt_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/cbrtf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/cos_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/cosf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/coshf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/cospif_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/erff_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/exp10_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/exp10f_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/exp2_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/exp2f_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/exp2m1f_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/exp_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/expf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/expm1_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/expm1f_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/hypotf_test.cpp (+34) 
- (modified) libc/test/src/math/smoke/log10_test.cpp (+26) 
- (modified) libc/test/src/math/smoke/log10f_test.cpp (+26) 
- (modified) libc/test/src/math/smoke/log1p_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/log1pf_test.cpp (+24) 
- (modified) libc/test/src/math/smoke/log2_test.cpp (+26) 
- (modified) libc/test/src/math/smoke/log2f_test.cpp (+25) 
- (modified) libc/test/src/math/smoke/log_test.cpp (+26) 
- (modified) libc/test/src/math/smoke/logf_test.cpp (+25) 
- (modified) libc/test/src/math/smoke/pow_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/powf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/sin_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/sinf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/sinhf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/sinpif_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/tan_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/tanf_test.cpp (+27) 
- (modified) libc/test/src/math/smoke/tanhf_test.cpp (+27) 


``````````diff
diff --git a/libc/src/math/generic/atan2.cpp b/libc/src/math/generic/atan2.cpp
index c39deebca4d40e..1b16e15d29d0b3 100644
--- a/libc/src/math/generic/atan2.cpp
+++ b/libc/src/math/generic/atan2.cpp
@@ -230,8 +230,8 @@ LLVM_LIBC_FUNCTION(double, atan2, (double y, double x)) {
   if (LIBC_UNLIKELY(max_exp > 0x7ffU - 128U || min_exp < 128U)) {
     if (x_bits.is_nan() || y_bits.is_nan())
       return FPBits::quiet_nan().get_val();
-    unsigned x_except = x_abs == 0 ? 0 : (FPBits(x_abs).is_inf() ? 2 : 1);
-    unsigned y_except = y_abs == 0 ? 0 : (FPBits(y_abs).is_inf() ? 2 : 1);
+    unsigned x_except = x == 0.0 ? 0 : (FPBits(x_abs).is_inf() ? 2 : 1);
+    unsigned y_except = y == 0.0 ? 0 : (FPBits(y_abs).is_inf() ? 2 : 1);
 
     // Exceptional cases:
     //   EXCEPT[y_except][x_except][x_is_neg]
diff --git a/libc/src/math/generic/cbrt.cpp b/libc/src/math/generic/cbrt.cpp
index 036664c2aafaf4..e4fb8010dfcf48 100644
--- a/libc/src/math/generic/cbrt.cpp
+++ b/libc/src/math/generic/cbrt.cpp
@@ -151,9 +151,10 @@ LLVM_LIBC_FUNCTION(double, cbrt, (double x)) {
 
   if (LIBC_UNLIKELY(x_abs < FPBits::min_normal().uintval() ||
                     x_abs >= FPBits::inf().uintval())) {
-    if (x_abs == 0 || x_abs >= FPBits::inf().uintval())
+    if (x == 0.0 || x_abs >= FPBits::inf().uintval())
       // x is 0, Inf, or NaN.
-      return x;
+      // Make sure it works for FTZ/DAZ modes.
+      return static_cast<double>(x + x);
 
     // x is non-zero denormal number.
     // Normalize x.
diff --git a/libc/src/math/generic/cbrtf.cpp b/libc/src/math/generic/cbrtf.cpp
index 313961bf356b83..0abbf6e879421c 100644
--- a/libc/src/math/generic/cbrtf.cpp
+++ b/libc/src/math/generic/cbrtf.cpp
@@ -93,9 +93,10 @@ LLVM_LIBC_FUNCTION(float, cbrtf, (float x)) {
   uint32_t x_abs = x_bits.uintval() & 0x7fff'ffff;
   uint32_t sign_bit = (x_bits.uintval() >> 31) << DoubleBits::EXP_LEN;
 
-  if (LIBC_UNLIKELY(x_abs == 0 || x_abs >= 0x7f80'0000)) {
+  if (LIBC_UNLIKELY(x == 0.0f || x_abs >= 0x7f80'0000)) {
     // x is 0, Inf, or NaN.
-    return x;
+    // Make sure it works for FTZ/DAZ modes.
+    return x + x;
   }
 
   double xd = static_cast<double>(x);
diff --git a/libc/src/math/generic/log.cpp b/libc/src/math/generic/log.cpp
index 57c70e31730bf6..4302c64c8abac8 100644
--- a/libc/src/math/generic/log.cpp
+++ b/libc/src/math/generic/log.cpp
@@ -749,7 +749,7 @@ LLVM_LIBC_FUNCTION(double, log, (double x)) {
 
   if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
                     xbits.uintval() > FPBits_t::max_normal().uintval())) {
-    if (xbits.is_zero()) {
+    if (x == 0.0) {
       // return -Inf and raise FE_DIVBYZERO.
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
diff --git a/libc/src/math/generic/log10.cpp b/libc/src/math/generic/log10.cpp
index b99b22b024fe3c..7df57ef85b81b9 100644
--- a/libc/src/math/generic/log10.cpp
+++ b/libc/src/math/generic/log10.cpp
@@ -751,7 +751,7 @@ LLVM_LIBC_FUNCTION(double, log10, (double x)) {
 
   if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
                     xbits.uintval() > FPBits_t::max_normal().uintval())) {
-    if (xbits.is_zero()) {
+    if (x == 0.0) {
       // return -Inf and raise FE_DIVBYZERO.
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
diff --git a/libc/src/math/generic/log10f.cpp b/libc/src/math/generic/log10f.cpp
index f7dd85cc08bf03..c635fa4ef9b63f 100644
--- a/libc/src/math/generic/log10f.cpp
+++ b/libc/src/math/generic/log10f.cpp
@@ -164,7 +164,7 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) {
 
   if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval() ||
                     x_u > FPBits::max_normal().uintval())) {
-    if (xbits.is_zero()) {
+    if (x == 0.0f) {
       // Return -inf and raise FE_DIVBYZERO
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
diff --git a/libc/src/math/generic/log1p.cpp b/libc/src/math/generic/log1p.cpp
index f301a5aba3a57c..43eb8a924aef47 100644
--- a/libc/src/math/generic/log1p.cpp
+++ b/libc/src/math/generic/log1p.cpp
@@ -927,8 +927,8 @@ LLVM_LIBC_FUNCTION(double, log1p, (double x)) {
       //   log(1 + x) = nextafter(x, -inf) for FE_DOWNWARD, or
       //                                       FE_TOWARDZERO and x > 0,
       //              = x                  otherwise.
-      if (LIBC_UNLIKELY(xbits.is_zero()))
-        return x;
+      if (x == 0.0)
+        return x + x; // Handle FTZ/DAZ correctly.
 
       volatile float tp = 1.0f;
       volatile float tn = -1.0f;
@@ -943,7 +943,7 @@ LLVM_LIBC_FUNCTION(double, log1p, (double x)) {
         return FPBits_t(x_u + 1).get_val();
       }
 
-      return x;
+      return (x + x == 0.0) ? x + x : x;
     }
     x_dd = fputil::exact_add(1.0, x);
   }
diff --git a/libc/src/math/generic/log2.cpp b/libc/src/math/generic/log2.cpp
index 7d868e2f6f6198..37ea0c8f134315 100644
--- a/libc/src/math/generic/log2.cpp
+++ b/libc/src/math/generic/log2.cpp
@@ -871,7 +871,7 @@ LLVM_LIBC_FUNCTION(double, log2, (double x)) {
 
   if (LIBC_UNLIKELY(xbits.uintval() < FPBits_t::min_normal().uintval() ||
                     xbits.uintval() > FPBits_t::max_normal().uintval())) {
-    if (xbits.is_zero()) {
+    if (x == 0.0) {
       // return -Inf and raise FE_DIVBYZERO.
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
diff --git a/libc/src/math/generic/log2f.cpp b/libc/src/math/generic/log2f.cpp
index 9cad02d796b189..111f3f130bcab1 100644
--- a/libc/src/math/generic/log2f.cpp
+++ b/libc/src/math/generic/log2f.cpp
@@ -72,7 +72,7 @@ LLVM_LIBC_FUNCTION(float, log2f, (float x)) {
   // Exceptional inputs.
   if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval() ||
                     x_u > FPBits::max_normal().uintval())) {
-    if (xbits.is_zero()) {
+    if (x == 0.0f) {
       fputil::set_errno_if_required(ERANGE);
       fputil::raise_except_if_required(FE_DIVBYZERO);
       return FPBits::inf(Sign::NEG).get_val();
diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp
index f8ecf320568ac7..30c00edafe21d8 100644
--- a/libc/src/math/generic/logf.cpp
+++ b/libc/src/math/generic/logf.cpp
@@ -82,7 +82,7 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
     }
     // Subnormal inputs.
     if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) {
-      if (x_u == 0) {
+      if (x == 0.0f) {
         // Return -inf and raise FE_DIVBYZERO
         fputil::set_errno_if_required(ERANGE);
         fputil::raise_except_if_required(FE_DIVBYZERO);
diff --git a/libc/src/math/generic/pow.cpp b/libc/src/math/generic/pow.cpp
index 181d3d40b3c9ad..213dbd959039c3 100644
--- a/libc/src/math/generic/pow.cpp
+++ b/libc/src/math/generic/pow.cpp
@@ -228,16 +228,18 @@ LLVM_LIBC_FUNCTION(double, pow, (double x, double y)) {
                     x_u >= FPBits::inf().uintval() ||
                     x_u < FPBits::min_normal().uintval())) {
     // Exceptional exponents.
-    switch (y_a) {
-    case 0: // y = +-0.0
+    if (y == 0.0)
       return 1.0;
+
+    switch (y_a) {
     case 0x3fe0'0000'0000'0000: { // y = +-0.5
       // TODO: speed up x^(-1/2) with rsqrt(x) when available.
-      if (LIBC_UNLIKELY(!y_sign && (x_u == FPBits::zero(Sign::NEG).uintval() ||
-                                    x_u == FPBits::inf(Sign::NEG).uintval()))) {
+      if (LIBC_UNLIKELY(
+              (x == 0.0 || x_u == FPBits::inf(Sign::NEG).uintval()))) {
         // pow(-0, 1/2) = +0
         // pow(-inf, 1/2) = +inf
-        return FPBits(x_abs).get_val();
+        // Make sure it works correctly for FTZ/DAZ.
+        return y_sign ? 1.0 / (x * x) : (x * x);
       }
       return y_sign ? (1.0 / fputil::sqrt<double>(x)) : fputil::sqrt<double>(x);
     }
@@ -269,7 +271,7 @@ LLVM_LIBC_FUNCTION(double, pow, (double x, double y)) {
           return 1.0;
         }
 
-        if (x_a == 0 && y_sign) {
+        if (x == 0.0 && y_sign) {
           // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO
           fputil::set_errno_if_required(EDOM);
           fputil::raise_except_if_required(FE_DIVBYZERO);
@@ -298,7 +300,7 @@ LLVM_LIBC_FUNCTION(double, pow, (double x, double y)) {
 
     // TODO: Speed things up with pow(2, y) = exp2(y) and pow(10, y) = exp10(y).
 
-    if (x_a == 0) {
+    if (x == 0.0) {
       bool out_is_neg = x_sign && is_odd_integer(y);
       if (y_sign) {
         // pow(0, negative number) = inf
diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp
index 83477c6ef2aceb..c84ce0da34b10a 100644
--- a/libc/src/math/generic/powf.cpp
+++ b/libc/src/math/generic/powf.cpp
@@ -529,10 +529,10 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
   // Hence x^y will either overflow or underflow if x is not zero.
   if (LIBC_UNLIKELY((y_abs & 0x0007'ffff) == 0) || (y_abs > 0x4f170000)) {
     // Exceptional exponents.
-    switch (y_abs) {
-    case 0x0000'0000: { // y = +-0.0f
+    if (y == 0.0f)
       return 1.0f;
-    }
+
+    switch (y_abs) {
     case 0x7f80'0000: { // y = +-Inf
       if (x_abs > 0x7f80'0000) {
         // pow(NaN, +-Inf) = NaN
@@ -542,7 +542,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
         // pow(+-1, +-Inf) = 1.0f
         return 1.0f;
       }
-      if (x_abs == 0 && y_u == 0xff80'0000) {
+      if (x == 0.0f && y_u == 0xff80'0000) {
         // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO
         fputil::set_errno_if_required(EDOM);
         fputil::raise_except_if_required(FE_DIVBYZERO);
@@ -561,12 +561,15 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
       switch (y_u) {
       case 0x3f00'0000: // y = 0.5f
         // pow(x, 1/2) = sqrt(x)
-        if (LIBC_UNLIKELY(x_u == 0x8000'0000 || x_u == 0xff80'0000)) {
+        if (LIBC_UNLIKELY(x == 0.0f || x_u == 0xff80'0000)) {
           // pow(-0, 1/2) = +0
           // pow(-inf, 1/2) = +inf
-          return FloatBits(x_abs).get_val();
+          // Make sure it is correct for FTZ/DAZ.
+          return x * x;
         }
-        return fputil::sqrt<float>(x);
+        float r;
+        r = fputil::sqrt<float>(x);
+        return (FloatBits(r).uintval() != 0x8000'0000) ? r : 0.0f;
       case 0x3f80'0000: // y = 1.0f
         return x;
       case 0x4000'0000: // y = 2.0f
@@ -634,8 +637,7 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
 
     const bool x_is_neg = x_u >= FloatBits::SIGN_MASK;
 
-    switch (x_abs) {
-    case 0x0000'0000: { // x = +-0.0f
+    if (x == 0.0f) {
       const bool out_is_neg =
           x_is_neg && is_odd_integer(FloatBits(y_u).get_val());
       if (y_u > 0x8000'0000U) {
@@ -647,7 +649,9 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
       // pow(0, positive number) = 0
       return out_is_neg ? -0.0f : 0.0f;
     }
-    case 0x7f80'0000: { // x = +-Inf
+
+    if (x_abs == 0x7f80'0000) {
+      // x = +-Inf
       const bool out_is_neg =
           x_is_neg && is_odd_integer(FloatBits(y_u).get_val());
       if (y_u >= FloatBits::SIGN_MASK) {
@@ -655,7 +659,6 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
       }
       return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS).get_val();
     }
-    }
 
     if (x_abs > 0x7f80'0000) {
       // x is NaN.
diff --git a/libc/src/math/generic/sin.cpp b/libc/src/math/generic/sin.cpp
index 2e1d3ffd5f37d8..b32486dff487ca 100644
--- a/libc/src/math/generic/sin.cpp
+++ b/libc/src/math/generic/sin.cpp
@@ -50,7 +50,7 @@ LLVM_LIBC_FUNCTION(double, sin, (double x)) {
       if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 26)) {
         // Signed zeros.
         if (LIBC_UNLIKELY(x == 0.0))
-          return x;
+          return x + x; // Make sure it works with FTZ/DAZ.
 
 #ifdef LIBC_TARGET_CPU_HAS_FMA
         return fputil::multiply_add(x, -0x1.0p-54, x);
diff --git a/libc/src/math/generic/tan.cpp b/libc/src/math/generic/tan.cpp
index f9be25ed866e1d..19d31a8441efb6 100644
--- a/libc/src/math/generic/tan.cpp
+++ b/libc/src/math/generic/tan.cpp
@@ -138,7 +138,7 @@ LLVM_LIBC_FUNCTION(double, tan, (double x)) {
       if (LIBC_UNLIKELY(x_e < FPBits::EXP_BIAS - 27)) {
         // Signed zeros.
         if (LIBC_UNLIKELY(x == 0.0))
-          return x;
+          return x + x; // Make sure it works with FTZ/DAZ.
 
 #ifdef LIBC_TARGET_CPU_HAS_FMA
         return fputil::multiply_add(x, 0x1.0p-54, x);
diff --git a/libc/test/src/math/smoke/HypotTest.h b/libc/test/src/math/smoke/HypotTest.h
index d7c62dcbeb0edb..30d57a4fe2a267 100644
--- a/libc/test/src/math/smoke/HypotTest.h
+++ b/libc/test/src/math/smoke/HypotTest.h
@@ -14,13 +14,11 @@
 #include "test/UnitTest/Test.h"
 
 template <typename T>
-class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test {
-private:
+struct HypotTestTemplate : public LIBC_NAMESPACE::testing::Test {
   using Func = T (*)(T, T);
 
   DECLARE_SPECIAL_CONSTANTS(T)
 
-public:
   void test_special_numbers(Func func) {
     constexpr int N = 4;
     // Pythagorean triples.
diff --git a/libc/test/src/math/smoke/acosf_test.cpp b/libc/test/src/math/smoke/acosf_test.cpp
index 039d8c2013830d..e5d56c70f27221 100644
--- a/libc/test/src/math/smoke/acosf_test.cpp
+++ b/libc/test/src/math/smoke/acosf_test.cpp
@@ -38,3 +38,27 @@ TEST_F(LlvmLibcAcosfTest, SpecialNumbers) {
   EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acosf(-2.0f));
   EXPECT_MATH_ERRNO(EDOM);
 }
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcAcosfTest, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+
+  EXPECT_FP_EQ(0x1.921fb6p0f, LIBC_NAMESPACE::acosf(min_denormal));
+}
+
+TEST_F(LlvmLibcAcosfTest, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+
+  EXPECT_FP_EQ(0x1.921fb6p0f, LIBC_NAMESPACE::acosf(min_denormal));
+}
+
+TEST_F(LlvmLibcAcosfTest, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_EQ(0x1.921fb6p0f, LIBC_NAMESPACE::acosf(min_denormal));
+}
+
+#endif
diff --git a/libc/test/src/math/smoke/acoshf_test.cpp b/libc/test/src/math/smoke/acoshf_test.cpp
index 91d433df80558d..c4e88259919c3c 100644
--- a/libc/test/src/math/smoke/acoshf_test.cpp
+++ b/libc/test/src/math/smoke/acoshf_test.cpp
@@ -35,3 +35,27 @@ TEST_F(LlvmLibcAcoshfTest, SpecialNumbers) {
   EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acoshf(neg_inf));
   EXPECT_MATH_ERRNO(EDOM);
 }
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcAcoshfTest, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+
+  EXPECT_FP_IS_NAN(LIBC_NAMESPACE::acoshf(min_denormal));
+}
+
+TEST_F(LlvmLibcAcoshfTest, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+
+  EXPECT_FP_IS_NAN(LIBC_NAMESPACE::acoshf(min_denormal));
+}
+
+TEST_F(LlvmLibcAcoshfTest, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_IS_NAN(LIBC_NAMESPACE::acoshf(min_denormal));
+}
+
+#endif
diff --git a/libc/test/src/math/smoke/asinf_test.cpp b/libc/test/src/math/smoke/asinf_test.cpp
index 450255ccd3020d..ce1576e2b57dfc 100644
--- a/libc/test/src/math/smoke/asinf_test.cpp
+++ b/libc/test/src/math/smoke/asinf_test.cpp
@@ -41,3 +41,27 @@ TEST_F(LlvmLibcAsinfTest, SpecialNumbers) {
   EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinf(-2.0f));
   EXPECT_MATH_ERRNO(EDOM);
 }
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcAsinfTest, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::asinf(min_denormal));
+}
+
+TEST_F(LlvmLibcAsinfTest, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::asinf(min_denormal));
+}
+
+TEST_F(LlvmLibcAsinfTest, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::asinf(min_denormal));
+}
+
+#endif
diff --git a/libc/test/src/math/smoke/asinhf_test.cpp b/libc/test/src/math/smoke/asinhf_test.cpp
index a8e54f379a1fd0..5b83ce6466113f 100644
--- a/libc/test/src/math/smoke/asinhf_test.cpp
+++ b/libc/test/src/math/smoke/asinhf_test.cpp
@@ -35,3 +35,27 @@ TEST_F(LlvmLibcAsinhfTest, SpecialNumbers) {
   EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, LIBC_NAMESPACE::asinhf(neg_inf));
   EXPECT_MATH_ERRNO(0);
 }
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcAsinhfTest, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::asinhf(min_denormal));
+}
+
+TEST_F(LlvmLibcAsinhfTest, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::asinhf(min_denormal));
+}
+
+TEST_F(LlvmLibcAsinhfTest, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::asinhf(min_denormal));
+}
+
+#endif
diff --git a/libc/test/src/math/smoke/atan2_test.cpp b/libc/test/src/math/smoke/atan2_test.cpp
index 61dd6cab1049fe..1606c3f378cb88 100644
--- a/libc/test/src/math/smoke/atan2_test.cpp
+++ b/libc/test/src/math/smoke/atan2_test.cpp
@@ -20,3 +20,40 @@ TEST_F(LlvmLibcAtan2Test, SpecialNumbers) {
   EXPECT_FP_EQ_ALL_ROUNDING(0.0, LIBC_NAMESPACE::atan2(1.0, inf));
   EXPECT_FP_EQ_ALL_ROUNDING(-0.0, LIBC_NAMESPACE::atan2(-1.0, inf));
 }
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcAtan2Test, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+
+  EXPECT_FP_EQ(0x1.921fb54442d18p-1,
+               LIBC_NAMESPACE::atan2(min_denormal, min_denormal));
+  EXPECT_FP_EQ(0x1.0000000000001p-52,
+               LIBC_NAMESPACE::atan2(min_denormal, max_denormal));
+  EXPECT_FP_EQ(0x1.921fb54442d17p0,
+               LIBC_NAMESPACE::atan2(max_denormal, min_denormal));
+  EXPECT_FP_EQ(0x1.921fb54442d18p-1,
+               LIBC_NAMESPACE::atan2(max_denormal, max_denormal));
+}
+
+TEST_F(LlvmLibcAtan2Test, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(min_denormal, min_denormal));
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(min_denormal, max_denormal));
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(max_denormal, min_denormal));
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(max_denormal, max_denormal));
+}
+
+TEST_F(LlvmLibcAtan2Test, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(min_denormal, min_denormal));
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(min_denormal, max_denormal));
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(max_denormal, min_denormal));
+  EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::atan2(max_denormal, max_denormal));
+}
+
+#endif
diff --git a/libc/test/src/math/smoke/atanf_test.cpp b/libc/test/src/math/smoke/atanf_test.cpp
index 0fe11d79533810..346b8e8abd1991 100644
--- a/libc/test/src/math/smoke/atanf_test.cpp
+++ b/libc/test/src/math/smoke/atanf_test.cpp
@@ -42,3 +42,27 @@ TEST_F(LlvmLibcAtanfTest, SpecialNumbers) {
   // EXPECT_FP_EXCEPTION(0);
   EXPECT_MATH_ERRNO(0);
 }
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcAtanfTest, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atanf(min_denormal));
+}
+
+TEST_F(LlvmLibcAtanfTest, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atanf(min_denormal));
+}
+
+TEST_F(LlvmLibcAtanfTest, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atanf(min_denormal));
+}
+
+#endif
diff --git a/libc/test/src/math/smoke/atanhf_test.cpp b/libc/test/src/math/smoke/atanhf_test.cpp
index e22926bd2f0376..8300b47ea9a315 100644
--- a/libc/test/src/math/smoke/atanhf_test.cpp
+++ b/libc/test/src/math/smoke/atanhf_test.cpp
@@ -76,3 +76,27 @@ TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) {
   EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::atanhf(neg_inf), FE_INVALID);
   EXPECT_MATH_ERRNO(EDOM);
 }
+
+#ifdef LIBC_TEST_FTZ_DAZ
+
+using namespace LIBC_NAMESPACE::testing;
+
+TEST_F(LlvmLibcAtanhfTest, FTZMode) {
+  ModifyMXCSR mxcsr(FTZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atanhf(min_denormal));
+}
+
+TEST_F(LlvmLibcAtanhfTest, DAZMode) {
+  ModifyMXCSR mxcsr(DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atanhf(min_denormal));
+}
+
+TEST_F(LlvmLibcAtanhfTest, FTZDAZMode) {
+  ModifyMXCSR mxcsr(FTZ | DAZ);
+
+  EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atanhf(min_denormal));
+}
+
+#endif
diff --git a/libc/test/src/math/smoke/cbrt_test.cpp b/libc/test/src/math/smoke/cbrt_test.cpp
index 724e0e979decc1..dfe23fed603de1 100644
--- a/libc/test/src/math/smoke/cbrt_test.cpp
+++ b/libc/test/src/math/smoke/cbrt_test.cpp
@@ -33,3 +33,30 @@ TEST_F(LlvmLibcCbrtTest, SpecialNumbers) {
   EXPECT_FP_EQ_ALL_ROUNDING(0x1.0p341, LIBC_NAMESPACE::cbrt(0x1.0p1023));
   EXPECT_FP_EQ_ALL_R...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/113744


More information about the libc-commits mailing list