Skip to content

Commit 1937c20

Browse files
committed
Avoid SmallVec::collect() in Result::intern_with().
This commit reduces instruction counts for several benchmarks by up to 5%.
1 parent 1419260 commit 1937c20

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

src/librustc/ty/context.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -2848,8 +2848,29 @@ impl<'a, T, R> InternIteratorElement<T, R> for &'a T
28482848

28492849
impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
28502850
type Output = Result<R, E>;
2851-
fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
2852-
Ok(f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?))
2851+
fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(mut iter: I, f: F)
2852+
-> Self::Output {
2853+
// This code is hot enough that it's worth specializing for the most
2854+
// common length lists, to avoid the overhead of `SmallVec` creation.
2855+
// The match arms are in order of frequency. The 1, 2, and 0 cases are
2856+
// typically hit in ~95% of cases. We assume that if the upper and
2857+
// lower bounds from `size_hint` agree they are correct.
2858+
Ok(match iter.size_hint() {
2859+
(1, Some(1)) => {
2860+
f(&[iter.next().unwrap()?])
2861+
}
2862+
(2, Some(2)) => {
2863+
let t0 = iter.next().unwrap()?;
2864+
let t1 = iter.next().unwrap()?;
2865+
f(&[t0, t1])
2866+
}
2867+
(0, Some(0)) => {
2868+
f(&[])
2869+
}
2870+
_ => {
2871+
f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?)
2872+
}
2873+
})
28532874
}
28542875
}
28552876

0 commit comments

Comments
 (0)