Skip to content

Commit 093b248

Browse files
perf: only calculate conflicts for candidates
1 parent fef2597 commit 093b248

File tree

1 file changed

+39
-12
lines changed

1 file changed

+39
-12
lines changed

src/librustc_mir/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
}
@@ -435,7 +462,7 @@ impl Conflicts {
435462
},
436463
);
437464

438-
let mut relevant_locals = Vec::new();
465+
let mut live_and_init_locals = Vec::new();
439466

440467
// Visit only reachable basic blocks. The exact order is not important.
441468
for (block, data) in traversal::preorder(body) {
@@ -448,7 +475,7 @@ impl Conflicts {
448475
// that, we first collect in the `MaybeInitializedLocals` results in a forwards
449476
// traversal.
450477

451-
relevant_locals.resize_with(data.statements.len() + 1, || {
478+
live_and_init_locals.resize_with(data.statements.len() + 1, || {
452479
BitSet::new_empty(body.local_decls.len())
453480
});
454481

@@ -457,19 +484,19 @@ impl Conflicts {
457484
let loc = Location { block, statement_index };
458485
init.seek_before_primary_effect(loc);
459486

460-
relevant_locals[statement_index].overwrite(init.get());
487+
live_and_init_locals[statement_index].overwrite(init.get());
461488
}
462489

463490
// Now, go backwards and union with the liveness results.
464491
for statement_index in (0..=data.statements.len()).rev() {
465492
let loc = Location { block, statement_index };
466493
live.seek_after_primary_effect(loc);
467494

468-
relevant_locals[statement_index].intersect(live.get());
495+
live_and_init_locals[statement_index].intersect(live.get());
469496

470497
trace!("record conflicts at {:?}", loc);
471498

472-
record_conflicts(&relevant_locals[statement_index]);
499+
record_conflicts(&mut live_and_init_locals[statement_index]);
473500
}
474501

475502
init.seek_to_block_end(block);
@@ -478,7 +505,7 @@ impl Conflicts {
478505
conflicts.intersect(live.get());
479506
trace!("record conflicts at end of {:?}", block);
480507

481-
record_conflicts(&conflicts);
508+
record_conflicts(&mut conflicts);
482509
}
483510

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

0 commit comments

Comments
 (0)