Skip to content

Commit c18adef

Browse files
committed
FEAT: Tweak bounds checked indexing code (Index, IndexMut)
Tweak bounds checked indexing code so that the compiler understands to remove the bounds check in some simple cases. See examples in the new example file bounds_check_elim.rs This helps in *some* cases where a conditional or loop conditional already do the required bounds check. Simple examples are if i < len and while i < len loops; the range iterator loop is a worse example, it doesn't do this as well! Further works is needed on that. Input code: ```rust pub fn test1d_single(a: &Array1<f64>, i: usize) -> f64 { if i < a.len() { a[i] } else { 0. } } ``` Codegen diff: ```diff test1d_single: .cfi_startproc - push rax -.Lcfi0: - .cfi_def_cfa_offset 16 xorps xmm0, xmm0 cmp qword ptr [rdi + 32], rsi - jbe .LBB0_3 + jbe .LBB0_2 + mov rax, qword ptr [rdi + 24] imul rsi, qword ptr [rdi + 40] - shl rsi, 3 - add rsi, qword ptr [rdi + 24] - je .LBB0_4 - movsd xmm0, qword ptr [rsi] -.LBB0_3: - pop rax + movsd xmm0, qword ptr [rax + 8*rsi] +.LBB0_2: ret -.LBB0_4: - call _ZN7ndarray11arraytraits19array_out_of_bounds17h009d4a482e88d6aaE@PLT .Lfunc_end0: .size test1d_single, .Lfunc_end0-test1d_single .cfi_endproc ```
1 parent a0e0c37 commit c18adef

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

src/arraytraits.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ impl<S, D, I> Index<I> for ArrayBase<S, D>
6969
#[inline]
7070
fn index(&self, index: I) -> &S::Elem {
7171
debug_bounds_check!(self, index);
72-
self.get(index).unwrap_or_else(|| array_out_of_bounds())
72+
unsafe {
73+
&*self.ptr.offset(index.index_checked(&self.dim, &self.strides)
74+
.unwrap_or_else(|| array_out_of_bounds()))
75+
}
7376
}
7477
}
7578

@@ -84,7 +87,10 @@ impl<S, D, I> IndexMut<I> for ArrayBase<S, D>
8487
#[inline]
8588
fn index_mut(&mut self, index: I) -> &mut S::Elem {
8689
debug_bounds_check!(self, index);
87-
self.get_mut(index).unwrap_or_else(|| array_out_of_bounds())
90+
unsafe {
91+
&mut *self.ptr.offset(index.index_checked(&self.dim, &self.strides)
92+
.unwrap_or_else(|| array_out_of_bounds()))
93+
}
8894
}
8995
}
9096

0 commit comments

Comments
 (0)