@@ -137,6 +137,7 @@ use crate::simplify::remove_dead_blocks;
137
137
use crate :: MirPass ;
138
138
use rustc_data_structures:: fx:: FxHashMap ;
139
139
use rustc_index:: bit_set:: BitSet ;
140
+ use rustc_index:: interval:: SparseIntervalMatrix ;
140
141
use rustc_middle:: mir:: visit:: { MutVisitor , PlaceContext , Visitor } ;
141
142
use rustc_middle:: mir:: HasLocalDecls ;
142
143
use rustc_middle:: mir:: { dump_mir, PassWhere } ;
@@ -146,7 +147,8 @@ use rustc_middle::mir::{
146
147
} ;
147
148
use rustc_middle:: ty:: TyCtxt ;
148
149
use rustc_mir_dataflow:: impls:: MaybeLiveLocals ;
149
- use rustc_mir_dataflow:: { Analysis , ResultsCursor } ;
150
+ use rustc_mir_dataflow:: points:: { save_as_intervals, DenseLocationMap , PointIndex } ;
151
+ use rustc_mir_dataflow:: Analysis ;
150
152
151
153
pub struct DestinationPropagation ;
152
154
@@ -170,6 +172,13 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
170
172
171
173
let borrowed = rustc_mir_dataflow:: impls:: borrowed_locals ( body) ;
172
174
175
+ let live = MaybeLiveLocals
176
+ . into_engine ( tcx, body)
177
+ . pass_name ( "MaybeLiveLocals-DestinationPropagation" )
178
+ . iterate_to_fixpoint ( ) ;
179
+ let points = DenseLocationMap :: new ( body) ;
180
+ let mut live = save_as_intervals ( & points, body, live) ;
181
+
173
182
// In order to avoid having to collect data for every single pair of locals in the body, we
174
183
// do not allow doing more than one merge for places that are derived from the same local at
175
184
// once. To avoid missed opportunities, we instead iterate to a fixed point - we'll refer to
@@ -193,22 +202,19 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
193
202
& mut allocations. candidates_reverse ,
194
203
) ;
195
204
trace ! ( ?candidates) ;
196
- let mut live = MaybeLiveLocals
197
- . into_engine ( tcx, body)
198
- . iterate_to_fixpoint ( )
199
- . into_results_cursor ( body) ;
200
- dest_prop_mir_dump ( tcx, body, & mut live, round_count) ;
205
+ dest_prop_mir_dump ( tcx, body, & points, & live, round_count) ;
201
206
202
207
FilterInformation :: filter_liveness (
203
208
& mut candidates,
204
- & mut live,
209
+ & points,
210
+ & live,
205
211
& mut allocations. write_info ,
206
212
body,
207
213
) ;
208
214
209
- // Because we do not update liveness information , it is unsound to use a local for more
210
- // than one merge operation within a single round of optimizations. We store here which
211
- // ones we have already used.
215
+ // Because we only filter once per round , it is unsound to use a local for more than
216
+ // one merge operation within a single round of optimizations. We store here which ones
217
+ // we have already used.
212
218
let mut merged_locals: BitSet < Local > = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
213
219
214
220
// This is the set of merges we will apply this round. It is a subset of the candidates.
@@ -227,9 +233,15 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
227
233
} ) {
228
234
break ;
229
235
}
236
+
237
+ // Replace `src` by `dest` everywhere.
230
238
merges. insert ( * src, * dest) ;
231
239
merged_locals. insert ( * src) ;
232
240
merged_locals. insert ( * dest) ;
241
+
242
+ // Update liveness information based on the merge we just performed.
243
+ // Every location where `src` was live, `dest` will be live.
244
+ live. union_rows ( * src, * dest) ;
233
245
}
234
246
trace ! ( merging = ?merges) ;
235
247
@@ -358,7 +370,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
358
370
359
371
struct FilterInformation < ' a , ' body , ' alloc , ' tcx > {
360
372
body : & ' body Body < ' tcx > ,
361
- live : & ' a mut ResultsCursor < ' body , ' tcx , MaybeLiveLocals > ,
373
+ points : & ' a DenseLocationMap ,
374
+ live : & ' a SparseIntervalMatrix < Local , PointIndex > ,
362
375
candidates : & ' a mut Candidates < ' alloc > ,
363
376
write_info : & ' alloc mut WriteInfo ,
364
377
at : Location ,
@@ -461,12 +474,14 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
461
474
/// locals as also being read from.
462
475
fn filter_liveness < ' b > (
463
476
candidates : & mut Candidates < ' alloc > ,
464
- live : & mut ResultsCursor < ' b , ' tcx , MaybeLiveLocals > ,
477
+ points : & DenseLocationMap ,
478
+ live : & SparseIntervalMatrix < Local , PointIndex > ,
465
479
write_info_alloc : & ' alloc mut WriteInfo ,
466
480
body : & ' b Body < ' tcx > ,
467
481
) {
468
482
let mut this = FilterInformation {
469
483
body,
484
+ points,
470
485
live,
471
486
candidates,
472
487
// We don't actually store anything at this scope, we just keep things here to be able
@@ -481,13 +496,11 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
481
496
fn internal_filter_liveness ( & mut self ) {
482
497
for ( block, data) in traversal:: preorder ( self . body ) {
483
498
self . at = Location { block, statement_index : data. statements . len ( ) } ;
484
- self . live . seek_after_primary_effect ( self . at ) ;
485
499
self . write_info . for_terminator ( & data. terminator ( ) . kind ) ;
486
500
self . apply_conflicts ( ) ;
487
501
488
502
for ( i, statement) in data. statements . iter ( ) . enumerate ( ) . rev ( ) {
489
503
self . at = Location { block, statement_index : i } ;
490
- self . live . seek_after_primary_effect ( self . at ) ;
491
504
self . write_info . for_statement ( & statement. kind , self . body ) ;
492
505
self . apply_conflicts ( ) ;
493
506
}
@@ -506,6 +519,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
506
519
None
507
520
}
508
521
} ) ;
522
+ let at = self . points . point_from_location ( self . at ) ;
509
523
self . candidates . filter_candidates_by (
510
524
* p,
511
525
|q| {
@@ -517,7 +531,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
517
531
// calls or inline asm. Because of this, we also mark locals as
518
532
// conflicting when both of them are written to in the same
519
533
// statement.
520
- if self . live . contains ( q) || writes. contains ( & q) {
534
+ if self . live . contains ( q, at ) || writes. contains ( & q) {
521
535
CandidateFilter :: Remove
522
536
} else {
523
537
CandidateFilter :: Keep
@@ -810,38 +824,17 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
810
824
fn dest_prop_mir_dump < ' body , ' tcx > (
811
825
tcx : TyCtxt < ' tcx > ,
812
826
body : & ' body Body < ' tcx > ,
813
- live : & mut ResultsCursor < ' body , ' tcx , MaybeLiveLocals > ,
827
+ points : & DenseLocationMap ,
828
+ live : & SparseIntervalMatrix < Local , PointIndex > ,
814
829
round : usize ,
815
830
) {
816
- let mut reachable = None ;
831
+ let locals_live_at = |location| {
832
+ let location = points. point_from_location ( location) ;
833
+ live. rows ( ) . filter ( |& r| live. contains ( r, location) ) . collect :: < Vec < _ > > ( )
834
+ } ;
817
835
dump_mir ( tcx, false , "DestinationPropagation-dataflow" , & round, body, |pass_where, w| {
818
- let reachable = reachable. get_or_insert_with ( || traversal:: reachable_as_bitset ( body) ) ;
819
-
820
- match pass_where {
821
- PassWhere :: BeforeLocation ( loc) if reachable. contains ( loc. block ) => {
822
- live. seek_after_primary_effect ( loc) ;
823
- writeln ! ( w, " // live: {:?}" , live. get( ) ) ?;
824
- }
825
- PassWhere :: AfterTerminator ( bb) if reachable. contains ( bb) => {
826
- let loc = body. terminator_loc ( bb) ;
827
- live. seek_before_primary_effect ( loc) ;
828
- writeln ! ( w, " // live: {:?}" , live. get( ) ) ?;
829
- }
830
-
831
- PassWhere :: BeforeBlock ( bb) if reachable. contains ( bb) => {
832
- live. seek_to_block_start ( bb) ;
833
- writeln ! ( w, " // live: {:?}" , live. get( ) ) ?;
834
- }
835
-
836
- PassWhere :: BeforeCFG | PassWhere :: AfterCFG | PassWhere :: AfterLocation ( _) => { }
837
-
838
- PassWhere :: BeforeLocation ( _) | PassWhere :: AfterTerminator ( _) => {
839
- writeln ! ( w, " // live: <unreachable>" ) ?;
840
- }
841
-
842
- PassWhere :: BeforeBlock ( _) => {
843
- writeln ! ( w, " // live: <unreachable>" ) ?;
844
- }
836
+ if let PassWhere :: BeforeLocation ( loc) = pass_where {
837
+ writeln ! ( w, " // live: {:?}" , locals_live_at( loc) ) ?;
845
838
}
846
839
847
840
Ok ( ( ) )
0 commit comments