Skip to content

Commit c80db40

Browse files
Auto merge of #141652 - compiler-errors:more-collect-and-apply, r=<try>
[PERF] More collect and apply I saw that we have quite a few `collect_and_apply` calls for N=3-7 (N=7 corresponding to cumulative 99% of nalgebra's calls). Didn't perf locally, but also this is super low-pri, so let's see what rust-timer says.
2 parents 52882f6 + 42aacf4 commit c80db40

File tree

1 file changed

+86
-48
lines changed

1 file changed

+86
-48
lines changed

compiler/rustc_type_ir/src/interner.rs

Lines changed: 86 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::ops::Deref;
44

55
use rustc_ast_ir::Movability;
66
use rustc_index::bit_set::DenseBitSet;
7-
use smallvec::SmallVec;
87

98
use crate::fold::TypeFoldable;
109
use crate::inherent::*;
@@ -381,29 +380,43 @@ impl<T, R> CollectAndApply<T, R> for T {
381380
I: Iterator<Item = T>,
382381
F: FnOnce(&[T]) -> R,
383382
{
384-
// This code is hot enough that it's worth specializing for the most
385-
// common length lists, to avoid the overhead of `SmallVec` creation.
386-
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
387-
// `size_hint` is incorrect a panic will occur via an `unwrap` or an
388-
// `assert`.
389-
match iter.size_hint() {
390-
(0, Some(0)) => {
391-
assert!(iter.next().is_none());
392-
f(&[])
393-
}
394-
(1, Some(1)) => {
395-
let t0 = iter.next().unwrap();
396-
assert!(iter.next().is_none());
397-
f(&[t0])
398-
}
399-
(2, Some(2)) => {
400-
let t0 = iter.next().unwrap();
401-
let t1 = iter.next().unwrap();
402-
assert!(iter.next().is_none());
403-
f(&[t0, t1])
404-
}
405-
_ => f(&iter.collect::<SmallVec<[_; 8]>>()),
406-
}
383+
let Some(t0) = iter.next() else {
384+
return f(&[]);
385+
};
386+
387+
let Some(t1) = iter.next() else {
388+
return f(&[t0]);
389+
};
390+
391+
let Some(t2) = iter.next() else {
392+
return f(&[t0, t1]);
393+
};
394+
395+
let Some(t3) = iter.next() else {
396+
return f(&[t0, t1, t2]);
397+
};
398+
399+
let Some(t4) = iter.next() else {
400+
return f(&[t0, t1, t2, t3]);
401+
};
402+
403+
let Some(t5) = iter.next() else {
404+
return f(&[t0, t1, t2, t3, t4]);
405+
};
406+
407+
let Some(t6) = iter.next() else {
408+
return f(&[t0, t1, t2, t3, t4, t5]);
409+
};
410+
411+
let Some(t7) = iter.next() else {
412+
return f(&[t0, t1, t2, t3, t4, t5, t6]);
413+
};
414+
415+
let Some(t8) = iter.next() else {
416+
return f(&[t0, t1, t2, t3, t4, t5, t6, t7]);
417+
};
418+
419+
f(&[t0, t1, t2, t3, t4, t5, t6, t7, t8].into_iter().chain(iter).collect::<Vec<_>>())
407420
}
408421
}
409422

@@ -418,30 +431,55 @@ impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
418431
I: Iterator<Item = Result<T, E>>,
419432
F: FnOnce(&[T]) -> R,
420433
{
421-
// This code is hot enough that it's worth specializing for the most
422-
// common length lists, to avoid the overhead of `SmallVec` creation.
423-
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
424-
// `size_hint` is incorrect a panic will occur via an `unwrap` or an
425-
// `assert`, unless a failure happens first, in which case the result
426-
// will be an error anyway.
427-
Ok(match iter.size_hint() {
428-
(0, Some(0)) => {
429-
assert!(iter.next().is_none());
430-
f(&[])
431-
}
432-
(1, Some(1)) => {
433-
let t0 = iter.next().unwrap()?;
434-
assert!(iter.next().is_none());
435-
f(&[t0])
436-
}
437-
(2, Some(2)) => {
438-
let t0 = iter.next().unwrap()?;
439-
let t1 = iter.next().unwrap()?;
440-
assert!(iter.next().is_none());
441-
f(&[t0, t1])
442-
}
443-
_ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
444-
})
434+
let Some(t0) = iter.next() else {
435+
return Ok(f(&[]));
436+
};
437+
let t0 = t0?;
438+
439+
let Some(t1) = iter.next() else {
440+
return Ok(f(&[t0]));
441+
};
442+
let t1 = t1?;
443+
444+
let Some(t2) = iter.next() else {
445+
return Ok(f(&[t0, t1]));
446+
};
447+
let t2 = t2?;
448+
449+
let Some(t3) = iter.next() else {
450+
return Ok(f(&[t0, t1, t2]));
451+
};
452+
let t3 = t3?;
453+
454+
let Some(t4) = iter.next() else {
455+
return Ok(f(&[t0, t1, t2, t3]));
456+
};
457+
let t4 = t4?;
458+
459+
let Some(t5) = iter.next() else {
460+
return Ok(f(&[t0, t1, t2, t3, t4]));
461+
};
462+
let t5 = t5?;
463+
464+
let Some(t6) = iter.next() else {
465+
return Ok(f(&[t0, t1, t2, t3, t4, t5]));
466+
};
467+
let t6 = t6?;
468+
469+
let Some(t7) = iter.next() else {
470+
return Ok(f(&[t0, t1, t2, t3, t4, t5, t6]));
471+
};
472+
let t7 = t7?;
473+
474+
let Some(t8) = iter.next() else {
475+
return Ok(f(&[t0, t1, t2, t3, t4, t5, t6, t7]));
476+
};
477+
let t8 = t8?;
478+
479+
Ok(f(&[Ok(t0), Ok(t1), Ok(t2), Ok(t3), Ok(t4), Ok(t5), Ok(t6), Ok(t7), Ok(t8)]
480+
.into_iter()
481+
.chain(iter)
482+
.collect::<Result<Vec<_>, _>>()?))
445483
}
446484
}
447485

0 commit comments

Comments
 (0)