@@ -162,10 +162,19 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
162
162
trace ! ( ?def_id) ;
163
163
164
164
let borrowed = rustc_mir_dataflow:: impls:: borrowed_locals ( body) ;
165
+ let points = DenseLocationMap :: new ( body) ;
166
+
167
+ candidates. reset_and_find ( body, & borrowed) ;
168
+ trace ! ( ?candidates) ;
169
+ if candidates. c . is_empty ( ) {
170
+ return ;
171
+ }
172
+
173
+ let relevant = RelevantLocals :: compute ( & candidates, body. local_decls . len ( ) ) ;
165
174
166
175
let live = MaybeLiveLocals . iterate_to_fixpoint ( tcx, body, Some ( "MaybeLiveLocals-DestProp" ) ) ;
167
- let points = DenseLocationMap :: new ( body ) ;
168
- let mut live = save_as_intervals ( & points, body, live. analysis , live. results ) ;
176
+ let mut live =
177
+ save_as_intervals ( & points, body, & relevant . original , live. analysis , live. results ) ;
169
178
170
179
// In order to avoid having to collect data for every single pair of locals in the body, we
171
180
// do not allow doing more than one merge for places that are derived from the same local at
@@ -181,22 +190,14 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
181
190
// https://github.com/rust-lang/regex/tree/b5372864e2df6a2f5e543a556a62197f50ca3650
182
191
let mut round_count = 0 ;
183
192
loop {
184
- // PERF: Can we do something smarter than recalculating the candidates and liveness
185
- // results?
186
- candidates. reset_and_find ( body, & borrowed) ;
187
- trace ! ( ?candidates) ;
188
- if candidates. c . is_empty ( ) {
189
- break ;
190
- }
191
-
192
- dest_prop_mir_dump ( tcx, body, & points, & live, round_count) ;
193
+ dest_prop_mir_dump ( tcx, body, & points, & live, & relevant, round_count) ;
193
194
194
195
let mut filter = FilterInformation :: filter_liveness (
195
196
& points,
196
197
& live,
197
198
& mut write_info,
198
199
body,
199
- & candidates ,
200
+ & relevant ,
200
201
) ;
201
202
202
203
// This is the set of merges we will apply this round. It is a subset of the candidates.
@@ -216,6 +217,10 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
216
217
merged_locals. insert ( src) ;
217
218
merged_locals. insert ( dest) ;
218
219
220
+ // `find_non_conflicting` ensures this is true.
221
+ let src = relevant. shrink [ src] . expect ( "merged locals are relevant" ) ;
222
+ let dest = relevant. shrink [ dest] . expect ( "merged locals are relevant" ) ;
223
+
219
224
// Update liveness information based on the merge we just performed.
220
225
// Every location where `src` was live, `dest` will be live.
221
226
live. union_rows ( src, dest) ;
@@ -232,6 +237,12 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
232
237
round_count += 1 ;
233
238
234
239
apply_merges ( body, tcx, merges, merged_locals) ;
240
+
241
+ candidates. reset_and_find ( body, & borrowed) ;
242
+ trace ! ( ?candidates) ;
243
+ if candidates. c . is_empty ( ) {
244
+ break ;
245
+ }
235
246
}
236
247
237
248
trace ! ( round_count) ;
@@ -373,7 +384,7 @@ impl RelevantLocals {
373
384
struct FilterInformation < ' a , ' tcx > {
374
385
body : & ' a Body < ' tcx > ,
375
386
points : & ' a DenseLocationMap ,
376
- relevant : RelevantLocals ,
387
+ relevant : & ' a RelevantLocals ,
377
388
conflicts : BitMatrix < RelevantLocal , RelevantLocal > ,
378
389
write_info : & ' a mut WriteInfo ,
379
390
at : Location ,
@@ -418,13 +429,11 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
418
429
/// locals as also being read from.
419
430
fn filter_liveness (
420
431
points : & ' a DenseLocationMap ,
421
- live : & SparseIntervalMatrix < Local , PointIndex > ,
432
+ live : & SparseIntervalMatrix < RelevantLocal , PointIndex > ,
422
433
write_info : & ' a mut WriteInfo ,
423
434
body : & ' a Body < ' tcx > ,
424
- candidates : & Candidates ,
435
+ relevant : & ' a RelevantLocals ,
425
436
) -> Self {
426
- let num_locals = body. local_decls . len ( ) ;
427
- let relevant = RelevantLocals :: compute ( candidates, num_locals) ;
428
437
let num_relevant = relevant. original . len ( ) ;
429
438
let mut this = FilterInformation {
430
439
body,
@@ -441,7 +450,7 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
441
450
this
442
451
}
443
452
444
- fn internal_filter_liveness ( & mut self , live : & SparseIntervalMatrix < Local , PointIndex > ) {
453
+ fn internal_filter_liveness ( & mut self , live : & SparseIntervalMatrix < RelevantLocal , PointIndex > ) {
445
454
for ( block, data) in traversal:: preorder ( self . body ) {
446
455
self . at = Location { block, statement_index : data. statements . len ( ) } ;
447
456
self . write_info . for_terminator ( & data. terminator ( ) . kind ) ;
@@ -457,7 +466,7 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
457
466
trace ! ( ?self . conflicts, "initial conflicts" ) ;
458
467
}
459
468
460
- fn record_conflicts ( & mut self , live : & SparseIntervalMatrix < Local , PointIndex > ) {
469
+ fn record_conflicts ( & mut self , live : & SparseIntervalMatrix < RelevantLocal , PointIndex > ) {
461
470
let writes = self . write_info . writes . iter ( ) . filter_map ( |& p| self . relevant . shrink [ p] ) ;
462
471
463
472
let skip_pair = self . write_info . skip_pair . and_then ( |( p, q) | {
@@ -475,11 +484,11 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
475
484
}
476
485
}
477
486
478
- for ( q , & original_q ) in self . relevant . original . iter_enumerated ( ) {
487
+ for q in self . relevant . original . indices ( ) {
479
488
if p != q
480
489
&& skip_pair != Some ( ( p, q) )
481
490
&& skip_pair != Some ( ( q, p) )
482
- && live. contains ( original_q , at)
491
+ && live. contains ( q , at)
483
492
{
484
493
self . conflicts . insert ( p, q) ;
485
494
}
@@ -488,21 +497,21 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
488
497
}
489
498
490
499
#[ tracing:: instrument( level = "trace" , skip( self ) ) ]
491
- fn record_merge ( & mut self , src : Local , dest : Local ) {
500
+ fn record_merge ( & mut self , src : RelevantLocal , dest : RelevantLocal ) {
492
501
trace ! ( ?self . conflicts, "pre" ) ;
493
- let src = self . relevant . shrink [ src] . expect ( "merged locals are relevant" ) ;
494
- let dest = self . relevant . shrink [ dest] . expect ( "merged locals are relevant" ) ;
495
502
self . conflicts . union_rows ( src, dest) ;
496
503
self . conflicts . union_cols ( src, dest) ;
497
504
trace ! ( ?self . conflicts, "post" ) ;
498
505
}
499
506
500
507
#[ tracing:: instrument( level = "trace" , skip( self ) , ret) ]
501
508
fn find_non_conflicting ( & self , src : Local , candidates : & Vec < Local > ) -> Option < Local > {
502
- let src = self . relevant . shrink [ src] . expect ( "merged locals are relevant" ) ;
509
+ // Refuse to merge if the local is not marked relevant.
510
+ let src = self . relevant . shrink [ src] ?;
503
511
candidates. iter ( ) . copied ( ) . find ( |& dest| {
504
- let dest = self . relevant . shrink [ dest] . expect ( "merged locals are relevant" ) ;
505
- !self . conflicts . contains ( src, dest) && !self . conflicts . contains ( dest, src)
512
+ self . relevant . shrink [ dest] . is_some_and ( |dest| {
513
+ !self . conflicts . contains ( src, dest) && !self . conflicts . contains ( dest, src)
514
+ } )
506
515
} )
507
516
}
508
517
}
@@ -773,12 +782,16 @@ fn dest_prop_mir_dump<'tcx>(
773
782
tcx : TyCtxt < ' tcx > ,
774
783
body : & Body < ' tcx > ,
775
784
points : & DenseLocationMap ,
776
- live : & SparseIntervalMatrix < Local , PointIndex > ,
785
+ live : & SparseIntervalMatrix < RelevantLocal , PointIndex > ,
786
+ relevant : & RelevantLocals ,
777
787
round : usize ,
778
788
) {
779
789
let locals_live_at = |location| {
780
790
let location = points. point_from_location ( location) ;
781
- live. rows ( ) . filter ( |& r| live. contains ( r, location) ) . collect :: < Vec < _ > > ( )
791
+ live. rows ( )
792
+ . filter ( |& r| live. contains ( r, location) )
793
+ . map ( |rl| relevant. original [ rl] )
794
+ . collect :: < Vec < _ > > ( )
782
795
} ;
783
796
dump_mir ( tcx, false , "DestinationPropagation-dataflow" , & round, body, |pass_where, w| {
784
797
if let PassWhere :: BeforeLocation ( loc) = pass_where {
0 commit comments