* x64: Take SIGFPE signals for divide traps Prior to this commit Wasmtime would configure `avoid_div_traps=true` unconditionally for Cranelift. This, for the division-based instructions, would change emitted code to explicitly trap on trap conditions instead of letting the `div` x86 instruction trap. There's no specific reason for Wasmtime, however, to specifically avoid traps in the `div` instruction. This means that the extra generated branches on x86 aren't necessary since the `div` and `idiv` instructions already trap for similar conditions as wasm requires. This commit instead disables the `avoid_div_traps` setting for Wasmtime's usage of Cranelift. Subsequently the codegen rules were updated slightly: * When `avoid_div_traps=true`, traps are no longer emitted for `div` instructions. * The `udiv`/`urem` instructions now list their trap as divide-by-zero instead of integer overflow. * The lowering for `sdiv` was updated to still explicitly check for zero but the integer overflow case is deferred to the instruction itself. * The lowering of `srem` no longer checks for zero and the listed trap for the `div` instruction is a divide-by-zero. This means that the codegen for `udiv` and `urem` no longer have any branches. The codegen for `sdiv` removes one branch but keeps the zero-check to differentiate the two kinds of traps. The codegen for `srem` removes one branch but keeps the -1 check since the semantics of `srem` mismatch with the semantics of `idiv` with a -1 divisor (specifically for INT_MIN). This is unlikely to have really all that much of a speedup but was something I noticed during #6008 which seemed like it'd be good to clean up. Plus Wasmtime's signal handling was already set up to catch `SIGFPE`, it was just never firing. * Remove the `avoid_div_traps` cranelift setting With no known users currently removing this should be possible and helps simplify the x64 backend. * x64: GC more support for avoid_div_traps Remove the `validate_sdiv_divisor*` pseudo-instructions and clean up some of the ISLE rules now that `div` is allowed to itself trap unconditionally. * x64: Store div trap code in instruction itself * Keep divisors in registers, not in memory Don't accidentally fold multiple traps together * Handle EXC_ARITHMETIC on macos * Update emit tests * Update winch and tests
152 lines
3.7 KiB
Plaintext
152 lines
3.7 KiB
Plaintext
test interpret
|
|
test run
|
|
target aarch64
|
|
target s390x
|
|
target x86_64
|
|
target riscv64
|
|
|
|
function %srem_i64(i64, i64) -> i64 {
|
|
block0(v0: i64,v1: i64):
|
|
v2 = srem v0, v1
|
|
return v2
|
|
}
|
|
; run: %srem_i64(0, 1) == 0
|
|
; run: %srem_i64(2, 2) == 0
|
|
; run: %srem_i64(1, -1) == 0
|
|
; run: %srem_i64(3, 2) == 1
|
|
; run: %srem_i64(19, 7) == 5
|
|
; run: %srem_i64(3, -2) == 1
|
|
; run: %srem_i64(-19, 7) == -5
|
|
; run: %srem_i64(-57, -5) == -2
|
|
; run: %srem_i64(0, 104857600000) == 0
|
|
; run: %srem_i64(104857600000, 511) == 398
|
|
; run: %srem_i64(0xC0FFEEEE_DECAFFFF, 8) == -1
|
|
; run: %srem_i64(0xC0FFEEEE_DECAFFFF, -8) == -1
|
|
; run: %srem_i64(0x80000000_00000000, -2) == 0
|
|
|
|
function %srem_i32(i32, i32) -> i32 {
|
|
block0(v0: i32,v1: i32):
|
|
v2 = srem v0, v1
|
|
return v2
|
|
}
|
|
; run: %srem_i32(0, 1) == 0
|
|
; run: %srem_i32(2, 2) == 0
|
|
; run: %srem_i32(1, -1) == 0
|
|
; run: %srem_i32(3, 2) == 1
|
|
; run: %srem_i32(19, 7) == 5
|
|
; run: %srem_i32(3, -2) == 1
|
|
; run: %srem_i32(-19, 7) == -5
|
|
; run: %srem_i32(0, 13) == 0
|
|
; run: %srem_i32(1048576, 8192) == 0
|
|
; run: %srem_i32(-1024, 255) == -4
|
|
; run: %srem_i32(0xC0FFEEEE, 8) == -2
|
|
; run: %srem_i32(0xC0FFEEEE, -8) == -2
|
|
; run: %srem_i32(0x80000000, -2) == 0
|
|
|
|
function %srem_i16(i16, i16) -> i16 {
|
|
block0(v0: i16,v1: i16):
|
|
v2 = srem v0, v1
|
|
return v2
|
|
}
|
|
; run: %srem_i16(0, 1) == 0
|
|
; run: %srem_i16(2, 2) == 0
|
|
; run: %srem_i16(1, -1) == 0
|
|
; run: %srem_i16(3, 2) == 1
|
|
; run: %srem_i16(19, 7) == 5
|
|
; run: %srem_i16(3, -2) == 1
|
|
; run: %srem_i16(13, 5) == 3
|
|
; run: %srem_i16(0, 42) == 0
|
|
; run: %srem_i16(4, -2) == 0
|
|
; run: %srem_i16(-19, 7) == -5
|
|
; run: %srem_i16(0xC0FF, 8) == -1
|
|
; run: %srem_i16(0xC0FF, -8) == -1
|
|
; run: %srem_i16(0x8000, -2) == 0
|
|
|
|
function %srem_i8(i8, i8) -> i8 {
|
|
block0(v0: i8,v1: i8):
|
|
v2 = srem v0, v1
|
|
return v2
|
|
}
|
|
; run: %srem_i8(0, 1) == 0
|
|
; run: %srem_i8(2, 2) == 0
|
|
; run: %srem_i8(1, -1) == 0
|
|
; run: %srem_i8(2, 7) == 2
|
|
; run: %srem_i8(3, 2) == 1
|
|
; run: %srem_i8(19, 7) == 5
|
|
; run: %srem_i8(3, -2) == 1
|
|
; run: %srem_i8(-19, 7) == -5
|
|
; run: %srem_i8(0xC0, 8) == 0
|
|
; run: %srem_i8(0xC0, -8) == 0
|
|
; run: %srem_i8(0x80, -2) == 0
|
|
|
|
|
|
function %srem_imm_i64(i64) -> i64 {
|
|
block0(v0: i64):
|
|
v1 = srem_imm v0, 3
|
|
return v1
|
|
}
|
|
; run: %srem_imm_i64(0) == 0
|
|
; run: %srem_imm_i64(1) == 1
|
|
; run: %srem_imm_i64(2) == 2
|
|
; run: %srem_imm_i64(3) == 0
|
|
; run: %srem_imm_i64(19) == 1
|
|
; run: %srem_imm_i64(-19) == -1
|
|
; run: %srem_imm_i64(-57) == 0
|
|
; run: %srem_imm_i64(104857600000) == 1
|
|
; run: %srem_imm_i64(0xC0FFEEEE_DECAFFFF) == -1
|
|
; run: %srem_imm_i64(0x80000000_00000000) == -2
|
|
|
|
function %srem_imm_i32(i32) -> i32 {
|
|
block0(v0: i32):
|
|
v1 = srem_imm v0, 3
|
|
return v1
|
|
}
|
|
; run: %srem_imm_i32(0) == 0
|
|
; run: %srem_imm_i32(1) == 1
|
|
; run: %srem_imm_i32(2) == 2
|
|
; run: %srem_imm_i32(3) == 0
|
|
; run: %srem_imm_i32(4) == 1
|
|
; run: %srem_imm_i32(19) == 1
|
|
; run: %srem_imm_i32(-19) == -1
|
|
; run: %srem_imm_i32(-42) == 0
|
|
; run: %srem_imm_i32(1057) == 1
|
|
; run: %srem_imm_i32(0xC0FFEEEE) == -2
|
|
|
|
function %srem_imm_i16(i16) -> i16 {
|
|
block0(v0: i16):
|
|
v1 = srem_imm v0, 3
|
|
return v1
|
|
}
|
|
; run: %srem_imm_i16(0) == 0
|
|
; run: %srem_imm_i16(1) == 1
|
|
; run: %srem_imm_i16(2) == 2
|
|
; run: %srem_imm_i16(3) == 0
|
|
; run: %srem_imm_i16(4) == 1
|
|
; run: %srem_imm_i16(19) == 1
|
|
; run: %srem_imm_i16(-19) == -1
|
|
; run: %srem_imm_i16(0xC0FF) == -1
|
|
; run: %srem_imm_i16(0x8000) == -2
|
|
|
|
function %srem_imm_i8(i8) -> i8 {
|
|
block0(v0: i8):
|
|
v1 = srem_imm v0, 3
|
|
return v1
|
|
}
|
|
; run: %srem_imm_i8(0) == 0
|
|
; run: %srem_imm_i8(1) == 1
|
|
; run: %srem_imm_i8(2) == 2
|
|
; run: %srem_imm_i8(3) == 0
|
|
; run: %srem_imm_i8(19) == 1
|
|
; run: %srem_imm_i8(-19) == -1
|
|
; run: %srem_imm_i8(0xC0) == -1
|
|
; run: %srem_imm_i8(0x80) == -2
|
|
|
|
function %srem_with_bmask(i64, i8) -> i8 {
|
|
block0(v0: i64, v1: i8):
|
|
v2 = bmask.i8 v0
|
|
v3 = srem v2, v1
|
|
return v3
|
|
}
|
|
; run: %srem_with_bmask(4352, -1) == 0
|
|
; run: %srem_with_bmask(4352, 1) == 0
|