@@ -100,10 +100,7 @@ use crate::{
100100 transform:: { MirPass , MirSource } ,
101101 util:: { dump_mir, PassWhere } ,
102102} ;
103- use dataflow:: {
104- impls:: { MaybeInitializedLocals , MaybeLiveLocals } ,
105- ResultsCursor ,
106- } ;
103+ use dataflow:: impls:: { MaybeInitializedLocals , MaybeLiveLocals } ;
107104use rustc_data_structures:: unify:: { InPlaceUnificationTable , UnifyKey } ;
108105use rustc_index:: {
109106 bit_set:: { BitMatrix , BitSet } ,
@@ -382,16 +379,11 @@ impl Conflicts {
382379 body. local_decls . len ( ) ,
383380 ) ;
384381
385- let mut record_conflicts =
386- |init : & ResultsCursor < ' _ , ' _ , MaybeInitializedLocals > ,
387- live : & ResultsCursor < ' _ , ' _ , MaybeLiveLocals > | {
388- let mut requires_storage = init. get ( ) . clone ( ) ;
389- requires_storage. intersect ( live. get ( ) ) ;
390-
391- for local in requires_storage. iter ( ) {
392- conflicts. union_row_with ( & requires_storage, local) ;
393- }
394- } ;
382+ let mut record_conflicts = |new_conflicts : & BitSet < _ > | {
383+ for local in new_conflicts. iter ( ) {
384+ conflicts. union_row_with ( & new_conflicts, local) ;
385+ }
386+ } ;
395387
396388 let def_id = source. def_id ( ) ;
397389 let mut init = MaybeInitializedLocals
@@ -457,27 +449,50 @@ impl Conflicts {
457449 } ,
458450 ) ;
459451
452+ let mut relevant_locals = Vec :: new ( ) ;
453+
460454 // Visit only reachable basic blocks. The exact order is not important.
461455 for ( block, data) in traversal:: preorder ( body) {
462- // Observe the dataflow state *before* all possible locations (statement or terminator) in
463- // each basic block...
456+ // We need to observe the dataflow state *before* all possible locations (statement or
457+ // terminator) in each basic block, and then observe the state *after* the terminator
458+ // effect is applied. As long as neither `init` nor `borrowed` has a "before" effect,
459+ // we will observe all possible dataflow states.
460+
461+ // Since liveness is a backwards analysis, we need to walk the results backwards. To do
462+ // that, we first collect in the `MaybeInitializedLocals` results in a forwards
463+ // traversal.
464+
465+ relevant_locals. resize_with ( data. statements . len ( ) + 1 , || {
466+ BitSet :: new_empty ( body. local_decls . len ( ) )
467+ } ) ;
468+
469+ // First, go forwards for `MaybeInitializedLocals`.
464470 for statement_index in 0 ..=data. statements . len ( ) {
465471 let loc = Location { block, statement_index } ;
466- trace ! ( "record conflicts at {:?}" , loc) ;
467472 init. seek_before_primary_effect ( loc) ;
473+
474+ relevant_locals[ statement_index] . clone_from ( init. get ( ) ) ;
475+ }
476+
477+ // Now, go backwards and union with the liveness results.
478+ for statement_index in ( 0 ..=data. statements . len ( ) ) . rev ( ) {
479+ let loc = Location { block, statement_index } ;
468480 live. seek_after_primary_effect ( loc) ;
469- // FIXME: liveness is backwards, so this is slow
470481
471- record_conflicts ( & init, & live) ;
482+ relevant_locals[ statement_index] . intersect ( live. get ( ) ) ;
483+
484+ trace ! ( "record conflicts at {:?}" , loc) ;
485+
486+ record_conflicts ( & relevant_locals[ statement_index] ) ;
472487 }
473488
474- // ...and then observe the state *after* the terminator effect is applied. As long as
475- // neither `init` nor `borrowed` has a "before" effect, we will observe all possible
476- // dataflow states here or in the loop above.
477- trace ! ( "record conflicts at end of {:?}" , block) ;
478489 init. seek_to_block_end ( block) ;
479490 live. seek_to_block_end ( block) ;
480- record_conflicts ( & init, & live) ;
491+ let mut conflicts = init. get ( ) . clone ( ) ;
492+ conflicts. intersect ( live. get ( ) ) ;
493+ trace ! ( "record conflicts at end of {:?}" , block) ;
494+
495+ record_conflicts ( & conflicts) ;
481496 }
482497
483498 Self { matrix : conflicts, unify_cache : BitSet :: new_empty ( body. local_decls . len ( ) ) }
0 commit comments