Skip to content

Cranelift: opt_level=speed breaks sdiv i64::MIN, i64::MIN #11927

@emturner

Description

@emturner

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 cranelift
  • cargo +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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIncorrect behavior in the current implementation that needs fixingcraneliftIssues related to the Cranelift code generator

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions