Merge pull request #2763 from cfallin/fix-srem-trap

Handle `srem` properly when `avoid_div_traps` is false.
This commit is contained in:
Chris Fallin
2021-03-24 23:58:26 -07:00
committed by GitHub
4 changed files with 33 additions and 2 deletions

View File

@@ -887,7 +887,6 @@ pub(crate) fn emit(
// idiv %divisor
//
// $done:
debug_assert!(info.flags().avoid_div_traps());
// Check if the divisor is zero, first.
let inst = Inst::cmp_rmi_r(*size, RegMemImm::imm(0), divisor.to_reg());

View File

@@ -5181,7 +5181,8 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
input_ty,
));
if flags.avoid_div_traps() {
// Always do explicit checks for `srem`: otherwise, INT_MIN % -1 is not handled properly.
if flags.avoid_div_traps() || op == Opcode::Srem {
// A vcode meta-instruction is used to lower the inline checks, since they embed
// pc-relative offsets that must not change, thus requiring regalloc to not
// interfere by introducing spills and reloads.

View File

@@ -0,0 +1,12 @@
test run
set avoid_div_traps=false
target x86_64
feature "experimental_x64"
function %f0(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = srem.i32 v0, v1
return v2
}
; run: %f0(0x80000000, 0xffffffff) == 0

View File

@@ -0,0 +1,19 @@
test compile
set avoid_div_traps=false
target x86_64
feature "experimental_x64"
;; We should get the checked-div/rem sequence (`srem` pseudoinst below) even
;; when `avoid_div_traps` above is false (i.e. even when the host is normally
;; willing to accept SIGFPEs as Wasm traps). The machine will SIGFPE in some
;; cases when `srem` is valid (specifically -INT_MIN % -1).
function %f0(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = srem.i64 v0, v1
; check: movq %rdi, %rax
; nextln: movl $$0, %edx
; nextln: srem $$rax:$$rdx, %rsi
; nextln: movq %rdx, %rax
return v2
}