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} ;
@@ -187,48 +186,47 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
187186
188187 let mut merged_locals = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
189188
190- for ( src, candidates) in candidates. c . into_iter ( ) {
191- trace ! ( ?src, ?candidates) ;
192-
193- for dst in candidates {
194- // We call `relevant.find(src)` inside the loop, as a previous iteration may have
195- // renamed `src` to one of the locals in `dst`.
196- let Some ( mut src) = relevant. find ( src) else { continue } ;
197- let Some ( src_live_ranges) = live. row ( src) else { continue } ;
198- trace ! ( ?src, ?src_live_ranges) ;
199-
200- let Some ( mut dst) = relevant. find ( dst) else { continue } ;
201- let Some ( dst_live_ranges) = live. row ( dst) else { continue } ;
202- trace ! ( ?dst, ?dst_live_ranges) ;
203-
204- if src_live_ranges. disjoint ( dst_live_ranges) {
205- // We want to replace `src` by `dst`.
206- let mut orig_src = relevant. original [ src] ;
207- let mut orig_dst = relevant. original [ dst] ;
208-
209- // The return place and function arguments are required and cannot be renamed.
210- // This check cannot be made during candidate collection, as we may want to
211- // unify the same non-required local with several required locals.
212- match ( is_local_required ( orig_src, body) , is_local_required ( orig_dst, body) ) {
213- // Renaming `src` is ok.
214- ( false , _) => { }
215- // Renaming `src` is wrong, but renaming `dst` is ok.
216- ( true , false ) => {
217- std:: mem:: swap ( & mut src, & mut dst) ;
218- std:: mem:: swap ( & mut orig_src, & mut orig_dst) ;
219- }
220- // Neither local can be renamed, so skip this case.
221- ( true , true ) => continue ,
222- }
189+ for ( src, dst) in candidates. c . into_iter ( ) {
190+ trace ! ( ?src, ?dst) ;
223191
224- trace ! ( ?src, ?dst, "merge" ) ;
225- merged_locals. insert ( orig_src) ;
226- merged_locals. insert ( orig_dst) ;
192+ let Some ( mut src) = relevant. find ( src) else { continue } ;
193+ let Some ( mut dst) = relevant. find ( dst) else { continue } ;
194+ if src == dst {
195+ continue ;
196+ }
227197
228- // Replace `src` by `dst`.
229- relevant. union ( src, dst) ;
230- live. union_rows ( /* read */ src, /* write */ dst) ;
198+ let Some ( src_live_ranges) = live. row ( src) else { continue } ;
199+ let Some ( dst_live_ranges) = live. row ( dst) else { continue } ;
200+ trace ! ( ?src, ?src_live_ranges) ;
201+ trace ! ( ?dst, ?dst_live_ranges) ;
202+
203+ if src_live_ranges. disjoint ( dst_live_ranges) {
204+ // We want to replace `src` by `dst`.
205+ let mut orig_src = relevant. original [ src] ;
206+ let mut orig_dst = relevant. original [ dst] ;
207+
208+ // The return place and function arguments are required and cannot be renamed.
209+ // This check cannot be made during candidate collection, as we may want to
210+ // unify the same non-required local with several required locals.
211+ match ( is_local_required ( orig_src, body) , is_local_required ( orig_dst, body) ) {
212+ // Renaming `src` is ok.
213+ ( false , _) => { }
214+ // Renaming `src` is wrong, but renaming `dst` is ok.
215+ ( true , false ) => {
216+ std:: mem:: swap ( & mut src, & mut dst) ;
217+ std:: mem:: swap ( & mut orig_src, & mut orig_dst) ;
218+ }
219+ // Neither local can be renamed, so skip this case.
220+ ( true , true ) => continue ,
231221 }
222+
223+ trace ! ( ?src, ?dst, "merge" ) ;
224+ merged_locals. insert ( orig_src) ;
225+ merged_locals. insert ( orig_dst) ;
226+
227+ // Replace `src` by `dst`.
228+ relevant. union ( src, dst) ;
229+ live. union_rows ( /* read */ src, /* write */ dst) ;
232230 }
233231 }
234232 trace ! ( ?merged_locals) ;
@@ -342,11 +340,9 @@ impl RelevantLocals {
342340 shrink. get_or_insert_with ( local, || original. push ( local) ) ;
343341 } ;
344342
345- for ( & src, destinations ) in candidates. c . iter ( ) {
343+ for & ( src, dest ) in candidates. c . iter ( ) {
346344 declare ( src) ;
347- for & dest in destinations {
348- declare ( dest)
349- }
345+ declare ( dest)
350346 }
351347
352348 let renames = IndexVec :: from_fn_n ( |l| l, original. len ( ) ) ;
@@ -388,8 +384,6 @@ impl RelevantLocals {
388384struct Candidates {
389385 /// The set of candidates we are considering in this optimization.
390386 ///
391- /// We will always merge the key into at most one of its values.
392- ///
393387 /// Whether a place ends up in the key or the value does not correspond to whether it appears as
394388 /// the lhs or rhs of any assignment. As a matter of fact, the places in here might never appear
395389 /// in an assignment at all. This happens because if we see an assignment like this:
@@ -400,7 +394,7 @@ struct Candidates {
400394 ///
401395 /// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to
402396 /// remove that assignment.
403- c : FxIndexMap < Local , Vec < Local > > ,
397+ c : Vec < ( Local , Local ) > ,
404398}
405399
406400// We first implement some utility functions which we will expose removing candidates according to
@@ -414,19 +408,13 @@ impl Candidates {
414408 let mut visitor = FindAssignments { body, candidates : Default :: default ( ) , borrowed } ;
415409 visitor. visit_body ( body) ;
416410
417- // Deduplicate candidates.
418- for ( _, cands) in visitor. candidates . iter_mut ( ) {
419- cands. sort ( ) ;
420- cands. dedup ( ) ;
421- }
422-
423411 Candidates { c : visitor. candidates }
424412 }
425413}
426414
427415struct FindAssignments < ' a , ' tcx > {
428416 body : & ' a Body < ' tcx > ,
429- candidates : FxIndexMap < Local , Vec < Local > > ,
417+ candidates : Vec < ( Local , Local ) > ,
430418 borrowed : & ' a DenseBitSet < Local > ,
431419}
432420
@@ -456,7 +444,7 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
456444 }
457445
458446 // We may insert duplicates here, but that's fine
459- self . candidates . entry ( src ) . or_default ( ) . push ( dest) ;
447+ self . candidates . push ( ( src , dest) ) ;
460448 }
461449 }
462450}
0 commit comments