@@ -652,45 +652,18 @@ impl f32 {
652
652
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
653
653
#[ rustc_const_unstable( feature = "const_float_classify" , issue = "72505" ) ]
654
654
pub const fn classify ( self ) -> FpCategory {
655
- // A previous implementation tried to only use bitmask-based checks,
656
- // using f32::to_bits to transmute the float to its bit repr and match on that.
657
- // If we only cared about being "technically" correct, that's an entirely legit
658
- // implementation.
659
- //
660
- // Unfortunately, there is hardware out there that does not correctly implement the IEEE
661
- // float semantics Rust relies on: x87 uses a too-large mantissa and exponent, and some
662
- // hardware flushes subnormals to zero. These are platforms bugs, and Rust will misbehave on
663
- // such hardware, but we can at least try to make things seem as sane as possible by being
664
- // careful here.
665
- //
666
- // FIXME(jubilee): Using x87 operations is never necessary in order to function
667
- // on x86 processors for Rust-to-Rust calls, so this issue should not happen.
668
- // Code generation should be adjusted to use non-C calling conventions, avoiding this.
669
- if self . is_infinite ( ) {
670
- // A value may compare unequal to infinity, despite having a "full" exponent mask.
671
- FpCategory :: Infinite
672
- } else if self . is_nan ( ) {
673
- // And it may not be NaN, as it can simply be an "overextended" finite value.
674
- FpCategory :: Nan
675
- } else {
676
- // However, std can't simply compare to zero to check for zero, either,
677
- // as correctness requires avoiding equality tests that may be Subnormal == -0.0
678
- // because it may be wrong under "denormals are zero" and "flush to zero" modes.
679
- // Most of std's targets don't use those, but they are used for thumbv7neon.
680
- // So, this does use bitpattern matching for the rest. On x87, due to the incorrect
681
- // float codegen on this hardware, this doesn't actually return a right answer for NaN
682
- // because it cannot correctly discern between a floating point NaN, and some normal
683
- // floating point numbers truncated from an x87 FPU -- but we took care of NaN above, so
684
- // we are fine.
685
- // FIXME(jubilee): This probably could at least answer things correctly for Infinity,
686
- // like the f64 version does, but I need to run more checks on how things go on x86.
687
- // I fear losing mantissa data that would have answered that differently.
688
- let b = self . to_bits ( ) ;
689
- match ( b & Self :: MAN_MASK , b & Self :: EXP_MASK ) {
690
- ( 0 , 0 ) => FpCategory :: Zero ,
691
- ( _, 0 ) => FpCategory :: Subnormal ,
692
- _ => FpCategory :: Normal ,
693
- }
655
+ // We used to have complicated logic here that avoids the simple bit-based tests to work
656
+ // around buggy codegen for x87 targets (see
657
+ // https://github.com/rust-lang/rust/issues/114479). However, some LLVM versions later, none
658
+ // of our tests is able to find any difference between the complicated and the naive
659
+ // version, so now we are back to the naive version.
660
+ let b = self . to_bits ( ) ;
661
+ match ( b & Self :: MAN_MASK , b & Self :: EXP_MASK ) {
662
+ ( 0 , Self :: EXP_MASK ) => FpCategory :: Infinite ,
663
+ ( _, Self :: EXP_MASK ) => FpCategory :: Nan ,
664
+ ( 0 , 0 ) => FpCategory :: Zero ,
665
+ ( _, 0 ) => FpCategory :: Subnormal ,
666
+ _ => FpCategory :: Normal ,
694
667
}
695
668
}
696
669
0 commit comments