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:: fx:: FxIndexMap ;
141140use rustc_index:: bit_set:: DenseBitSet ;
142141use rustc_index:: interval:: SparseIntervalMatrix ;
143142use rustc_index:: { IndexVec , newtype_index} ;
@@ -179,48 +178,47 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
179178
180179 let mut merged_locals = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
181180
182- for ( src, candidates) in candidates. c . into_iter ( ) {
183- trace ! ( ?src, ?candidates) ;
184-
185- for dst in candidates {
186- // We call `relevant.find(src)` inside the loop, as a previous iteration may have
187- // renamed `src` to one of the locals in `dst`.
188- let Some ( mut src) = relevant. find ( src) else { continue } ;
189- let Some ( src_live_ranges) = live. row ( src) else { continue } ;
190- trace ! ( ?src, ?src_live_ranges) ;
191-
192- let Some ( mut dst) = relevant. find ( dst) else { continue } ;
193- let Some ( dst_live_ranges) = live. row ( dst) else { continue } ;
194- trace ! ( ?dst, ?dst_live_ranges) ;
195-
196- if src_live_ranges. disjoint ( dst_live_ranges) {
197- // We want to replace `src` by `dst`.
198- let mut orig_src = relevant. original [ src] ;
199- let mut orig_dst = relevant. original [ dst] ;
200-
201- // The return place and function arguments are required and cannot be renamed.
202- // This check cannot be made during candidate collection, as we may want to
203- // unify the same non-required local with several required locals.
204- match ( is_local_required ( orig_src, body) , is_local_required ( orig_dst, body) ) {
205- // Renaming `src` is ok.
206- ( false , _) => { }
207- // Renaming `src` is wrong, but renaming `dst` is ok.
208- ( true , false ) => {
209- std:: mem:: swap ( & mut src, & mut dst) ;
210- std:: mem:: swap ( & mut orig_src, & mut orig_dst) ;
211- }
212- // Neither local can be renamed, so skip this case.
213- ( true , true ) => continue ,
214- }
181+ for ( src, dst) in candidates. c . into_iter ( ) {
182+ trace ! ( ?src, ?dst) ;
215183
216- trace ! ( ?src, ?dst, "merge" ) ;
217- merged_locals. insert ( orig_src) ;
218- merged_locals. insert ( orig_dst) ;
184+ let Some ( mut src) = relevant. find ( src) else { continue } ;
185+ let Some ( mut dst) = relevant. find ( dst) else { continue } ;
186+ if src == dst {
187+ continue ;
188+ }
219189
220- // Replace `src` by `dst`.
221- relevant. union ( src, dst) ;
222- live. union_rows ( /* read */ src, /* write */ dst) ;
190+ let Some ( src_live_ranges) = live. row ( src) else { continue } ;
191+ let Some ( dst_live_ranges) = live. row ( dst) else { continue } ;
192+ trace ! ( ?src, ?src_live_ranges) ;
193+ trace ! ( ?dst, ?dst_live_ranges) ;
194+
195+ if src_live_ranges. disjoint ( dst_live_ranges) {
196+ // We want to replace `src` by `dst`.
197+ let mut orig_src = relevant. original [ src] ;
198+ let mut orig_dst = relevant. original [ dst] ;
199+
200+ // The return place and function arguments are required and cannot be renamed.
201+ // This check cannot be made during candidate collection, as we may want to
202+ // unify the same non-required local with several required locals.
203+ match ( is_local_required ( orig_src, body) , is_local_required ( orig_dst, body) ) {
204+ // Renaming `src` is ok.
205+ ( false , _) => { }
206+ // Renaming `src` is wrong, but renaming `dst` is ok.
207+ ( true , false ) => {
208+ std:: mem:: swap ( & mut src, & mut dst) ;
209+ std:: mem:: swap ( & mut orig_src, & mut orig_dst) ;
210+ }
211+ // Neither local can be renamed, so skip this case.
212+ ( true , true ) => continue ,
223213 }
214+
215+ trace ! ( ?src, ?dst, "merge" ) ;
216+ merged_locals. insert ( orig_src) ;
217+ merged_locals. insert ( orig_dst) ;
218+
219+ // Replace `src` by `dst`.
220+ relevant. union ( src, dst) ;
221+ live. union_rows ( /* read */ src, /* write */ dst) ;
224222 }
225223 }
226224 trace ! ( ?merged_locals) ;
@@ -334,11 +332,9 @@ impl RelevantLocals {
334332 shrink. get_or_insert_with ( local, || original. push ( local) ) ;
335333 } ;
336334
337- for ( & src, destinations ) in candidates. c . iter ( ) {
335+ for & ( src, dest ) in candidates. c . iter ( ) {
338336 declare ( src) ;
339- for & dest in destinations {
340- declare ( dest)
341- }
337+ declare ( dest)
342338 }
343339
344340 let renames = IndexVec :: from_fn_n ( |l| l, original. len ( ) ) ;
@@ -380,8 +376,6 @@ impl RelevantLocals {
380376struct Candidates {
381377 /// The set of candidates we are considering in this optimization.
382378 ///
383- /// We will always merge the key into at most one of its values.
384- ///
385379 /// Whether a place ends up in the key or the value does not correspond to whether it appears as
386380 /// the lhs or rhs of any assignment. As a matter of fact, the places in here might never appear
387381 /// in an assignment at all. This happens because if we see an assignment like this:
@@ -392,7 +386,7 @@ struct Candidates {
392386 ///
393387 /// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to
394388 /// remove that assignment.
395- c : FxIndexMap < Local , Vec < Local > > ,
389+ c : Vec < ( Local , Local ) > ,
396390}
397391
398392// We first implement some utility functions which we will expose removing candidates according to
@@ -406,19 +400,13 @@ impl Candidates {
406400 let mut visitor = FindAssignments { body, candidates : Default :: default ( ) , borrowed } ;
407401 visitor. visit_body ( body) ;
408402
409- // Deduplicate candidates.
410- for ( _, cands) in visitor. candidates . iter_mut ( ) {
411- cands. sort ( ) ;
412- cands. dedup ( ) ;
413- }
414-
415403 Candidates { c : visitor. candidates }
416404 }
417405}
418406
419407struct FindAssignments < ' a , ' tcx > {
420408 body : & ' a Body < ' tcx > ,
421- candidates : FxIndexMap < Local , Vec < Local > > ,
409+ candidates : Vec < ( Local , Local ) > ,
422410 borrowed : & ' a DenseBitSet < Local > ,
423411}
424412
@@ -448,7 +436,7 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
448436 }
449437
450438 // We may insert duplicates here, but that's fine
451- self . candidates . entry ( src ) . or_default ( ) . push ( dest) ;
439+ self . candidates . push ( ( src , dest) ) ;
452440 }
453441 }
454442}
0 commit comments