Skip to content

[libc][math][c23] Fix impl and tests for X86_80 canonicalize function. #87097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

Sh0g0-1758
Copy link
Member

In continutation to: #86924

@llvmbot llvmbot added the libc label Mar 29, 2024
@llvmbot
Copy link
Member

llvmbot commented Mar 29, 2024

@llvm/pr-subscribers-libc

Author: Shourya Goel (Sh0g0-1758)

Changes

In continutation to: #86924


Full diff: https://github.com/llvm/llvm-project/pull/87097.diff

3 Files Affected:

  • (modified) libc/src/__support/FPUtil/BasicOperations.h (+13-10)
  • (modified) libc/test/src/math/smoke/CMakeLists.txt (+4)
  • (modified) libc/test/src/math/smoke/CanonicalizeTest.h (+39-48)
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index a47931bb33900a..04a30f53d576de 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -185,27 +185,28 @@ LIBC_INLINE int canonicalize(T &cx, const T &x) {
     // More precisely :
     // Exponent   |       Significand      | Meaning
     //            | Bits 63-62 | Bits 61-0 |
-    // All Ones   |     00     |    Zero   | Pseudo Infinity, Value = Infinty
+    // All Ones   |     00     |    Zero   | Pseudo Infinity, Value = SNaN
     // All Ones   |     00     |  Non-Zero | Pseudo NaN, Value = SNaN
     // All Ones   |     01     | Anything  | Pseudo NaN, Value = SNaN
     //            |   Bit 63   | Bits 62-0 |
     // All zeroes |   One      | Anything  | Pseudo Denormal, Value =
-    //            |            |           | (−1)**s × m × 2**−16382
-    // All Other  |   Zero     | Anything  | Unnormal, Value =
-    //  Values    |            |           | (−1)**s × m × 2**−16382
+    //            |            |           | (−1)*s × m × 2*−16382
+    // All Other  |   Zero     | Anything  | Unnormal, Value = SNaN
+    //  Values    |            |           |
     bool bit63 = sx.get_implicit_bit();
     UInt128 mantissa = sx.get_explicit_mantissa();
     bool bit62 = static_cast<bool>((mantissa & (1ULL << 62)) >> 62);
     int exponent = sx.get_biased_exponent();
     if (exponent == 0x7FFF) {
       if (!bit63 && !bit62) {
-        if (mantissa == 0)
-          cx = FPBits<T>::inf(sx.sign()).get_val();
-        else {
+        if (mantissa == 0) {
           cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val();
           raise_except_if_required(FE_INVALID);
           return 1;
         }
+        cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val();
+        raise_except_if_required(FE_INVALID);
+        return 1;
       } else if (!bit63 && bit62) {
         cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val();
         raise_except_if_required(FE_INVALID);
@@ -219,9 +220,11 @@ LIBC_INLINE int canonicalize(T &cx, const T &x) {
         cx = x;
     } else if (exponent == 0 && bit63)
       cx = FPBits<T>::make_value(mantissa, 0).get_val();
-    else if (exponent != 0 && !bit63)
-      cx = FPBits<T>::make_value(mantissa, 0).get_val();
-    else if (LIBC_UNLIKELY(sx.is_signaling_nan())) {
+    else if (exponent != 0 && !bit63) {
+      cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val();
+      raise_except_if_required(FE_INVALID);
+      return 1;
+    } else if (LIBC_UNLIKELY(sx.is_signaling_nan())) {
       cx =
           FPBits<T>::quiet_nan(sx.sign(), sx.get_explicit_mantissa()).get_val();
       raise_except_if_required(FE_INVALID);
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 3b756127fe21ea..ae2cbad7d5a7d9 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -178,6 +178,7 @@ add_fp_unittest(
     libc.src.math.canonicalize
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.integer_literals
 )
 
 add_fp_unittest(
@@ -193,6 +194,7 @@ add_fp_unittest(
     libc.src.math.canonicalizef
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.integer_literals
 )
 
 add_fp_unittest(
@@ -208,6 +210,7 @@ add_fp_unittest(
     libc.src.math.canonicalizef128
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.integer_literals
 )
 
 add_fp_unittest(
@@ -223,6 +226,7 @@ add_fp_unittest(
     libc.src.math.canonicalizel
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.integer_literals
 )
 
 add_fp_unittest(
diff --git a/libc/test/src/math/smoke/CanonicalizeTest.h b/libc/test/src/math/smoke/CanonicalizeTest.h
index c8af83f1983881..933d44d2718f9b 100644
--- a/libc/test/src/math/smoke/CanonicalizeTest.h
+++ b/libc/test/src/math/smoke/CanonicalizeTest.h
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_TEST_SRC_MATH_SMOKE_CANONICALIZETEST_H
 
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/integer_literals.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
@@ -22,6 +23,8 @@
 
 #define TEST_REGULAR(x, y, expected) TEST_SPECIAL(x, y, expected, 0)
 
+using LIBC_NAMESPACE::operator""_u128;
+
 template <typename T>
 class CanonicalizeTest : public LIBC_NAMESPACE::testing::Test {
 
@@ -55,33 +58,31 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::Test {
       T cx;
       // Exponent   |       Significand      | Meaning
       //            | Bits 63-62 | Bits 61-0 |
-      // All Ones   |     00     |    Zero   | Pseudo Infinity, Value = Infinty
-
-      FPBits test1((UInt128(0x7FFF) << 64) + UInt128(0x0000000000000000));
+      // All Ones   |     00     |    Zero   | Pseudo Infinity, Value = SNaN
+      FPBits test1(0x00000000'00007FFF'00000000'00000000_u128);
       const T test1_val = test1.get_val();
-      TEST_SPECIAL(cx, test1_val, 0, 0);
-      EXPECT_FP_EQ(cx, inf);
+      TEST_SPECIAL(cx, test1_val, 1, FE_INVALID);
+      EXPECT_FP_EQ(cx, aNaN);
 
       // Exponent   |       Significand      | Meaning
       //            | Bits 63-62 | Bits 61-0 |
       // All Ones   |     00     |  Non-Zero | Pseudo NaN, Value = SNaN
-
-      FPBits test2_1((UInt128(0x7FFF) << 64) + UInt128(0x0000000000000001));
+      FPBits test2_1(0x00000000'00007FFF'00000000'00000001_u128);
       const T test2_1_val = test2_1.get_val();
       TEST_SPECIAL(cx, test2_1_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test2_2((UInt128(0x7FFF) << 64) + UInt128(0x0000004270000001));
+      FPBits test2_2(0x00000000'00007FFF'00000042'70000001_u128);
       const T test2_2_val = test2_2.get_val();
       TEST_SPECIAL(cx, test2_2_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test2_3((UInt128(0x7FFF) << 64) + UInt128(0x0000000008261001));
+      FPBits test2_3(0x00000000'00007FFF'00000000'08261001_u128);
       const T test2_3_val = test2_3.get_val();
       TEST_SPECIAL(cx, test2_3_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test2_4((UInt128(0x7FFF) << 64) + UInt128(0x0000780008261001));
+      FPBits test2_4(0x00000000'00007FFF'00007800'08261001_u128);
       const T test2_4_val = test2_4.get_val();
       TEST_SPECIAL(cx, test2_4_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
@@ -89,23 +90,22 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::Test {
       // Exponent   |       Significand      | Meaning
       //            | Bits 63-62 | Bits 61-0 |
       // All Ones   |     01     | Anything  | Pseudo NaN, Value = SNaN
-
-      FPBits test3_1((UInt128(0x7FFF) << 64) + UInt128(0x4000000000000000));
+      FPBits test3_1(0x00000000'00007FFF'40000000'00000000_u128);
       const T test3_1_val = test3_1.get_val();
       TEST_SPECIAL(cx, test3_1_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test3_2((UInt128(0x7FFF) << 64) + UInt128(0x4000004270000001));
+      FPBits test3_2(0x00000000'00007FFF'40000042'70000001_u128);
       const T test3_2_val = test3_2.get_val();
       TEST_SPECIAL(cx, test3_2_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test3_3((UInt128(0x7FFF) << 64) + UInt128(0x4000000008261001));
+      FPBits test3_3(0x00000000'00007FFF'40000000'08261001_u128);
       const T test3_3_val = test3_3.get_val();
       TEST_SPECIAL(cx, test3_3_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test3_4((UInt128(0x7FFF) << 64) + UInt128(0x4007800008261001));
+      FPBits test3_4(0x00000000'00007FFF'40007800'08261001_u128);
       const T test3_4_val = test3_4.get_val();
       TEST_SPECIAL(cx, test3_4_val, 1, FE_INVALID);
       EXPECT_FP_EQ(cx, aNaN);
@@ -113,21 +113,19 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::Test {
       // Exponent   |       Significand      | Meaning
       //            |   Bit 63   | Bits 62-0 |
       // All zeroes |   One      | Anything  | Pseudo Denormal, Value =
-      //            |            |           | (−1)**s × m × 2**−16382
-
-      FPBits test4_1((UInt128(0x0000) << 64) + UInt128(0x8000000000000000));
+      //            |            |           | (−1)*s × m × 2*−16382
+      FPBits test4_1(0x00000000'00000000'80000000'00000000_u128);
       const T test4_1_val = test4_1.get_val();
       TEST_SPECIAL(cx, test4_1_val, 0, 0);
       EXPECT_FP_EQ(
           cx, FPBits::make_value(test4_1.get_explicit_mantissa(), 0).get_val());
 
-      FPBits test4_2((UInt128(0x0000) << 64) + UInt128(0x8000004270000001));
+      FPBits test4_2(0x00000000'00000000'80000042'70000001_u128);
       const T test4_2_val = test4_2.get_val();
       TEST_SPECIAL(cx, test4_2_val, 0, 0);
       EXPECT_FP_EQ(
           cx, FPBits::make_value(test4_2.get_explicit_mantissa(), 0).get_val());
-
-      FPBits test4_3((UInt128(0x0000) << 64) + UInt128(0x8000000008261001));
+      FPBits test4_3(0x00000000'00000000'80000000'08261001_u128);
       const T test4_3_val = test4_3.get_val();
       TEST_SPECIAL(cx, test4_3_val, 0, 0);
       EXPECT_FP_EQ(
@@ -135,44 +133,37 @@ class CanonicalizeTest : public LIBC_NAMESPACE::testing::Test {
 
       // Exponent   |       Significand      | Meaning
       //            |   Bit 63   | Bits 62-0 |
-      // All Other  |   Zero     | Anything  | Unnormal, Value =
-      //  Values    |            |           | (−1)**s × m × 2**−16382
-
-      FPBits test5_1(UInt128(0x0000000000000001));
+      // All Other  |   Zero     | Anything  | Unnormal, Value = SNaN
+      //  Values    |            |           |
+      FPBits test5_1(0x00000000'00000040'00000000'00000001_u128);
       const T test5_1_val = test5_1.get_val();
-      TEST_SPECIAL(cx, test5_1_val, 0, 0);
-      EXPECT_FP_EQ(
-          cx, FPBits::make_value(test5_1.get_explicit_mantissa(), 0).get_val());
+      TEST_SPECIAL(cx, test5_1_val, 1, FE_INVALID);
+      EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test5_2(UInt128(0x0000004270000001));
+      FPBits test5_2(0x00000000'00000230'00000042'70000001_u128);
       const T test5_2_val = test5_2.get_val();
-      TEST_SPECIAL(cx, test5_2_val, 0, 0);
-      EXPECT_FP_EQ(
-          cx, FPBits::make_value(test5_2.get_explicit_mantissa(), 0).get_val());
+      TEST_SPECIAL(cx, test5_2_val, 1, FE_INVALID);
+      EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test5_3(UInt128(0x0000000008261001));
+      FPBits test5_3(0x00000000'00000560'00000000'08261001_u128);
       const T test5_3_val = test5_3.get_val();
-      TEST_SPECIAL(cx, test5_3_val, 0, 0);
-      EXPECT_FP_EQ(
-          cx, FPBits::make_value(test5_3.get_explicit_mantissa(), 0).get_val());
+      TEST_SPECIAL(cx, test5_3_val, 1, FE_INVALID);
+      EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test5_4(UInt128(0x0000002816000000));
+      FPBits test5_4(0x00000000'00000780'00000028'16000000_u128);
       const T test5_4_val = test5_4.get_val();
-      TEST_SPECIAL(cx, test5_4_val, 0, 0);
-      EXPECT_FP_EQ(
-          cx, FPBits::make_value(test5_4.get_explicit_mantissa(), 0).get_val());
+      TEST_SPECIAL(cx, test5_4_val, 1, FE_INVALID);
+      EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test5_5(UInt128(0x0000004270000001));
+      FPBits test5_5(0x00000000'00000900'00000042'70000001_u128);
       const T test5_5_val = test5_5.get_val();
-      TEST_SPECIAL(cx, test5_5_val, 0, 0);
-      EXPECT_FP_EQ(
-          cx, FPBits::make_value(test5_5.get_explicit_mantissa(), 0).get_val());
+      TEST_SPECIAL(cx, test5_5_val, 1, FE_INVALID);
+      EXPECT_FP_EQ(cx, aNaN);
 
-      FPBits test5_6(UInt128(0x0000000008261001));
+      FPBits test5_6(0x00000000'00000AB0'00000000'08261001_u128);
       const T test5_6_val = test5_6.get_val();
-      TEST_SPECIAL(cx, test5_6_val, 0, 0);
-      EXPECT_FP_EQ(
-          cx, FPBits::make_value(test5_6.get_explicit_mantissa(), 0).get_val());
+      TEST_SPECIAL(cx, test5_6_val, 1, FE_INVALID);
+      EXPECT_FP_EQ(cx, aNaN);
     }
   }
 

@Sh0g0-1758
Copy link
Member Author

@nickdesaulniers

@nickdesaulniers
Copy link
Member

Here's how I would fix this up locally; the "git-fu" can be tricky.

$ cd llvm-project/
$ git checkout main
$ git pull
$ git checkout -b X86_80
$ git revert d357324f7700188c9ef179a4bc7898079cf49b6f
$ git cherry-pick 1237900e44643b34833b05403ccef2eeee5f6234
$ git cherry-pick 5c30985389d7eac3f334554feb4a4bf3c34824c5
$ git cherry-pick 6ed0c6fa7bdcd4bfc7b7c2cee7dc7bf9e9cde138
$ gh pr create

That way in one PR (which can be squashed when merged) we have the revert followed by the fixes. This makes it crystal clear to reviewers that the initial commit is just the inverse of the previous revert, and that the subsequent changes are the fixes. Reviewers can look at the individual commits in github code review.

@Sh0g0-1758
Copy link
Member Author

@nickdesaulniers, closing this. Raised a PR that correctly tracks the revert and changes. I went for the second option as prescribed by you in the original message because I was unsure as to how to do the former.

@Sh0g0-1758 Sh0g0-1758 closed this Mar 29, 2024
lntue pushed a commit that referenced this pull request Mar 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants