diff options
| author | Camille Gillot <gillot.camille@gmail.com> | 2025-08-26 23:38:45 +0000 |
|---|---|---|
| committer | Camille Gillot <gillot.camille@gmail.com> | 2025-09-07 16:45:34 +0000 |
| commit | 28ff5cf502a0132a4eed8aa46fa7371c7e7ed3f1 (patch) | |
| tree | 33a78a3b3666ae2c200c5ca6e22c4da318c91115 | |
| parent | 99f6bcf38065c78897a80c9fc7f8c49962df0ab7 (diff) | |
| download | rust-28ff5cf502a0132a4eed8aa46fa7371c7e7ed3f1.tar.gz rust-28ff5cf502a0132a4eed8aa46fa7371c7e7ed3f1.zip | |
Simplify candidate collection.
| -rw-r--r-- | compiler/rustc_mir_transform/src/dest_prop.rs | 98 |
1 files changed, 43 insertions, 55 deletions
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 359cd622608..b6306c4869b 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -137,7 +137,6 @@ //! [attempt 3]: https://github.com/rust-lang/rust/pull/72632 //! [attempt 4]: https://github.com/rust-lang/rust/pull/96451 -use rustc_data_structures::fx::FxIndexMap; use rustc_index::bit_set::DenseBitSet; use rustc_index::interval::SparseIntervalMatrix; use rustc_index::{IndexVec, newtype_index}; @@ -187,48 +186,47 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { let mut merged_locals = DenseBitSet::new_empty(body.local_decls.len()); - for (src, candidates) in candidates.c.into_iter() { - trace!(?src, ?candidates); - - for dst in candidates { - // We call `relevant.find(src)` inside the loop, as a previous iteration may have - // renamed `src` to one of the locals in `dst`. - let Some(mut src) = relevant.find(src) else { continue }; - let Some(src_live_ranges) = live.row(src) else { continue }; - trace!(?src, ?src_live_ranges); - - let Some(mut dst) = relevant.find(dst) else { continue }; - let Some(dst_live_ranges) = live.row(dst) else { continue }; - trace!(?dst, ?dst_live_ranges); - - if src_live_ranges.disjoint(dst_live_ranges) { - // We want to replace `src` by `dst`. - let mut orig_src = relevant.original[src]; - let mut orig_dst = relevant.original[dst]; - - // The return place and function arguments are required and cannot be renamed. - // This check cannot be made during candidate collection, as we may want to - // unify the same non-required local with several required locals. - match (is_local_required(orig_src, body), is_local_required(orig_dst, body)) { - // Renaming `src` is ok. - (false, _) => {} - // Renaming `src` is wrong, but renaming `dst` is ok. - (true, false) => { - std::mem::swap(&mut src, &mut dst); - std::mem::swap(&mut orig_src, &mut orig_dst); - } - // Neither local can be renamed, so skip this case. - (true, true) => continue, - } + for (src, dst) in candidates.c.into_iter() { + trace!(?src, ?dst); - trace!(?src, ?dst, "merge"); - merged_locals.insert(orig_src); - merged_locals.insert(orig_dst); + let Some(mut src) = relevant.find(src) else { continue }; + let Some(mut dst) = relevant.find(dst) else { continue }; + if src == dst { + continue; + } - // Replace `src` by `dst`. - relevant.union(src, dst); - live.union_rows(/* read */ src, /* write */ dst); + let Some(src_live_ranges) = live.row(src) else { continue }; + let Some(dst_live_ranges) = live.row(dst) else { continue }; + trace!(?src, ?src_live_ranges); + trace!(?dst, ?dst_live_ranges); + + if src_live_ranges.disjoint(dst_live_ranges) { + // We want to replace `src` by `dst`. + let mut orig_src = relevant.original[src]; + let mut orig_dst = relevant.original[dst]; + + // The return place and function arguments are required and cannot be renamed. + // This check cannot be made during candidate collection, as we may want to + // unify the same non-required local with several required locals. + match (is_local_required(orig_src, body), is_local_required(orig_dst, body)) { + // Renaming `src` is ok. + (false, _) => {} + // Renaming `src` is wrong, but renaming `dst` is ok. + (true, false) => { + std::mem::swap(&mut src, &mut dst); + std::mem::swap(&mut orig_src, &mut orig_dst); + } + // Neither local can be renamed, so skip this case. + (true, true) => continue, } + + trace!(?src, ?dst, "merge"); + merged_locals.insert(orig_src); + merged_locals.insert(orig_dst); + + // Replace `src` by `dst`. + relevant.union(src, dst); + live.union_rows(/* read */ src, /* write */ dst); } } trace!(?merged_locals); @@ -342,11 +340,9 @@ impl RelevantLocals { shrink.get_or_insert_with(local, || original.push(local)); }; - for (&src, destinations) in candidates.c.iter() { + for &(src, dest) in candidates.c.iter() { declare(src); - for &dest in destinations { - declare(dest) - } + declare(dest) } let renames = IndexVec::from_fn_n(|l| l, original.len()); @@ -388,8 +384,6 @@ impl RelevantLocals { struct Candidates { /// The set of candidates we are considering in this optimization. /// - /// We will always merge the key into at most one of its values. - /// /// Whether a place ends up in the key or the value does not correspond to whether it appears as /// the lhs or rhs of any assignment. As a matter of fact, the places in here might never appear /// in an assignment at all. This happens because if we see an assignment like this: @@ -400,7 +394,7 @@ struct Candidates { /// /// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to /// remove that assignment. - c: FxIndexMap<Local, Vec<Local>>, + c: Vec<(Local, Local)>, } // We first implement some utility functions which we will expose removing candidates according to @@ -414,19 +408,13 @@ impl Candidates { let mut visitor = FindAssignments { body, candidates: Default::default(), borrowed }; visitor.visit_body(body); - // Deduplicate candidates. - for (_, cands) in visitor.candidates.iter_mut() { - cands.sort(); - cands.dedup(); - } - Candidates { c: visitor.candidates } } } struct FindAssignments<'a, 'tcx> { body: &'a Body<'tcx>, - candidates: FxIndexMap<Local, Vec<Local>>, + candidates: Vec<(Local, Local)>, borrowed: &'a DenseBitSet<Local>, } @@ -456,7 +444,7 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> { } // We may insert duplicates here, but that's fine - self.candidates.entry(src).or_default().push(dest); + self.candidates.push((src, dest)); } } } |
