@@ -652,42 +652,18 @@ impl f32 {
652652 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
653653 #[ rustc_const_unstable( feature = "const_float_classify" , issue = "72505" ) ]
654654 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 ,
691667 }
692668 }
693669
0 commit comments