Skip to content

[libc][math][c23] Fix X86_Binary80 special cases for canonicalize functions. #86924

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

Merged
merged 5 commits into from
Mar 28, 2024

Conversation

Sh0g0-1758
Copy link
Member

Updates the special case of pseudo infinty as pointed in #85940

@llvmbot llvmbot added the libc label Mar 28, 2024
@Sh0g0-1758
Copy link
Member Author

cc: @jcranmer-intel

@llvmbot
Copy link
Member

llvmbot commented Mar 28, 2024

@llvm/pr-subscribers-libc

Author: Shourya Goel (Sh0g0-1758)

Changes

Updates the special case of pseudo infinty as pointed in #85940


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

2 Files Affected:

  • (modified) libc/src/__support/FPUtil/BasicOperations.h (+6-4)
  • (modified) libc/test/src/math/smoke/CanonicalizeTest.h (+3-3)
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index a47931bb33900a..bdb91a98a0d357 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -185,7 +185,7 @@ 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 |
@@ -199,9 +199,11 @@ LIBC_INLINE int canonicalize(T &cx, const T &x) {
     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;
+        } else {
           cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val();
           raise_except_if_required(FE_INVALID);
           return 1;
diff --git a/libc/test/src/math/smoke/CanonicalizeTest.h b/libc/test/src/math/smoke/CanonicalizeTest.h
index c8af83f1983881..1891d47922cf88 100644
--- a/libc/test/src/math/smoke/CanonicalizeTest.h
+++ b/libc/test/src/math/smoke/CanonicalizeTest.h
@@ -55,12 +55,12 @@ 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
+      // All Ones   |     00     |    Zero   | Pseudo Infinity, Value = SNaN
 
       FPBits test1((UInt128(0x7FFF) << 64) + UInt128(0x0000000000000000));
       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 |

@lntue lntue requested a review from jcranmer-intel March 28, 2024 14:07
@nickdesaulniers
Copy link
Member

Do we only need to do this for x86 or all targets?

Copy link
Contributor

@jcranmer-intel jcranmer-intel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnormals also need changing.

@lntue lntue changed the title [libc][math][c23] Fix X86_80 Special Case [libc][math][c23] Fix x86_80 special cases for canonicalize functions. Mar 28, 2024
@lntue lntue changed the title [libc][math][c23] Fix x86_80 special cases for canonicalize functions. [libc][math][c23] Fix X86_Binary80 special cases for canonicalize functions. Mar 28, 2024
Formatter
@Sh0g0-1758
Copy link
Member Author

@nickdesaulniers, I don't think I follow you. Rest of the targets are already in canonical form, no?

@jcranmer-intel, updated Unnormal too, now they return a qNAN with FE_INVALID

@Sh0g0-1758
Copy link
Member Author

Fixed tests. Ran into a rather interesting observation. Why is that

A = (UInt128(0x0000) << 64) + UInt128(0x8000000000000000)
B = (UInt128(0x0001) << 64) + UInt128(0x8000000000000000)

Both have a get_biased_exponent() value of 1 ?

@lntue
Copy link
Contributor

lntue commented Mar 28, 2024

Fixed tests. Ran into a rather interesting observation. Why is that

A = (UInt128(0x0000) << 64) + UInt128(0x8000000000000000)
B = (UInt128(0x0001) << 64) + UInt128(0x8000000000000000)

Both have a get_biased_exponent() value of 1 ?

get_biased_exponent follows the IEEE 754 convention, and is used to compute the real values of the bit patterns. So once you added a hidden bit to your mantissa, the real value is simply

  2^(get_biased_exponent() - EXPONENT_BIAS) * m.

Another way to think about it is that:

  2^(get_biased_exponent() - EXPONENT_BIAS - FRACTION_LEN) is the value of the least significant bit.

@Sh0g0-1758
Copy link
Member Author

Sh0g0-1758 commented Mar 28, 2024

Fixed tests. Ran into a rather interesting observation. Why is that

A = (UInt128(0x0000) << 64) + UInt128(0x8000000000000000)
B = (UInt128(0x0001) << 64) + UInt128(0x8000000000000000)

Both have a get_biased_exponent() value of 1 ?

get_biased_exponent follows the IEEE 754 convention, and is used to compute the real values of the bit patterns. So once you added a hidden bit to your mantissa, the real value is simply

  2^(get_biased_exponent() - EXPONENT_BIAS) * m.

Another way to think about it is that:

  2^(get_biased_exponent() - EXPONENT_BIAS - FRACTION_LEN) is the value of the least significant bit.

Thanks for the explanation. Actually replacing the tests with _u128 strings gave me added clarity as I played around with the bits a lot while locally testing. Thanks for the suggestion.

@jcranmer-intel
Copy link
Contributor

The logic here looks correct now to me; I'll leave it to the libc maintainers to make other commentary on the code.

@lntue lntue merged commit 7c1c07c into llvm:main Mar 28, 2024
@nickdesaulniers
Copy link
Member

@nickdesaulniers
Copy link
Member

nickdesaulniers commented Mar 28, 2024

Sorry, it's not clear to me why this is failing. I've reverted it for now in d357324.

Fails in presubmit.

Should have been "postsubmit." Oops.

@lntue
Copy link
Contributor

lntue commented Mar 28, 2024

I ran it with -DLLVM_USE_SANITIZER=Undefined and got:

[ RUN      ] LlvmLibcCanonicalizeTest.X64_80SpecialNumbers
/usr/local/google/home/lntue/experiment/llvm/llvm-project/libc/src/__support/integer_literals.h:102:7: runtime error: execution reached an unreachable program point
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/local/google/home/lntue/experiment/llvm/llvm-project/libc/src/__support/integer_literals.h:102:7 in 

https://github.com/llvm/llvm-project/blob/main/libc/src/__support/integer_literals.h#L102

@lntue
Copy link
Contributor

lntue commented Mar 28, 2024

I think it is because the first groups of your uint128 literals have more than 8 0's on L70,75,80,85.

@Sh0g0-1758
Copy link
Member Author

@nickdesaulniers, as pointed out by @intue, the error was caused by an extra 0 in the tests. I have linked a patch for it. Please land the changes on main so that the patch can land.

@nickdesaulniers
Copy link
Member

No, we don't reland broken changes in main in llvm-project. Add a revert of d357324 in your PR #87016 first, with the fix either as a distinct reviewer which is squashed when merging (a nice touch for reviewers to see what's new in the reland), or just have 1 commit which is this PR + the fixup squashed (less easy for reviewers to see what's different).

@Sh0g0-1758
Copy link
Member Author

@nickdesaulniers, to avoid mutch hassle, I have opened a fresh PR with the changes from this PR and the updated test cases.

Sh0g0-1758 added a commit to Sh0g0-1758/llvm-project 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.

5 participants