Open
Description
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
Labels
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Category: An issue highlighting optimization opportunities or PRs implementing suchIssue: Problems and improvements with respect to performance of generated code.Issue expected to be fixed by the next major LLVM upgrade, or backported fixes