Skip to content

Missed optimization: bounds checking if index is both subtracted and divided #134704

Open
@SuperSamus

Description

Take this code:

#[no_mangle]
pub fn example(arr: &[u32]) -> u32 {
    let mut result = 0;
    for i in 1..arr.len() {
        result = arr[(i - 1) / 2];
    }
    result
}

If there was only a subtraction, the bounds check would be removed. Same if there was only a division (or a right shift).
But if there are both, it isn't:

example_1:
        xor     eax, eax
        cmp     rsi, 2
        jb      .LBB0_5
        lea     rcx, [rsi - 1]
        xor     edx, edx
.LBB0_2:
        mov     rax, rdx
        shr     rax
        cmp     rax, rsi
        jae     .LBB0_6
        inc     rdx
        cmp     rcx, rdx
        jne     .LBB0_2
        mov     eax, dword ptr [rdi + 4*rax]
.LBB0_5:
        ret
.LBB0_6:
        push    rax
        lea     rdx, [rip + .L__unnamed_1]
        mov     rdi, rax
        call    qword ptr [rip + core::panicking::panic_bounds_check::he3703b517476def5@GOTPCREL]

Adding unsafe {assert_unchecked((i - 1) / 2 < i)}; fixes the issue.

Godbolt

Metadata

Assignees

No one assigned

    Labels

    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions