Skip to content

Commit 73621b2

Browse files
committed
Auto merge of #118490 - Nadrieril:arena-alloc-matrix, r=<try>
[Experiment] Exhaustiveness: allocate memory better Exhaustiveness is a recursive algorithm that allocates a bunch of slices at every step. Let's see if I can improve performance by improving allocations. Already just using `Vec::with_capacity` is showing impressive improvements on my local measurements. r? `@ghost`
2 parents f45631b + ab2a92a commit 73621b2

File tree

1 file changed

+11
-14
lines changed

1 file changed

+11
-14
lines changed

Diff for: compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,8 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
599599
// an or-pattern. Panics if `self` is empty.
600600
fn expand_or_pat<'a>(&'a self) -> impl Iterator<Item = PatStack<'p, 'tcx>> + Captures<'a> {
601601
self.head().flatten_or_pat().into_iter().map(move |pat| {
602-
let mut new_pats = smallvec![pat];
602+
let mut new_pats = SmallVec::<[_; 2]>::with_capacity(self.len());
603+
new_pats.push(pat);
603604
new_pats.extend_from_slice(&self.pats[1..]);
604605
PatStack { pats: new_pats }
605606
})
@@ -614,7 +615,9 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
614615
) -> PatStack<'p, 'tcx> {
615616
// We pop the head pattern and push the new fields extracted from the arguments of
616617
// `self.head()`.
617-
let mut new_pats = self.head().specialize(pcx, ctor);
618+
let ctor_fields = self.head().specialize(pcx, ctor);
619+
let mut new_pats = SmallVec::<[_; 2]>::with_capacity(self.len() + ctor_fields.len() - 1);
620+
new_pats.extend_from_slice(&ctor_fields);
618621
new_pats.extend_from_slice(&self.pats[1..]);
619622
PatStack { pats: new_pats }
620623
}
@@ -732,18 +735,11 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
732735
}
733736

734737
/// Build a new matrix from an iterator of `MatchArm`s.
735-
fn new<'a>(
736-
cx: &MatchCheckCtxt<'p, 'tcx>,
737-
iter: impl Iterator<Item = &'a MatchArm<'p, 'tcx>>,
738-
scrut_ty: Ty<'tcx>,
739-
) -> Self
740-
where
741-
'p: 'a,
742-
{
738+
fn new(cx: &MatchCheckCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>) -> Self {
743739
let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP));
744740
let wildcard_row = PatStack::from_pattern(wild_pattern);
745-
let mut matrix = Matrix { rows: vec![], wildcard_row };
746-
for (row_id, arm) in iter.enumerate() {
741+
let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), wildcard_row };
742+
for (row_id, arm) in arms.iter().enumerate() {
747743
let v = MatrixRow {
748744
pats: PatStack::from_pattern(arm.pat),
749745
parent_row: row_id, // dummy, we won't read it
@@ -806,7 +802,8 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
806802
ctor: &Constructor<'tcx>,
807803
) -> Matrix<'p, 'tcx> {
808804
let wildcard_row = self.wildcard_row.pop_head_constructor(pcx, ctor);
809-
let mut matrix = Matrix { rows: vec![], wildcard_row };
805+
let rows = Vec::with_capacity(self.rows.len()); // Better waste capacity than reallocate a lot.
806+
let mut matrix = Matrix { rows, wildcard_row };
810807
for (i, row) in self.rows().enumerate() {
811808
if ctor.is_covered_by(pcx, row.head().ctor()) {
812809
let new_row = row.pop_head_constructor(pcx, ctor, i);
@@ -1386,7 +1383,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
13861383
arms: &[MatchArm<'p, 'tcx>],
13871384
scrut_ty: Ty<'tcx>,
13881385
) -> UsefulnessReport<'p, 'tcx> {
1389-
let mut matrix = Matrix::new(cx, arms.iter(), scrut_ty);
1386+
let mut matrix = Matrix::new(cx, arms, scrut_ty);
13901387
let non_exhaustiveness_witnesses =
13911388
compute_exhaustiveness_and_reachability(cx, &mut matrix, true);
13921389

0 commit comments

Comments
 (0)