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

Commit 402f863

Browse files
perf: walk liveness backwards in Conflicts::build
1 parent 7dbc7f7 commit 402f863

File tree

1 file changed

+39
-24
lines changed

1 file changed

+39
-24
lines changed

compiler/rustc_mir/src/transform/dest_prop.rs

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,7 @@ use crate::{
100100
transform::{MirPass, MirSource},
101101
util::{dump_mir, PassWhere},
102102
};
103-
use dataflow::{
104-
impls::{MaybeInitializedLocals, MaybeLiveLocals},
105-
ResultsCursor,
106-
};
103+
use dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
107104
use rustc_data_structures::unify::{InPlaceUnificationTable, UnifyKey};
108105
use rustc_index::{
109106
bit_set::{BitMatrix, BitSet},
@@ -382,16 +379,11 @@ impl Conflicts {
382379
body.local_decls.len(),
383380
);
384381

385-
let mut record_conflicts =
386-
|init: &ResultsCursor<'_, '_, MaybeInitializedLocals>,
387-
live: &ResultsCursor<'_, '_, MaybeLiveLocals>| {
388-
let mut requires_storage = init.get().clone();
389-
requires_storage.intersect(live.get());
390-
391-
for local in requires_storage.iter() {
392-
conflicts.union_row_with(&requires_storage, local);
393-
}
394-
};
382+
let mut record_conflicts = |new_conflicts: &BitSet<_>| {
383+
for local in new_conflicts.iter() {
384+
conflicts.union_row_with(&new_conflicts, local);
385+
}
386+
};
395387

396388
let def_id = source.def_id();
397389
let mut init = MaybeInitializedLocals
@@ -457,27 +449,50 @@ impl Conflicts {
457449
},
458450
);
459451

452+
let mut relevant_locals = Vec::new();
453+
460454
// Visit only reachable basic blocks. The exact order is not important.
461455
for (block, data) in traversal::preorder(body) {
462-
// Observe the dataflow state *before* all possible locations (statement or terminator) in
463-
// each basic block...
456+
// We need to observe the dataflow state *before* all possible locations (statement or
457+
// terminator) in each basic block, and then observe the state *after* the terminator
458+
// effect is applied. As long as neither `init` nor `borrowed` has a "before" effect,
459+
// we will observe all possible dataflow states.
460+
461+
// Since liveness is a backwards analysis, we need to walk the results backwards. To do
462+
// that, we first collect in the `MaybeInitializedLocals` results in a forwards
463+
// traversal.
464+
465+
relevant_locals.resize_with(data.statements.len() + 1, || {
466+
BitSet::new_empty(body.local_decls.len())
467+
});
468+
469+
// First, go forwards for `MaybeInitializedLocals`.
464470
for statement_index in 0..=data.statements.len() {
465471
let loc = Location { block, statement_index };
466-
trace!("record conflicts at {:?}", loc);
467472
init.seek_before_primary_effect(loc);
473+
474+
relevant_locals[statement_index].clone_from(init.get());
475+
}
476+
477+
// Now, go backwards and union with the liveness results.
478+
for statement_index in (0..=data.statements.len()).rev() {
479+
let loc = Location { block, statement_index };
468480
live.seek_after_primary_effect(loc);
469-
// FIXME: liveness is backwards, so this is slow
470481

471-
record_conflicts(&init, &live);
482+
relevant_locals[statement_index].intersect(live.get());
483+
484+
trace!("record conflicts at {:?}", loc);
485+
486+
record_conflicts(&relevant_locals[statement_index]);
472487
}
473488

474-
// ...and then observe the state *after* the terminator effect is applied. As long as
475-
// neither `init` nor `borrowed` has a "before" effect, we will observe all possible
476-
// dataflow states here or in the loop above.
477-
trace!("record conflicts at end of {:?}", block);
478489
init.seek_to_block_end(block);
479490
live.seek_to_block_end(block);
480-
record_conflicts(&init, &live);
491+
let mut conflicts = init.get().clone();
492+
conflicts.intersect(live.get());
493+
trace!("record conflicts at end of {:?}", block);
494+
495+
record_conflicts(&conflicts);
481496
}
482497

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

0 commit comments

Comments
 (0)