-
Couldn't load subscription status.
- Fork 1.5k
Description
When compiling with opt_level=speed, sdiv i64::MIN, i64::MIN returns -1 instead of 1.
The same occurs with opt_level=speed_and_size.
.clif Test Case
test interpret
test run
set opt_level=speed
target x86_64
function %sdiv_by_const_neg_i64min_i64(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 -9223372036854775808
v2 = sdiv v0, v1
return v2
}
; run: %sdiv_by_const_neg_i64min_i64(-9223372036854775808) == 1
Steps to Reproduce
- add the above in
cranelift/filetests/filetests/runtests/sdiv-broken.clif cd craneliftcargo +1.88.0 run -- test filetests/filetests/runtests/sdiv-broken.clif
Expected Results
The test should pass. i64::MIN / i64::MIN == 1.
Actual Results
We get an incorrect result: i64::MIN / i64::MIN == -1
Versions and Environment
Cranelift version or commit: f678260 is the first commit that causes the issue.
All cranelift versions from then on (1.22.0 -> current @ 1.25.1) are affected.
Operating system: Guix Linux @ 6.16.7, Ubuntu 24.04.3 LTS, MacOS.
Architecture: AMD64, x86_64, Mac M2.
Extra Info
As far as I can tell, the algorithm for the 'const denominator division' is correct. Indeed the proptests cover this case.
My best guess is that there could be some issue in how the constants are all inlined from the smulhi and the various other shifts in the fast algorithm. All other values appear to work correctly.
EDIT: the incorrect rule fires in the case of sdiv where d == ty::MIN. Namely, the rule for positive power of two fires instead of negative power of two.