Code change:
unsafe { self.__iterator_get_unchecked(index) } } } <ins> trait SpecFold: Iterator { fn spec_fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B; } impl<A: Iterator, B: Iterator> SpecFold for Zip<A, B> { // Adapted from default impl from the Iterator trait #[inline] default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { let mut accum = init; while let Some(x) = ZipImpl::next(&mut self) { accum = f(accum, x); } accum } } impl<A: TrustedLen, B: TrustedLen> SpecFold for Zip<A, B> { #[inline] fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { let mut accum = init; loop { let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 { (upper, false) } else { // Per TrustedLen contract a None upper bound means more than usize::MAX items (usize::MAX, true) }; for _ in 0..upper { let pair = // SAFETY: TrustedLen guarantees that at least `upper` many items are available // therefore we know they can't be None unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) }; accum = f(accum, pair); } if !more { break; } } accum } } </ins>

Related discussion:
text: <!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code: I expected to see this happen: same codegen or similar in performance Instead, this happened: array has way worse codegen <details<summaryAssembly</summary<p</p</details<!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: 1.64 <!-- Provide the version you are using that has the regression. --65 till now. Regressed in nightly-2022-08-13, maybe LLVM 15 ?: : <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. -- modify labels: +regression-from-stable-to-stable -regression-untriaged <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
WG-prioritization assigning priority (). cc since this regressed in the LLVM 15 update label -I-prioritize +P-medium +T-compiler
I've seen llvm doing these strange 1-byte-at-a-time "vectorizations" in other places too. This might be a more general problem. In this case we can probably paper over it by implementing TrustedRandomAccess for the array iter.
Unfortunately, the array iterator is fundamentally worse right now, because indexing into it -- a fundamental part of being a by-value array iterator -- keeps it from SRoAing and thus doesn't optimize well. This is why when I was making better I ended up making to not have to use . Sadly, for the foreseeable future you're better off using the "weaker" slice iterator when you can.
My guess is that the SROA is missing something in the opaque pointer mode.