Skip to content

Commit d90508f

Browse files
committed
use indexed loop instead of ptr bumping
this seems to produce less IR
1 parent ba5b2f0 commit d90508f

File tree

2 files changed

+20
-18
lines changed

2 files changed

+20
-18
lines changed

library/core/src/slice/iter/macros.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -192,23 +192,33 @@ macro_rules! iterator {
192192
}
193193

194194
#[inline]
195-
fn fold<B, F>(mut self, init: B, mut f: F) -> B
195+
fn fold<B, F>(self, init: B, mut f: F) -> B
196196
where
197197
F: FnMut(B, Self::Item) -> B,
198198
{
199-
// Handling the 0-len case explicitly and then using a do-while style loop
200-
// helps the optimizer. See issue #106288
199+
// this implementation consists of the following optimizations compared to the
200+
// default implementation:
201+
// - do-while loop, as is llvm's preferred loop shape,
202+
// see https://releases.llvm.org/16.0.0/docs/LoopTerminology.html#more-canonical-loops
203+
// - bumps an index instead of a pointer since the latter case inhibits
204+
// some optimizations, see #111603
205+
// - avoids Option wrapping/matching
201206
if is_empty!(self) {
202207
return init;
203208
}
204209
let mut acc = init;
205-
// SAFETY: The 0-len case was handled above so one loop iteration is guaranteed.
206-
unsafe {
207-
loop {
208-
acc = f(acc, next_unchecked!(self));
209-
if is_empty!(self) {
210-
break;
211-
}
210+
let mut i = 0;
211+
let len = len!(self);
212+
loop {
213+
// SAFETY: the loop iterates `i in 0..len`, which always is in bounds of
214+
// the slice allocation
215+
acc = f(acc, unsafe { & $( $mut_ )? *self.ptr.add(i).as_ptr() });
216+
// SAFETY: `i` can't overflow since it'll only reach usize::MAX if the
217+
// slice had that length, in which case we'll break out of the loop
218+
// after the increment
219+
i = unsafe { i.unchecked_add(1) };
220+
if i == len {
221+
break;
212222
}
213223
}
214224
acc

tests/codegen/vec-shrink-panik.rs

-8
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,6 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
3737
// CHECK-LABEL: @issue75636
3838
#[no_mangle]
3939
pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
40-
// CHECK-NOT: panic
41-
42-
// Call to panic_cannot_unwind in case of double-panic is expected,
43-
// on LLVM 16 and older, but other panics are not.
44-
// old: filter
45-
// old-NEXT: ; call core::panicking::panic_cannot_unwind
46-
// old-NEXT: panic_cannot_unwind
47-
4840
// CHECK-NOT: panic
4941
iter.iter().copied().collect()
5042
}

0 commit comments

Comments
 (0)