Files
wasmtime/cranelift/filetests/filetests/runtests/div-checks.clif
Alex Crichton 5ae8575296 x64: Take SIGFPE signals for divide traps (#6026)
* 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
2023-03-16 00:18:45 +00:00

126 lines
2.3 KiB
Plaintext

test run
target aarch64
target s390x
target x86_64
target riscv64
function %i8(i8, i8) -> i8 {
block0(v0: i8, v1: i8):
v2 = srem.i8 v0, v1
return v2
}
; run: %i8(0x80, 0xff) == 0
function %i8_const(i8) -> i8 {
block0(v0: i8):
v1 = iconst.i8 -1
v2 = srem.i8 v0, v1
return v2
}
; run: %i8_const(0x80) == 0
function %i16(i16, i16) -> i16 {
block0(v0: i16, v1: i16):
v2 = srem.i16 v0, v1
return v2
}
; run: %i16(0x8000, 0xffff) == 0
function %i16_const(i16) -> i16 {
block0(v0: i16):
v1 = iconst.i16 0xffff
v2 = srem.i16 v0, v1
return v2
}
; run: %i16_const(0x8000) == 0
function %i32(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = srem.i32 v0, v1
return v2
}
; run: %i32(0x80000000, 0xffffffff) == 0
function %i32_const(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 -1
v2 = srem.i32 v0, v1
return v2
}
; run: %i32_const(0x80000000) == 0
function %i64(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = srem.i64 v0, v1
return v2
}
; run: %i64(0x800000000000000, 0xffffffffffffffff) == 0
function %i64_const(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 -1
v2 = srem.i64 v0, v1
return v2
}
; run: %i64_const(0x800000000000000) == 0
function %i8_u(i8, i8) -> i8 {
block0(v0: i8,v1: i8):
v2 = urem v0, v1
return v2
}
; run: %i8_u(0x80, 0xff) == 0x80
function %i8_u_const(i8) -> i8 {
block0(v0: i8):
v1 = iconst.i8 -1
v2 = urem v0, v1
return v2
}
; run: %i8_u_const(0x80) == 0x80
function %i16_u(i16, i16) -> i16 {
block0(v0: i16, v1: i16):
v2 = urem.i16 v0, v1
return v2
}
; run: %i16_u(0x8000, 0xffff) == 0x8000
function %i16_u_const(i16) -> i16 {
block0(v0: i16):
v1 = iconst.i16 0xffff
v2 = urem.i16 v0, v1
return v2
}
; run: %i16_u_const(0x8000) == 0x8000
function %i32_u(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = urem.i32 v0, v1
return v2
}
; run: %i32_u(0x80000000, 0xffffffff) == 0x80000000
function %i32_u_const(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 -1
v2 = urem.i32 v0, v1
return v2
}
; run: %i32_u_const(0x80000000) == 0x80000000
function %i64_u(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = urem.i64 v0, v1
return v2
}
; run: %i64_u(0x800000000000000, 0xffffffffffffffff) == 0x800000000000000
function %i64_u_const(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 -1
v2 = urem.i64 v0, v1
return v2
}
; run: %i64_u_const(0x800000000000000) == 0x800000000000000