Help Us Benchmark Saturating Float Casts!

Earlier today I was trying my hand at getting the run-pass test suite passing on wasm32-unknown-unknown, but alas I hit a failure in the saturating-float-casts.rs test! I believe that in wasm32 we’ll actually want to unconditionally turn on the saturating cast behavior because an out-of-bounds cast is actually a trap!

So the problem I’m seeing is that when executing the saturating-float-casts.rs test it’ll fail with integer result unrepresentable which I think means an out of bounds cast. I minimized the test to:

use std::f64;

#[inline(never)]                                    
fn bar<T>(t: T) -> T { t }                          
                                                    
#[no_mangle]                                        
pub fn foo() -> f64 {                               
    if bar(f64::INFINITY) as i8 != i8::max_value() {
        extern { fn exit(); }
        unsafe { exit(); }                          
    }                                               
    bar(f64::NEG_INFINITY)                          
}             

I couldn’t really quite follow the wasm IR, but I figured I could take a stab at the LLVM IR. So instead of a wasm target the IR here is generated for x86_64-unknown-linux-gnu with optimizations disabled

define double @foo() unnamed_addr #2 {                                         
start:                                                                         
  %_1 = alloca {}, align 1                                                     
; call wut::bar                                                                
  %0 = call double @_ZN3wut3bar17h434e9ad8e9a22fa7E(double 0x7FF0000000000000) 
  br label %bb1                                                                
                                                                               
bb1:                                              ; preds = %start             
  %1 = fptosi double %0 to i8                                                  

I think that this IR may not be correct? @hanna-kruppe correct me if I’m wrong though! According to LLVM’s documentation the fptosi instruction is undefined behavior if the source doesn’t fit in the destination, but in this case I think it’s unconditionally putting f64::INFINITY into the destination of i8? I think this is what’s causing a trap on wasm as that instruction generates a trap instead of doing anything else.

@hanna-kruppe is this expected behavior? Or maybe I’ve misdiagnosed? I can certainly open an issue with more details if that would help!

1 Like