Skip to content

Commit dd20eaf

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 dd20eaf

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

cranelift/codegen/src/nan_canonicalization.rs

Lines changed: 13 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,15 @@ 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()
60+
|| ty == types::F32X4
61+
|| ty == types::F64X2
62+
}
63+
}
5164
_ => false,
5265
}
5366
}

0 commit comments

Comments
 (0)