134
134
use crate :: MirPass ;
135
135
use rustc_data_structures:: fx:: { FxIndexMap , IndexEntry , IndexOccupiedEntry } ;
136
136
use rustc_index:: bit_set:: BitSet ;
137
+ use rustc_index:: interval:: SparseIntervalMatrix ;
137
138
use rustc_middle:: mir:: visit:: { MutVisitor , PlaceContext , Visitor } ;
138
139
use rustc_middle:: mir:: HasLocalDecls ;
139
140
use rustc_middle:: mir:: { dump_mir, PassWhere } ;
@@ -143,7 +144,8 @@ use rustc_middle::mir::{
143
144
} ;
144
145
use rustc_middle:: ty:: TyCtxt ;
145
146
use rustc_mir_dataflow:: impls:: MaybeLiveLocals ;
146
- use rustc_mir_dataflow:: { Analysis , ResultsCursor } ;
147
+ use rustc_mir_dataflow:: points:: { save_as_intervals, DenseLocationMap , PointIndex } ;
148
+ use rustc_mir_dataflow:: Analysis ;
147
149
148
150
pub struct DestinationPropagation ;
149
151
@@ -167,6 +169,13 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
167
169
168
170
let borrowed = rustc_mir_dataflow:: impls:: borrowed_locals ( body) ;
169
171
172
+ let live = MaybeLiveLocals
173
+ . into_engine ( tcx, body)
174
+ . pass_name ( "MaybeLiveLocals-DestinationPropagation" )
175
+ . iterate_to_fixpoint ( ) ;
176
+ let points = DenseLocationMap :: new ( body) ;
177
+ let mut live = save_as_intervals ( & points, body, live) ;
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
172
181
// once. To avoid missed opportunities, we instead iterate to a fixed point - we'll refer to
@@ -190,22 +199,19 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
190
199
& mut allocations. candidates_reverse ,
191
200
) ;
192
201
trace ! ( ?candidates) ;
193
- let mut live = MaybeLiveLocals
194
- . into_engine ( tcx, body)
195
- . iterate_to_fixpoint ( )
196
- . into_results_cursor ( body) ;
197
- dest_prop_mir_dump ( tcx, body, & mut live, round_count) ;
202
+ dest_prop_mir_dump ( tcx, body, & points, & live, round_count) ;
198
203
199
204
FilterInformation :: filter_liveness (
200
205
& mut candidates,
201
- & mut live,
206
+ & points,
207
+ & live,
202
208
& mut allocations. write_info ,
203
209
body,
204
210
) ;
205
211
206
- // Because we do not update liveness information , it is unsound to use a local for more
207
- // than one merge operation within a single round of optimizations. We store here which
208
- // ones we have already used.
212
+ // Because we only filter once per round , it is unsound to use a local for more than
213
+ // one merge operation within a single round of optimizations. We store here which ones
214
+ // we have already used.
209
215
let mut merged_locals: BitSet < Local > = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
210
216
211
217
// This is the set of merges we will apply this round. It is a subset of the candidates.
@@ -224,9 +230,15 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
224
230
} ) {
225
231
break ;
226
232
}
233
+
234
+ // Replace `src` by `dest` everywhere.
227
235
merges. insert ( * src, * dest) ;
228
236
merged_locals. insert ( * src) ;
229
237
merged_locals. insert ( * dest) ;
238
+
239
+ // Update liveness information based on the merge we just performed.
240
+ // Every location where `src` was live, `dest` will be live.
241
+ live. union_rows ( * src, * dest) ;
230
242
}
231
243
trace ! ( merging = ?merges) ;
232
244
@@ -349,7 +361,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
349
361
350
362
struct FilterInformation < ' a , ' body , ' alloc , ' tcx > {
351
363
body : & ' body Body < ' tcx > ,
352
- live : & ' a mut ResultsCursor < ' body , ' tcx , MaybeLiveLocals > ,
364
+ points : & ' a DenseLocationMap ,
365
+ live : & ' a SparseIntervalMatrix < Local , PointIndex > ,
353
366
candidates : & ' a mut Candidates < ' alloc > ,
354
367
write_info : & ' alloc mut WriteInfo ,
355
368
at : Location ,
@@ -452,12 +465,14 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
452
465
/// locals as also being read from.
453
466
fn filter_liveness < ' b > (
454
467
candidates : & mut Candidates < ' alloc > ,
455
- live : & mut ResultsCursor < ' b , ' tcx , MaybeLiveLocals > ,
468
+ points : & DenseLocationMap ,
469
+ live : & SparseIntervalMatrix < Local , PointIndex > ,
456
470
write_info_alloc : & ' alloc mut WriteInfo ,
457
471
body : & ' b Body < ' tcx > ,
458
472
) {
459
473
let mut this = FilterInformation {
460
474
body,
475
+ points,
461
476
live,
462
477
candidates,
463
478
// We don't actually store anything at this scope, we just keep things here to be able
@@ -472,13 +487,11 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
472
487
fn internal_filter_liveness ( & mut self ) {
473
488
for ( block, data) in traversal:: preorder ( self . body ) {
474
489
self . at = Location { block, statement_index : data. statements . len ( ) } ;
475
- self . live . seek_after_primary_effect ( self . at ) ;
476
490
self . write_info . for_terminator ( & data. terminator ( ) . kind ) ;
477
491
self . apply_conflicts ( ) ;
478
492
479
493
for ( i, statement) in data. statements . iter ( ) . enumerate ( ) . rev ( ) {
480
494
self . at = Location { block, statement_index : i } ;
481
- self . live . seek_after_primary_effect ( self . at ) ;
482
495
self . write_info . for_statement ( & statement. kind , self . body ) ;
483
496
self . apply_conflicts ( ) ;
484
497
}
@@ -497,6 +510,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
497
510
None
498
511
}
499
512
} ) ;
513
+ let at = self . points . point_from_location ( self . at ) ;
500
514
self . candidates . filter_candidates_by (
501
515
* p,
502
516
|q| {
@@ -508,7 +522,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
508
522
// calls or inline asm. Because of this, we also mark locals as
509
523
// conflicting when both of them are written to in the same
510
524
// statement.
511
- if self . live . contains ( q) || writes. contains ( & q) {
525
+ if self . live . contains ( q, at ) || writes. contains ( & q) {
512
526
CandidateFilter :: Remove
513
527
} else {
514
528
CandidateFilter :: Keep
@@ -801,38 +815,17 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
801
815
fn dest_prop_mir_dump < ' body , ' tcx > (
802
816
tcx : TyCtxt < ' tcx > ,
803
817
body : & ' body Body < ' tcx > ,
804
- live : & mut ResultsCursor < ' body , ' tcx , MaybeLiveLocals > ,
818
+ points : & DenseLocationMap ,
819
+ live : & SparseIntervalMatrix < Local , PointIndex > ,
805
820
round : usize ,
806
821
) {
807
- let mut reachable = None ;
822
+ let locals_live_at = |location| {
823
+ let location = points. point_from_location ( location) ;
824
+ live. rows ( ) . filter ( |& r| live. contains ( r, location) ) . collect :: < Vec < _ > > ( )
825
+ } ;
808
826
dump_mir ( tcx, false , "DestinationPropagation-dataflow" , & round, body, |pass_where, w| {
809
- let reachable = reachable. get_or_insert_with ( || traversal:: reachable_as_bitset ( body) ) ;
810
-
811
- match pass_where {
812
- PassWhere :: BeforeLocation ( loc) if reachable. contains ( loc. block ) => {
813
- live. seek_after_primary_effect ( loc) ;
814
- writeln ! ( w, " // live: {:?}" , live. get( ) ) ?;
815
- }
816
- PassWhere :: AfterTerminator ( bb) if reachable. contains ( bb) => {
817
- let loc = body. terminator_loc ( bb) ;
818
- live. seek_before_primary_effect ( loc) ;
819
- writeln ! ( w, " // live: {:?}" , live. get( ) ) ?;
820
- }
821
-
822
- PassWhere :: BeforeBlock ( bb) if reachable. contains ( bb) => {
823
- live. seek_to_block_start ( bb) ;
824
- writeln ! ( w, " // live: {:?}" , live. get( ) ) ?;
825
- }
826
-
827
- PassWhere :: BeforeCFG | PassWhere :: AfterCFG | PassWhere :: AfterLocation ( _) => { }
828
-
829
- PassWhere :: BeforeLocation ( _) | PassWhere :: AfterTerminator ( _) => {
830
- writeln ! ( w, " // live: <unreachable>" ) ?;
831
- }
832
-
833
- PassWhere :: BeforeBlock ( _) => {
834
- writeln ! ( w, " // live: <unreachable>" ) ?;
835
- }
827
+ if let PassWhere :: BeforeLocation ( loc) = pass_where {
828
+ writeln ! ( w, " // live: {:?}" , locals_live_at( loc) ) ?;
836
829
}
837
830
838
831
Ok ( ( ) )
0 commit comments