Skip to content

Bounds check not elided for index that should be known to be in-bounds #139759

@okaneco

Description

@okaneco

When calculating a new index with valid_index.saturating_sub(1), I expected the bounds check to be elided. Instead, get_unchecked must be used to eliminate the check.
https://rust.godbolt.org/z/3d8o81T5h

#[inline(never)]
pub fn src(s: &[i32], index: usize) -> i32 {
    if index < s.len() {
        let lower_bound = index.saturating_sub(1);
        s[lower_bound]
    } else {
        -1
    }
}

#[inline(never)]
pub fn tgt(s: &[i32], index: usize) -> i32 {
    if index < s.len() {
        let lower_bound = index.saturating_sub(1);

        // SAFETY: 0 <= lower_bound <= index < s.len()
        unsafe { *s.get_unchecked(lower_bound) }
    } else {
        -1
    }
}
Assembly
example::src::he0570b220ad4b59c:
        mov     eax, -1
        cmp     rdx, rsi
        jae     .LBB0_3
        xor     eax, eax
        sub     rdx, 1
        cmovae  rax, rdx
        cmp     rax, rsi
        jae     .LBB0_4
        mov     eax, dword ptr [rdi + 4*rax]
.LBB0_3:
        ret
.LBB0_4:
        push    rax
        lea     rdx, [rip + .Lanon.75debc62a0d2e1b3b01bdfb8cd64dd40.1]
        mov     rdi, rax
        call    qword ptr [rip + core::panicking::panic_bounds_check::hbc0e9d687b85ab6e@GOTPCREL]

.Lanon.75debc62a0d2e1b3b01bdfb8cd64dd40.0:
        .ascii  "/app/example.rs"

.Lanon.75debc62a0d2e1b3b01bdfb8cd64dd40.1:
        .quad   .Lanon.75debc62a0d2e1b3b01bdfb8cd64dd40.0
        .asciz  "\017\000\000\000\000\000\000\000\005\000\000\000\t\000\000"
example::tgt::h9b445c80275c4bef:
        mov     eax, -1
        cmp     rdx, rsi
        jae     .LBB0_2
        xor     eax, eax
        sub     rdx, 1
        cmovae  rax, rdx
        mov     eax, dword ptr [rdi + 4*rax]
.LBB0_2:
        ret

I came across this while starting to constify floor_char_boundary by rewriting it into a while loop.
https://rust.godbolt.org/z/zEYvEPG8v

Meta

rustc 1.88.0-nightly (0fe8f3454 2025-04-10)
binary: rustc
commit-hash: 0fe8f3454dbe9dda52a254991347e96bec579a6f
commit-date: 2025-04-10
host: x86_64-unknown-linux-gnu
release: 1.88.0-nightly
LLVM version: 20.1.2
Internal compiler ID: nightly

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchE-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