Skip to content

float to/from bits and classify: update for float semantics RFC - #128598

Merged
bors merged 3 commits into
rust-lang:masterfrom
RalfJung:float-comments
Aug 17, 2024
Merged

float to/from bits and classify: update for float semantics RFC#128598
bors merged 3 commits into
rust-lang:masterfrom
RalfJung:float-comments

Conversation

@RalfJung

@RalfJung RalfJung commented Aug 3, 2024

Copy link
Copy Markdown
Member

With rust-lang/rfcs#3514 having been accepted, it is clear that hardware which e.g. flushes subnormal to zero is just non-conformant from a Rust perspective -- this is a hardware bug, or maybe an LLVM backend bug (where LLVM doesn't lower floating-point ops in a way that they have the standardized behavior). So update the comments here to make it clear that we don't have to do any of this, we're just being nice.

Also remove the subnormal/NaN checks from the (unstable) const-version of to/from-bits; they are not needed since we decided with the aforementioned RFC that it is okay to get a different result at const-time and at run-time.

r? @workingjubilee since I think you wrote many of the comments I am editing here.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Aug 3, 2024
@rust-log-analyzer

This comment has been minimized.

@RalfJung

RalfJung commented Aug 3, 2024

Copy link
Copy Markdown
Member Author

@rust-lang/wg-const-eval this also makes it so that to_bits / from_bits in const will expose the bit pattern of NaNs (and subnormals). That matches the accepted float semantics RFC: the exposed bit pattern is guaranteed to be some NaN bit pattern, but which exact bit pattern one gets is not fixed. (These functions are still unstable, though they could be stabilized soon.)

@RalfJung RalfJung changed the title float to/from bits and classify: update comments regarding non-conformant hardware float to/from bits and classify: update for float semantics RFC Aug 3, 2024
@tgross35

tgross35 commented Aug 4, 2024

Copy link
Copy Markdown
Contributor

Would you be able to update f16 and f128 too? If you run into anything too weird there then I can do it separately after this merges.

( 5 files changed, 43 insertions(+), 394 deletions(-) love these kind of diffstats)

@RalfJung

RalfJung commented Aug 4, 2024

Copy link
Copy Markdown
Member Author

I'll wait for a review before doing that so that I don't have to do the same edits 4 times.

@tgross35 tgross35 added the A-floating-point Area: Floating point numbers and arithmetic label Aug 7, 2024

@workingjubilee workingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

cool, okay!

sorry for taking so long to review but I had to like... also go over the float rfc again with a fine-tooth comb.

Comment thread library/core/src/num/f32.rs Outdated

// Check that NaNs roundtrip their bits regardless of signalingness
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
// ...actually, let's just check that these break. :D

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hell yeah

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is not new code, I just moved it. ;)

Comment thread library/core/src/num/f64.rs Outdated
// implementation.
//
// Unfortunately, there is hardware out there that does not correctly implement the IEEE
// float semantics Rust relies on: x87 uses a too large exponent, and some hardware flushes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// float semantics Rust relies on: x87 uses a too large exponent, and some hardware flushes
// float semantics Rust relies on: x87 uses a too-large exponent, and some hardware flushes

@RalfJung
RalfJung force-pushed the float-comments branch 2 times, most recently from 1aed419 to 29232ca Compare August 15, 2024 12:22
@RalfJung

Copy link
Copy Markdown
Member Author

I have done the same edits for f16 and f128, and also replaced the transmutes in classify with to_bits now that that does not lead to recursion any more. The partial_classify functions I found really hard to explain and document separately so I inlined them into their only call site.

Comment thread library/core/src/num/f16.rs Outdated
// we are fine.
let b = self.to_bits();
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
(0, Self::EXP_MASK) => FpCategory::Infinite,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@tgross35 f16 is somewhat odd here -- it checks for infinity above and then again with the bitwise check here. That's different from f32, which only checks it separately, and f64, which only checks it via the bits. Isn't this arm here dead code because we already checked is_infinite above?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You are right, that is redundant - I don't think that was done with any specific intent.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I will follow what f32 does then since it seems closest to f16.

@RalfJung

RalfJung commented Aug 15, 2024

Copy link
Copy Markdown
Member Author

( 5 files changed, 43 insertions(+), 394 deletions(-) love these kind of diffstats)

Yeah same. :D
FWIW in principle we could delete a lot more code here and just always do bit-pattern classification. According to our own semantics, that is correct. The LLVM x86-non-SSE codegen path is just buggy (and unlikely to be fixed as nobody who knows how to fix it cares enough bout this target) and that's why we are carrying these work-arounds... and compiling code to instructions that flush subnormals is equally buggy.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@RalfJung
RalfJung force-pushed the float-comments branch 2 times, most recently from 9339bdb to eb5f421 Compare August 15, 2024 19:17

@workingjubilee workingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

sorry, only noticed this typo on this last scan.

Comment thread library/core/src/num/f32.rs Outdated
Comment thread library/core/src/num/f64.rs Outdated
Comment thread library/core/src/num/f16.rs Outdated
@RalfJung

Copy link
Copy Markdown
Member Author

Typo fixed :)

@workingjubilee

Copy link
Copy Markdown
Member

huzzah!

looks good.
@bors r+ rollup

@bors

bors commented Aug 16, 2024

Copy link
Copy Markdown
Collaborator

📌 Commit 368a4c6 has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 16, 2024
@bors

bors commented Aug 16, 2024

Copy link
Copy Markdown
Collaborator

📌 Commit 852b9dd has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 16, 2024
@RalfJung

Copy link
Copy Markdown
Member Author

@bors r=workingjubilee

@bors

bors commented Aug 16, 2024

Copy link
Copy Markdown
Collaborator

📌 Commit ec1cb80 has been approved by workingjubilee

It is now in the queue for this repository.

Comment on lines +83 to +88
const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
if !has_broken_floats() {
const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
if !has_broken_floats() {
const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
}
if !has_broken_floats() {
const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
}
const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);

As f64 has an even number of explicit significand bits, MASKED_NAN1 will be the signalling NaN.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's rename these to SIGNALING_NAN and QUIET_NAN shall we?

I am aware of the mips differentiation, you can comment on "according to IEEE754-2008" if you like.

@beetrees beetrees Aug 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The float semantics RFC states "Rust assumes that the quiet/signalling bit being set to 1 indicates a quiet NaN (QNaN), and a value of 0 indicates a signalling NaN (SNaN)." so it could also be "according to Rust's float semantics".

(As a side note, I don't think f{16,32,64,128}::NAN are explicitly documented as being quiet NaNs anywhere, although this has always been the case and is probably relied upon in practice. Now that the RFC has formally defined what Rust thinks a quiet NaN is, the documentation can probably be updated to guarantee that f{16,32,64,128}::NAN are quiet NaNs, although that's probably a task for a separate PR as it would technically make new stable guarantees.)

@tgross35

Copy link
Copy Markdown
Contributor

@bors r- per the above

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 16, 2024
@workingjubilee

Copy link
Copy Markdown
Member

thank you ecstatic-morse for explicitly documenting this test is about preserving bits for simple casts even in the signaling/quieted cases, you just saved me from making a very bad suggestion.

@workingjubilee workingjubilee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Like this, or so

Comment thread tests/ui/consts/const-float-bits-conv.rs Outdated
Comment thread tests/ui/consts/const-float-bits-conv.rs Outdated
Comment thread tests/ui/consts/const-float-bits-conv.rs Outdated
Comment thread tests/ui/consts/const-float-bits-conv.rs Outdated
RalfJung and others added 2 commits August 17, 2024 10:26
also fix typo in const-float-bits-conv
Co-authored-by: Jubilee <46493976+workingjubilee@users.noreply.github.com>
@RalfJung

Copy link
Copy Markdown
Member Author

@bors r=workingjubilee

@bors

bors commented Aug 17, 2024

Copy link
Copy Markdown
Collaborator

📌 Commit 5f33085 has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 17, 2024
@bors

bors commented Aug 17, 2024

Copy link
Copy Markdown
Collaborator

⌛ Testing commit 5f33085 with merge 426a60a...

@bors

bors commented Aug 17, 2024

Copy link
Copy Markdown
Collaborator

☀️ Test successful - checks-actions
Approved by: workingjubilee
Pushing 426a60a to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Aug 17, 2024
@bors
bors merged commit 426a60a into rust-lang:master Aug 17, 2024
@rustbot rustbot added this to the 1.82.0 milestone Aug 17, 2024
@RalfJung
RalfJung deleted the float-comments branch August 17, 2024 12:02
@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (426a60a): comparison URL.

Overall result: ❌ regressions - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
5.0% [5.0%, 5.0%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary -0.7%, secondary -2.3%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.3% [2.3%, 2.3%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.7% [-2.4%, -1.3%] 3
Improvements ✅
(secondary)
-2.3% [-2.3%, -2.3%] 1
All ❌✅ (primary) -0.7% [-2.4%, 2.3%] 4

Cycles

Results (secondary 2.5%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.5% [2.1%, 2.7%] 6
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Binary size

Results (primary 0.0%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.0% [0.0%, 0.0%] 3
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.1% [-0.1%, -0.1%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.0% [-0.1%, 0.0%] 4

Bootstrap: 749.331s -> 750.684s (0.18%)
Artifact size: 339.18 MiB -> 339.13 MiB (-0.01%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-floating-point Area: Floating point numbers and arithmetic merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants