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:: fx:: FxIndexMap ;
141
140
use rustc_index:: bit_set:: DenseBitSet ;
142
141
use rustc_index:: interval:: SparseIntervalMatrix ;
143
142
use rustc_index:: { IndexVec , newtype_index} ;
@@ -179,48 +178,47 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
179
178
180
179
let mut merged_locals = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
181
180
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) ;
215
183
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
+ }
219
189
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 ,
223
213
}
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) ;
224
222
}
225
223
}
226
224
trace ! ( ?merged_locals) ;
@@ -334,11 +332,9 @@ impl RelevantLocals {
334
332
shrink. get_or_insert_with ( local, || original. push ( local) ) ;
335
333
} ;
336
334
337
- for ( & src, destinations ) in candidates. c . iter ( ) {
335
+ for & ( src, dest ) in candidates. c . iter ( ) {
338
336
declare ( src) ;
339
- for & dest in destinations {
340
- declare ( dest)
341
- }
337
+ declare ( dest)
342
338
}
343
339
344
340
let renames = IndexVec :: from_fn_n ( |l| l, original. len ( ) ) ;
@@ -392,7 +388,7 @@ struct Candidates {
392
388
///
393
389
/// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to
394
390
/// remove that assignment.
395
- c : FxIndexMap < Local , Vec < Local > > ,
391
+ c : Vec < ( Local , Local ) > ,
396
392
}
397
393
398
394
// We first implement some utility functions which we will expose removing candidates according to
@@ -406,19 +402,13 @@ impl Candidates {
406
402
let mut visitor = FindAssignments { body, candidates : Default :: default ( ) , borrowed } ;
407
403
visitor. visit_body ( body) ;
408
404
409
- // Deduplicate candidates.
410
- for ( _, cands) in visitor. candidates . iter_mut ( ) {
411
- cands. sort ( ) ;
412
- cands. dedup ( ) ;
413
- }
414
-
415
405
Candidates { c : visitor. candidates }
416
406
}
417
407
}
418
408
419
409
struct FindAssignments < ' a , ' tcx > {
420
410
body : & ' a Body < ' tcx > ,
421
- candidates : FxIndexMap < Local , Vec < Local > > ,
411
+ candidates : Vec < ( Local , Local ) > ,
422
412
borrowed : & ' a DenseBitSet < Local > ,
423
413
}
424
414
@@ -448,7 +438,7 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
448
438
}
449
439
450
440
// We may insert duplicates here, but that's fine
451
- self . candidates . entry ( src ) . or_default ( ) . push ( dest) ;
441
+ self . candidates . push ( ( src , dest) ) ;
452
442
}
453
443
}
454
444
}
0 commit comments