@@ -652,42 +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
- // see also https://github.com/rust-lang/rust/issues/114479
666
- if self . is_infinite ( ) {
667
- // A value may compare unequal to infinity, despite having a "full" exponent mask.
668
- FpCategory :: Infinite
669
- } else if self . is_nan ( ) {
670
- // And it may not be NaN, as it can simply be an "overextended" finite value.
671
- FpCategory :: Nan
672
- } else {
673
- // However, std can't simply compare to zero to check for zero, either,
674
- // as correctness requires avoiding equality tests that may be Subnormal == -0.0
675
- // because it may be wrong under "denormals are zero" and "flush to zero" modes.
676
- // Most of std's targets don't use those, but they are used for thumbv7neon.
677
- // So, this does use bitpattern matching for the rest. On x87, due to the incorrect
678
- // float codegen on this hardware, this doesn't actually return a right answer for NaN
679
- // because it cannot correctly discern between a floating point NaN, and some normal
680
- // floating point numbers truncated from an x87 FPU -- but we took care of NaN above, so
681
- // we are fine.
682
- // FIXME(jubilee): This probably could at least answer things correctly for Infinity,
683
- // like the f64 version does, but I need to run more checks on how things go on x86.
684
- // I fear losing mantissa data that would have answered that differently.
685
- let b = self . to_bits ( ) ;
686
- match ( b & Self :: MAN_MASK , b & Self :: EXP_MASK ) {
687
- ( 0 , 0 ) => FpCategory :: Zero ,
688
- ( _, 0 ) => FpCategory :: Subnormal ,
689
- _ => FpCategory :: Normal ,
690
- }
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 ,
691
667
}
692
668
}
693
669
0 commit comments