Add an avoid_div_traps setting.
This enables code generation that never causes a SIGFPE signal to be raised from a division instruction. Instead, division and remainder calculations are protected by explicit traps.
This commit is contained in:
71
cranelift/filetests/isa/intel/legalize-div-traps.cton
Normal file
71
cranelift/filetests/isa/intel/legalize-div-traps.cton
Normal file
@@ -0,0 +1,71 @@
|
||||
; Test the division legalizations.
|
||||
test legalizer
|
||||
set is_64bit
|
||||
; See also legalize-div.cton.
|
||||
set avoid_div_traps=1
|
||||
isa intel
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: EBB=ebb\d+
|
||||
|
||||
function %udiv(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = udiv v0, v1
|
||||
; nextln: $(fz=$V) = ifcmp_imm $v1, 0
|
||||
; nextln: trapif eq $fz, int_divz
|
||||
; nextln: $(hi=$V) = iconst.i64 0
|
||||
; nextln: $(d=$V), $(r=$V) = x86_udivmodx $v0, $hi, $v1
|
||||
return v2
|
||||
; nextln: return $d
|
||||
}
|
||||
|
||||
function %urem(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = urem v0, v1
|
||||
; nextln: $(fz=$V) = ifcmp_imm $v1, 0
|
||||
; nextln: trapif eq $fz, int_divz
|
||||
; nextln: $(hi=$V) = iconst.i64 0
|
||||
; nextln: $(d=$V), $(r=$V) = x86_udivmodx $v0, $hi, $v1
|
||||
return v2
|
||||
; nextln: return $r
|
||||
}
|
||||
|
||||
function %sdiv(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = sdiv v0, v1
|
||||
; nextln: $(fm1=$V) = ifcmp_imm $v1, -1
|
||||
; nextln: brif eq $fm1, $(m1=$EBB)
|
||||
; nextln: $(fz=$V) = ifcmp_imm $v1, 0
|
||||
; nextln: trapif eq $fz, int_divz
|
||||
; check: $(hi=$V) = sshr
|
||||
; nextln: $(q=$V), $(r=$V) = x86_sdivmodx $v0, $hi, $v1
|
||||
; nextln: jump $(done=$EBB)($q)
|
||||
; check: $m1:
|
||||
; nextln: $(fm=$V) = ifcmp_imm.i64 $v0, 0x8000_0000_0000_0000
|
||||
; nextln: trapif eq $fm, int_ovf
|
||||
; check: $done($v2: i64):
|
||||
return v2
|
||||
; nextln: return $v2
|
||||
}
|
||||
|
||||
; The srem expansion needs to special-case x % -1 since x86_sdivmodx traps on INT_MIN/-1.
|
||||
; TODO: Add more explicit pattern matching once we've cleaned up the ifcmp+brif pattern.
|
||||
function %srem(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = srem v0, v1
|
||||
; nextln: $(fm1=$V) = ifcmp_imm $v1, -1
|
||||
; nextln: brif eq $fm1, $(m1=$EBB)
|
||||
; check: $(hi=$V) = sshr
|
||||
; nextln: $(d=$V), $(r=$V) = x86_sdivmodx $v0, $hi, $v1
|
||||
; nextln: jump $(done=$EBB)($r)
|
||||
; check: $m1:
|
||||
; nextln: $(zero=$V) = iconst.i64 0
|
||||
; nextln: jump $(done=$EBB)($zero)
|
||||
; check: $done($v2: i64):
|
||||
return v2
|
||||
; nextln: return $v2
|
||||
}
|
||||
58
cranelift/filetests/isa/intel/legalize-div.cton
Normal file
58
cranelift/filetests/isa/intel/legalize-div.cton
Normal file
@@ -0,0 +1,58 @@
|
||||
; Test the division legalizations.
|
||||
test legalizer
|
||||
set is_64bit
|
||||
; See also legalize-div-traps.cton.
|
||||
set avoid_div_traps=0
|
||||
isa intel
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: EBB=ebb\d+
|
||||
|
||||
function %udiv(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = udiv v0, v1
|
||||
; nextln: $(hi=$V) = iconst.i64 0
|
||||
; nextln: $(d=$V), $(r=$V) = x86_udivmodx $v0, $hi, $v1
|
||||
return v2
|
||||
; nextln: return $d
|
||||
}
|
||||
|
||||
function %urem(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = urem v0, v1
|
||||
; nextln: $(hi=$V) = iconst.i64 0
|
||||
; nextln: $(d=$V), $(r=$V) = x86_udivmodx $v0, $hi, $v1
|
||||
return v2
|
||||
; nextln: return $r
|
||||
}
|
||||
|
||||
function %sdiv(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = sdiv v0, v1
|
||||
; check: $(hi=$V) = sshr
|
||||
; nextln: $(d=$V), $(r=$V) = x86_sdivmodx $v0, $hi, $v1
|
||||
return v2
|
||||
; nextln: return $d
|
||||
}
|
||||
|
||||
; The srem expansion needs to special-case x % -1 since x86_sdivmodx traps on INT_MIN/-1.
|
||||
; TODO: Add more explicit pattern matching once we've cleaned up the ifcmp+brif pattern.
|
||||
function %srem(i64, i64) -> i64 {
|
||||
ebb0(v0: i64, v1: i64):
|
||||
; check: $ebb0(
|
||||
v2 = srem v0, v1
|
||||
; nextln: $(fm1=$V) = ifcmp_imm $v1, -1
|
||||
; nextln: brif eq $fm1, $(m1=$EBB)
|
||||
; check: $(hi=$V) = sshr
|
||||
; nextln: $(d=$V), $(r=$V) = x86_sdivmodx $v0, $hi, $v1
|
||||
; nextln: jump $(done=$EBB)($r)
|
||||
; check: $m1:
|
||||
; nextln: $(zero=$V) = iconst.i64 0
|
||||
; nextln: jump $(done=$EBB)($zero)
|
||||
; check: $done($v2: i64):
|
||||
return v2
|
||||
; nextln: return $v2
|
||||
}
|
||||
Reference in New Issue
Block a user