-impl<'a> Conflicts<'a> {
- fn build<'tcx>(
- tcx: TyCtxt<'tcx>,
- body: &'_ Body<'tcx>,
- relevant_locals: &'a BitSet<Local>,
- ) -> Self {
- // We don't have to look out for locals that have their address taken, since
- // `find_candidates` already takes care of that.
-
- let conflicts = BitMatrix::from_row_n(
- &BitSet::new_empty(body.local_decls.len()),
- body.local_decls.len(),
- );
-
- let mut init = MaybeInitializedLocals
- .into_engine(tcx, body)
- .iterate_to_fixpoint()
- .into_results_cursor(body);
- let mut live =
- MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint().into_results_cursor(body);
-
- let mut reachable = None;
- dump_mir(tcx, None, "DestinationPropagation-dataflow", &"", body, |pass_where, w| {
- let reachable = reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body));
-
- match pass_where {
- PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => {
- init.seek_before_primary_effect(loc);
- live.seek_after_primary_effect(loc);
-
- writeln!(w, " // init: {:?}", init.get())?;
- writeln!(w, " // live: {:?}", live.get())?;
- }
- PassWhere::AfterTerminator(bb) if reachable.contains(bb) => {
- let loc = body.terminator_loc(bb);
- init.seek_after_primary_effect(loc);
- live.seek_before_primary_effect(loc);
-
- writeln!(w, " // init: {:?}", init.get())?;
- writeln!(w, " // live: {:?}", live.get())?;
- }
-
- PassWhere::BeforeBlock(bb) if reachable.contains(bb) => {
- init.seek_to_block_start(bb);
- live.seek_to_block_start(bb);
-
- writeln!(w, " // init: {:?}", init.get())?;
- writeln!(w, " // live: {:?}", live.get())?;
- }
-
- PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {}
-
- PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => {
- writeln!(w, " // init: <unreachable>")?;
- writeln!(w, " // live: <unreachable>")?;
- }
-
- PassWhere::BeforeBlock(_) => {
- writeln!(w, " // init: <unreachable>")?;
- writeln!(w, " // live: <unreachable>")?;
- }
+// We first implement some utility functions which we will expose removing candidates according to
+// different needs. Throughout the livenss filtering, the `candidates` are only ever accessed
+// through these methods, and not directly.
+impl<'alloc> Candidates<'alloc> {
+ /// Just `Vec::retain`, but the condition is inverted and we add debugging output
+ fn vec_remove_debug(
+ src: Local,
+ v: &mut Vec<Local>,
+ mut f: impl FnMut(Local) -> bool,
+ at: Location,
+ ) {
+ v.retain(|dest| {
+ let remove = f(*dest);
+ if remove {
+ trace!("eliminating {:?} => {:?} due to conflict at {:?}", src, dest, at);