137
137
//! [attempt 3]: https://github.com/rust-lang/rust/pull/72632
138
138
//! [attempt 4]: https://github.com/rust-lang/rust/pull/96451
139
139
140
+ use rustc_data_structures:: union_find:: UnionFind ;
140
141
use rustc_index:: bit_set:: DenseBitSet ;
141
142
use rustc_index:: interval:: SparseIntervalMatrix ;
142
143
use rustc_index:: { IndexVec , newtype_index} ;
@@ -217,13 +218,16 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
217
218
merged_locals. insert ( orig_dst) ;
218
219
219
220
// 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
+ if head != src {
223
+ live. union_rows ( /* read */ src, /* write */ head) ;
224
+ }
225
+ if head != dst {
226
+ live. union_rows ( /* read */ dst, /* write */ head) ;
227
+ }
222
228
}
223
229
}
224
230
trace ! ( ?merged_locals) ;
225
-
226
- relevant. make_idempotent ( ) ;
227
231
trace ! ( ?relevant. renames) ;
228
232
229
233
if merged_locals. is_empty ( ) {
@@ -318,7 +322,7 @@ newtype_index! {
318
322
struct RelevantLocals {
319
323
original : IndexVec < RelevantLocal , Local > ,
320
324
shrink : IndexVec < Local , Option < RelevantLocal > > ,
321
- renames : IndexVec < RelevantLocal , RelevantLocal > ,
325
+ renames : UnionFind < RelevantLocal > ,
322
326
}
323
327
324
328
impl RelevantLocals {
@@ -337,35 +341,21 @@ impl RelevantLocals {
337
341
declare ( dest)
338
342
}
339
343
340
- let renames = IndexVec :: from_fn_n ( |l| l , original. len ( ) ) ;
344
+ let renames = UnionFind :: new ( original. len ( ) ) ;
341
345
RelevantLocals { original, shrink, renames }
342
346
}
343
347
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
- }
348
+ fn find ( & mut self , src : Local ) -> Option < RelevantLocal > {
349
+ let src = self . shrink [ src] ?;
350
+ let src = self . renames . find ( src) ;
351
351
Some ( src)
352
352
}
353
353
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
- }
354
+ fn union ( & mut self , lhs : RelevantLocal , rhs : RelevantLocal ) -> RelevantLocal {
355
+ let head = self . renames . unify ( lhs, rhs) ;
356
+ // We need to ensure we keep the original local of the RHS, as it may be a required local.
357
+ self . original [ head] = self . original [ rhs] ;
358
+ head
369
359
}
370
360
}
371
361
0 commit comments