@@ -137,6 +137,7 @@ use crate::simplify::remove_dead_blocks;
137137use crate :: MirPass ;
138138use rustc_data_structures:: fx:: FxHashMap ;
139139use rustc_index:: bit_set:: BitSet ;
140+ use rustc_index:: interval:: SparseIntervalMatrix ;
140141use rustc_middle:: mir:: visit:: { MutVisitor , PlaceContext , Visitor } ;
141142use rustc_middle:: mir:: HasLocalDecls ;
142143use rustc_middle:: mir:: { dump_mir, PassWhere } ;
@@ -146,7 +147,8 @@ use rustc_middle::mir::{
146147} ;
147148use rustc_middle:: ty:: TyCtxt ;
148149use 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 ;
150152
151153pub struct DestinationPropagation ;
152154
@@ -170,6 +172,13 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
170172
171173 let borrowed = rustc_mir_dataflow:: impls:: borrowed_locals ( body) ;
172174
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+
173182 // In order to avoid having to collect data for every single pair of locals in the body, we
174183 // do not allow doing more than one merge for places that are derived from the same local at
175184 // 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 {
193202 & mut allocations. candidates_reverse ,
194203 ) ;
195204 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) ;
201206
202207 FilterInformation :: filter_liveness (
203208 & mut candidates,
204- & mut live,
209+ & points,
210+ & live,
205211 & mut allocations. write_info ,
206212 body,
207213 ) ;
208214
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.
212218 let mut merged_locals: BitSet < Local > = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
213219
214220 // 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 {
227233 } ) {
228234 break ;
229235 }
236+
237+ // Replace `src` by `dest` everywhere.
230238 merges. insert ( * src, * dest) ;
231239 merged_locals. insert ( * src) ;
232240 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) ;
233245 }
234246 trace ! ( merging = ?merges) ;
235247
@@ -358,7 +370,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
358370
359371struct FilterInformation < ' a , ' body , ' alloc , ' tcx > {
360372 body : & ' body Body < ' tcx > ,
361- live : & ' a mut ResultsCursor < ' body , ' tcx , MaybeLiveLocals > ,
373+ points : & ' a DenseLocationMap ,
374+ live : & ' a SparseIntervalMatrix < Local , PointIndex > ,
362375 candidates : & ' a mut Candidates < ' alloc > ,
363376 write_info : & ' alloc mut WriteInfo ,
364377 at : Location ,
@@ -461,12 +474,14 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
461474 /// locals as also being read from.
462475 fn filter_liveness < ' b > (
463476 candidates : & mut Candidates < ' alloc > ,
464- live : & mut ResultsCursor < ' b , ' tcx , MaybeLiveLocals > ,
477+ points : & DenseLocationMap ,
478+ live : & SparseIntervalMatrix < Local , PointIndex > ,
465479 write_info_alloc : & ' alloc mut WriteInfo ,
466480 body : & ' b Body < ' tcx > ,
467481 ) {
468482 let mut this = FilterInformation {
469483 body,
484+ points,
470485 live,
471486 candidates,
472487 // 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> {
481496 fn internal_filter_liveness ( & mut self ) {
482497 for ( block, data) in traversal:: preorder ( self . body ) {
483498 self . at = Location { block, statement_index : data. statements . len ( ) } ;
484- self . live . seek_after_primary_effect ( self . at ) ;
485499 self . write_info . for_terminator ( & data. terminator ( ) . kind ) ;
486500 self . apply_conflicts ( ) ;
487501
488502 for ( i, statement) in data. statements . iter ( ) . enumerate ( ) . rev ( ) {
489503 self . at = Location { block, statement_index : i } ;
490- self . live . seek_after_primary_effect ( self . at ) ;
491504 self . write_info . for_statement ( & statement. kind , self . body ) ;
492505 self . apply_conflicts ( ) ;
493506 }
@@ -506,6 +519,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
506519 None
507520 }
508521 } ) ;
522+ let at = self . points . point_from_location ( self . at ) ;
509523 self . candidates . filter_candidates_by (
510524 * p,
511525 |q| {
@@ -517,7 +531,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
517531 // calls or inline asm. Because of this, we also mark locals as
518532 // conflicting when both of them are written to in the same
519533 // statement.
520- if self . live . contains ( q) || writes. contains ( & q) {
534+ if self . live . contains ( q, at ) || writes. contains ( & q) {
521535 CandidateFilter :: Remove
522536 } else {
523537 CandidateFilter :: Keep
@@ -810,38 +824,17 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
810824fn dest_prop_mir_dump < ' body , ' tcx > (
811825 tcx : TyCtxt < ' tcx > ,
812826 body : & ' body Body < ' tcx > ,
813- live : & mut ResultsCursor < ' body , ' tcx , MaybeLiveLocals > ,
827+ points : & DenseLocationMap ,
828+ live : & SparseIntervalMatrix < Local , PointIndex > ,
814829 round : usize ,
815830) {
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+ } ;
817835 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) ) ?;
845838 }
846839
847840 Ok ( ( ) )
0 commit comments