about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2022-03-25 19:17:19 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2022-03-25 19:32:14 +0100
commitf3d97cce279fd2372aafec3761791b4110d70bf5 (patch)
tree00101f6e59b07d1b0d8605b5123ece3c82b2da60
parente336e1bccf3831097283469243b0228accea85d4 (diff)
downloadrust-f3d97cce279fd2372aafec3761791b4110d70bf5.tar.gz
rust-f3d97cce279fd2372aafec3761791b4110d70bf5.zip
Fix saturating float casts test
Fixes #737
-rw-r--r--example/std_example.rs6
-rwxr-xr-xscripts/test_rustc_tests.sh1
-rw-r--r--src/cast.rs29
3 files changed, 26 insertions, 10 deletions
diff --git a/example/std_example.rs b/example/std_example.rs
index 5bc51a541b5..0a2bce2621d 100644
--- a/example/std_example.rs
+++ b/example/std_example.rs
@@ -1,7 +1,8 @@
-#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
+#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)]
 
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
+use std::hint::black_box;
 use std::io::Write;
 use std::ops::Generator;
 
@@ -86,6 +87,9 @@ fn main() {
     assert_eq!(houndred_f64 as i128, 100);
     assert_eq!(1u128.rotate_left(2), 4);
 
+    assert_eq!(black_box(f32::NAN) as i128, 0);
+    assert_eq!(black_box(f32::NAN) as u128, 0);
+
     // Test signed 128bit comparing
     let max = usize::MAX as i128;
     if 100i128 < 0i128 || 100i128 > max {
diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh
index f03a921d6a3..5f47e7204ea 100755
--- a/scripts/test_rustc_tests.sh
+++ b/scripts/test_rustc_tests.sh
@@ -79,7 +79,6 @@ rm src/test/ui/abi/stack-protector.rs # requires stack protector support
 
 # giving different but possibly correct results
 # =============================================
-rm src/test/ui/numbers-arithmetic/saturating-float-casts.rs # intrinsic gives different but valid result
 rm src/test/ui/simd/intrinsic/float-minmax-pass.rs # same
 rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
 rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
diff --git a/src/cast.rs b/src/cast.rs
index e7e6afeb865..e19070774c6 100644
--- a/src/cast.rs
+++ b/src/cast.rs
@@ -84,7 +84,7 @@ pub(crate) fn clif_int_or_float_cast(
             fx.bcx.ins().fcvt_from_uint(to_ty, from)
         }
     } else if from_ty.is_float() && to_ty.is_int() {
-        if to_ty == types::I128 {
+        let val = if to_ty == types::I128 {
             // _____sssf___
             // __fix   sfti: f32 -> i128
             // __fix   dfti: f64 -> i128
@@ -109,13 +109,9 @@ pub(crate) fn clif_int_or_float_cast(
 
             let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
 
-            return fx
-                .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
-                .load_scalar(fx);
-        }
-
-        // float -> int-like
-        if to_ty == types::I8 || to_ty == types::I16 {
+            fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
+                .load_scalar(fx)
+        } else if to_ty == types::I8 || to_ty == types::I16 {
             // FIXME implement fcvt_to_*int_sat.i8/i16
             let val = if to_signed {
                 fx.bcx.ins().fcvt_to_sint_sat(types::I32, from)
@@ -146,6 +142,23 @@ pub(crate) fn clif_int_or_float_cast(
             fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
         } else {
             fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
+        };
+
+        if let Some(false) = fx.tcx.sess.opts.debugging_opts.saturating_float_casts {
+            return val;
+        }
+
+        let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
+        if to_ty == types::I128 {
+            // FIXME(bytecodealliance/wasmtime#3963): select.i128 on fcmp eq miscompiles
+            let (lsb, msb) = fx.bcx.ins().isplit(val);
+            let zero = fx.bcx.ins().iconst(types::I64, 0);
+            let lsb = fx.bcx.ins().select(is_not_nan, lsb, zero);
+            let msb = fx.bcx.ins().select(is_not_nan, msb, zero);
+            fx.bcx.ins().iconcat(lsb, msb)
+        } else {
+            let zero = fx.bcx.ins().iconst(to_ty, 0);
+            fx.bcx.ins().select(is_not_nan, val, zero)
         }
     } else if from_ty.is_float() && to_ty.is_float() {
         // float -> float