Skip to content

Compiler do not remove slice bounds checks if index is guaranteed to be less than part of the length #110971

@AngelicosPhosphoros

Description

@AngelicosPhosphoros

I tried this code:

pub fn test_assert(arr: &[u32], j: usize)->u32{
    assert!(j < arr.len() / 2);
    arr[j]
}

I expected to see this happen: Since for any nonnegative integer i / 2 < i, j < i / 2 implies that j < i so we should not have bounds check here at indexing.

Instead, this happened: Function checks j twice: first for len / 2 then for len, and generates all code for panics.

example::test_assert:
        push    rax
        mov     rax, rsi
        shr     rax
        cmp     rax, rdx
        jbe     .LBB0_3
        cmp     rdx, rsi
        jae     .LBB0_2
        mov     eax, dword ptr [rdi + 4*rdx]
        pop     rcx
        ret
.LBB0_2:
        lea     rax, [rip + .L__unnamed_1]
        mov     rdi, rdx
        mov     rdx, rax
        call    qword ptr [rip + core::panicking::panic_bounds_check@GOTPCREL]
        ud2
.LBB0_3:
        lea     rdi, [rip + .L__unnamed_2]
        lea     rdx, [rip + .L__unnamed_3]
        mov     esi, 35
        call    qword ptr [rip + core::panicking::panic@GOTPCREL]
        ud2

I noticed, that if we shorten slice first, it can remove bounds checks. E.g. this code doesn't generate any bounds checks:

pub fn test_unreachable2(arr: &[u32], j: usize)->u32{
    let arr = &arr[..arr.len() / 2];
    if j >= arr.len() {
        unsafe {
            unreachable_unchecked();
        }
    }
    arr[j]
}
example::test_unreachable2:
        mov     eax, dword ptr [rdi + 4*rdx]
        ret

Meta

rustc --version --verbose:

rustc 1.69.0 (84c898d65 2023-04-16)
binary: rustc
commit-hash: 84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc
commit-date: 2023-04-16
host: x86_64-unknown-linux-gnu
release: 1.69.0
LLVM version: 15.0.7

Godbolt link.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.I-slowIssue: Problems and improvements with respect to performance of generated code.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions