Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ab26fb1

Browse files
perf: only calculate conflicts for candidates
1 parent 665a98d commit ab26fb1

File tree

1 file changed

+39
-12
lines changed

1 file changed

+39
-12
lines changed

compiler/rustc_mir/src/transform/dest_prop.rs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,22 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
124124
return;
125125
}
126126

127-
let mut conflicts = Conflicts::build(tcx, body, source);
127+
let candidates = find_candidates(tcx, body);
128+
if candidates.is_empty() {
129+
debug!("{:?}: no dest prop candidates, done", source.def_id());
130+
return;
131+
}
132+
133+
// Collect all locals we care about. We only compute conflicts for these to save time.
134+
let mut relevant_locals = BitSet::new_empty(body.local_decls.len());
135+
for CandidateAssignment { dest, src, loc: _ } in &candidates {
136+
relevant_locals.insert(dest.local);
137+
relevant_locals.insert(*src);
138+
}
139+
140+
let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
128141
let mut replacements = Replacements::new(body.local_decls.len());
129-
for candidate @ CandidateAssignment { dest, src, loc } in find_candidates(tcx, body) {
142+
for candidate @ CandidateAssignment { dest, src, loc } in candidates {
130143
// Merge locals that don't conflict.
131144
if conflicts.contains(dest.local, src) {
132145
debug!("at assignment {:?}, conflict {:?} vs. {:?}", loc, dest.local, src);
@@ -370,16 +383,30 @@ struct Conflicts {
370383
}
371384

372385
impl Conflicts {
373-
fn build<'tcx>(tcx: TyCtxt<'tcx>, body: &'_ Body<'tcx>, source: MirSource<'tcx>) -> Self {
374-
// We don't have to look out for locals that have their address taken, since `find_candidates`
375-
// already takes care of that.
386+
fn build<'tcx>(
387+
tcx: TyCtxt<'tcx>,
388+
body: &'_ Body<'tcx>,
389+
source: MirSource<'tcx>,
390+
relevant_locals: &BitSet<Local>,
391+
) -> Self {
392+
// We don't have to look out for locals that have their address taken, since
393+
// `find_candidates` already takes care of that.
394+
395+
debug!(
396+
"Conflicts::build: {}/{} locals relevant",
397+
relevant_locals.count(),
398+
body.local_decls.len()
399+
);
376400

377401
let mut conflicts = BitMatrix::from_row_n(
378402
&BitSet::new_empty(body.local_decls.len()),
379403
body.local_decls.len(),
380404
);
381405

382-
let mut record_conflicts = |new_conflicts: &BitSet<_>| {
406+
let mut record_conflicts = |new_conflicts: &mut BitSet<_>| {
407+
// Remove all locals that are not candidates.
408+
new_conflicts.intersect(relevant_locals);
409+
383410
for local in new_conflicts.iter() {
384411
conflicts.union_row_with(&new_conflicts, local);
385412
}
@@ -449,7 +476,7 @@ impl Conflicts {
449476
},
450477
);
451478

452-
let mut relevant_locals = Vec::new();
479+
let mut live_and_init_locals = Vec::new();
453480

454481
// Visit only reachable basic blocks. The exact order is not important.
455482
for (block, data) in traversal::preorder(body) {
@@ -462,7 +489,7 @@ impl Conflicts {
462489
// that, we first collect in the `MaybeInitializedLocals` results in a forwards
463490
// traversal.
464491

465-
relevant_locals.resize_with(data.statements.len() + 1, || {
492+
live_and_init_locals.resize_with(data.statements.len() + 1, || {
466493
BitSet::new_empty(body.local_decls.len())
467494
});
468495

@@ -471,19 +498,19 @@ impl Conflicts {
471498
let loc = Location { block, statement_index };
472499
init.seek_before_primary_effect(loc);
473500

474-
relevant_locals[statement_index].clone_from(init.get());
501+
live_and_init_locals[statement_index].clone_from(init.get());
475502
}
476503

477504
// Now, go backwards and union with the liveness results.
478505
for statement_index in (0..=data.statements.len()).rev() {
479506
let loc = Location { block, statement_index };
480507
live.seek_after_primary_effect(loc);
481508

482-
relevant_locals[statement_index].intersect(live.get());
509+
live_and_init_locals[statement_index].intersect(live.get());
483510

484511
trace!("record conflicts at {:?}", loc);
485512

486-
record_conflicts(&relevant_locals[statement_index]);
513+
record_conflicts(&mut live_and_init_locals[statement_index]);
487514
}
488515

489516
init.seek_to_block_end(block);
@@ -492,7 +519,7 @@ impl Conflicts {
492519
conflicts.intersect(live.get());
493520
trace!("record conflicts at end of {:?}", block);
494521

495-
record_conflicts(&conflicts);
522+
record_conflicts(&mut conflicts);
496523
}
497524

498525
Self { matrix: conflicts, unify_cache: BitSet::new_empty(body.local_decls.len()) }

0 commit comments

Comments
 (0)