Skip to content

Possible range of values isn't fully tracked after division #150353

@kornelski

Description

@kornelski

LLVM can't see an always-true relationship between two divided numbers:

void check(unsigned long v) {   
    assert((v / 100) <= v);           // optimized out OK
    assert((v / 200) <= v);           // optimized out OK

    assert((v / 200) <= (v / 2));     // FAIL        
}

Oddly, adding if (v >= 400) return; makes it prove the third case is true:

void check(unsigned long v) {   
    if (v >= 400) return;

    assert((v / 100) <= v);           // optimized out
    assert((v / 200) <= v);           // optimized out

    assert((v / 200) <= (v / 2));     // optimized out now too     
}

but with if (v >= 401) return; it becomes unknowable again.

Here's a real-world code that needs such reasoning to remove bounds checks:

https://github.com/kornelski/rust/blob/999967a57dce987bbad353d152f03c3ef67d41f2/library/core/src/slice/sort/select.rs#L222-L232

I expected I'd only need to prove the v.len() is non-0 to remove the bounds checks, but I needed to add more hints.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions