-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Constant propagate int-to-float conversions (#7915)
This commit is born out of a fuzz bug on x64 that was discovered recently. Today, on `main`, and in the 17.0.1 release Wasmtime will panic when compiling this wasm module for x64: (module (func (result v128) i32.const 0 i32x4.splat f64x2.convert_low_i32x4_u)) panicking with: thread '<unnamed>' panicked at /home/alex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.104.1/src/machinst/lower.rs:766:21: should be implemented in ISLE: inst = `v6 = fcvt_from_uint.f64x2 v13 ; v13 = const0`, type = `Some(types::F64X2)` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Bisections points to the "cause" of this regression as #7859 which more-or-less means that this has always been an issue and that PR just happened to expose the issue. What's happening here is that egraph optimizations are turning the IR into a form that the x64 backend can't codegen. Namely there's no general purpose lowering of i64x2 being converted to f64x2. The Wasm frontend never produces this but the optimizations internally end up producing this. Notably here the result of this function is constant and what's happening is that a convert-of-a-splat is happening. In lieu of adding the full general lowering to x64 (which is perhaps overdue since this is the second or third time this panic has been triggered) I've opted to add constant propagation optimizations for int-to-float conversions. These are all based on the Rust `as` operator which has the same semantics as Cranelift. This is enough to fix the issue here for the time being.
- Loading branch information
1 parent
e7ab3a4
commit 8a2d9bc
Showing
5 changed files
with
279 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
222 changes: 222 additions & 0 deletions
222
cranelift/filetests/filetests/egraph/fcvt-from-int.clif
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
test optimize | ||
set opt_level=speed | ||
target x86_64 | ||
target aarch64 | ||
target s390x | ||
target riscv64 | ||
|
||
function %i32_0_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i32 0 | ||
v1 = fcvt_from_sint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %i32_neg1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i32 -1 | ||
v1 = fcvt_from_sint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const -0x1.000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %i32_1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i32 1 | ||
v1 = fcvt_from_sint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0x1.000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %u32_0_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i32 0 | ||
v1 = fcvt_from_uint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %u32_neg1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i32 -1 | ||
v1 = fcvt_from_uint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0x1.000000p32 | ||
; check: return v2 | ||
} | ||
|
||
function %u32_1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i32 1 | ||
v1 = fcvt_from_uint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0x1.000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %i32_0_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i32 0 | ||
v1 = fcvt_from_sint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %i32_neg1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i32 -1 | ||
v1 = fcvt_from_sint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const -0x1.0000000000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %i32_1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i32 1 | ||
v1 = fcvt_from_sint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0x1.0000000000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %u32_0_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i32 0 | ||
v1 = fcvt_from_uint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %u32_neg1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i32 -1 | ||
v1 = fcvt_from_uint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0x1.fffffffe00000p31 | ||
; check: return v2 | ||
} | ||
|
||
function %u32_1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i32 1 | ||
v1 = fcvt_from_uint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0x1.0000000000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %i64_0_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i64 0 | ||
v1 = fcvt_from_sint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %i64_neg1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i64 -1 | ||
v1 = fcvt_from_sint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const -0x1.000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %i64_1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i64 1 | ||
v1 = fcvt_from_sint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0x1.000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %u64_0_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i64 0 | ||
v1 = fcvt_from_uint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %u64_neg1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i64 -1 | ||
v1 = fcvt_from_uint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0x1.000000p64 | ||
; check: return v2 | ||
} | ||
|
||
function %u64_1_to_f32() -> f32 { | ||
block0: | ||
v0 = iconst.i64 1 | ||
v1 = fcvt_from_uint.f32 v0 | ||
return v1 | ||
; check: v2 = f32const 0x1.000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %i64_0_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i64 0 | ||
v1 = fcvt_from_sint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %i64_neg1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i64 -1 | ||
v1 = fcvt_from_sint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const -0x1.0000000000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %i64_1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i64 1 | ||
v1 = fcvt_from_sint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0x1.0000000000000p0 | ||
; check: return v2 | ||
} | ||
|
||
function %u64_0_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i64 0 | ||
v1 = fcvt_from_uint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0.0 | ||
; check: return v2 | ||
} | ||
|
||
function %u64_neg1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i64 -1 | ||
v1 = fcvt_from_uint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0x1.0000000000000p64 | ||
; check: return v2 | ||
} | ||
|
||
function %u64_1_to_f64() -> f64 { | ||
block0: | ||
v0 = iconst.i64 1 | ||
v1 = fcvt_from_uint.f64 v0 | ||
return v1 | ||
; check: v2 = f64const 0x1.0000000000000p0 | ||
; check: return v2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
(module | ||
(func (param i32) (result v128) | ||
local.get 0 | ||
i32x4.splat | ||
f64x2.convert_low_i32x4_u | ||
) | ||
) | ||
|
||
(module | ||
(func (result v128) | ||
i32.const 0 | ||
i32x4.splat | ||
f64x2.convert_low_i32x4_u | ||
) | ||
) |