137137//! [attempt 3]: https://github.com/rust-lang/rust/pull/72632
138138//! [attempt 4]: https://github.com/rust-lang/rust/pull/96451
139139
140+ use rustc_data_structures:: union_find:: UnionFind ;
140141use rustc_index:: bit_set:: DenseBitSet ;
141142use rustc_index:: interval:: SparseIntervalMatrix ;
142143use rustc_index:: { IndexVec , newtype_index} ;
@@ -217,13 +218,12 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
217218 merged_locals. insert ( orig_dst) ;
218219
219220 // Replace `src` by `dst`.
220- relevant. union ( src, dst) ;
221- live. union_rows ( /* read */ src, /* write */ dst) ;
221+ let head = relevant. union ( src, dst) ;
222+ live. union_rows ( /* read */ src, /* write */ head) ;
223+ live. union_rows ( /* read */ dst, /* write */ head) ;
222224 }
223225 }
224226 trace ! ( ?merged_locals) ;
225-
226- relevant. make_idempotent ( ) ;
227227 trace ! ( ?relevant. renames) ;
228228
229229 if merged_locals. is_empty ( ) {
@@ -318,7 +318,7 @@ newtype_index! {
318318struct RelevantLocals {
319319 original : IndexVec < RelevantLocal , Local > ,
320320 shrink : IndexVec < Local , Option < RelevantLocal > > ,
321- renames : IndexVec < RelevantLocal , RelevantLocal > ,
321+ renames : UnionFind < RelevantLocal > ,
322322}
323323
324324impl RelevantLocals {
@@ -337,35 +337,21 @@ impl RelevantLocals {
337337 declare ( dest)
338338 }
339339
340- let renames = IndexVec :: from_fn_n ( |l| l , original. len ( ) ) ;
340+ let renames = UnionFind :: new ( original. len ( ) ) ;
341341 RelevantLocals { original, shrink, renames }
342342 }
343343
344- fn find ( & self , src : Local ) -> Option < RelevantLocal > {
345- let mut src = self . shrink [ src] ?;
346- while let s2 = self . renames [ src]
347- && src != s2
348- {
349- src = s2
350- }
344+ fn find ( & mut self , src : Local ) -> Option < RelevantLocal > {
345+ let src = self . shrink [ src] ?;
346+ let src = self . renames . find ( src) ;
351347 Some ( src)
352348 }
353349
354- fn union ( & mut self , lhs : RelevantLocal , rhs : RelevantLocal ) {
355- self . renames [ lhs] = rhs;
356- }
357-
358- fn make_idempotent ( & mut self ) {
359- for l in self . renames . indices ( ) {
360- let mut h = self . renames [ l] ;
361- while let h2 = self . renames [ h]
362- && h != h2
363- {
364- h = h2
365- }
366- self . renames [ l] = h;
367- debug_assert_eq ! ( h, self . renames[ h] , "non-idempotent for {l:?}" ) ;
368- }
350+ fn union ( & mut self , lhs : RelevantLocal , rhs : RelevantLocal ) -> RelevantLocal {
351+ let head = self . renames . unify ( lhs, rhs) ;
352+ // We need to ensure we keep the original local of the RHS, as it may be a required local.
353+ self . original [ head] = self . original [ rhs] ;
354+ head
369355 }
370356}
371357
0 commit comments