Skip to content

Commit c8f15a7

Browse files
committed
Cranelift: apply NaN canonicalization to libcalls
This probably doesn't matter much in the real world, since the libcalls are only emitted on pre-SSE4.1 x64, and hence on CPUs released before 2007 (Intel) and 2011 (AMD). It does trip up the fuzzer though, since the libcalls are interpreted differently between Pulley and Cranelift. Alternatively, we could make SSE4.1 a requirement and remove the libcalls entirely: they're unused on all other platforms.
1 parent 122ddc7 commit c8f15a7

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

cranelift/codegen/src/nan_canonicalization.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ pub fn do_nan_canonicalization(func: &mut Function, has_vector_support: bool) {
2626
/// Returns true/false based on whether the instruction is a floating-point
2727
/// arithmetic operation. This ignores operations like `fneg`, `fabs`, or
2828
/// `fcopysign` that only operate on the sign bit of a floating point value.
29+
///
30+
/// Also matches `call` and `call_indirect` instructions that return a single
31+
/// floating-point result, since external function calls (e.g. libcalls like
32+
/// `%CeilF32`) can also produce nondeterministic NaN payloads.
2933
fn is_fp_arith(pos: &mut FuncCursor, inst: Inst) -> bool {
3034
match pos.func.dfg.insts[inst] {
3135
InstructionData::Unary { opcode, .. } => {
@@ -48,6 +52,13 @@ fn is_fp_arith(pos: &mut FuncCursor, inst: Inst) -> bool {
4852
|| opcode == Opcode::Fsub
4953
}
5054
InstructionData::Ternary { opcode, .. } => opcode == Opcode::Fma,
55+
InstructionData::Call { .. } | InstructionData::CallIndirect { .. } => {
56+
let results = pos.func.dfg.inst_results(inst);
57+
results.len() == 1 && {
58+
let ty = pos.func.dfg.value_type(results[0]);
59+
ty.is_float() || ty == types::F32X4 || ty == types::F64X2
60+
}
61+
}
5162
_ => false,
5263
}
5364
}

0 commit comments

Comments
 (0)