@@ -100,10 +100,7 @@ use crate::{
100
100
transform:: { MirPass , MirSource } ,
101
101
util:: { dump_mir, PassWhere } ,
102
102
} ;
103
- use dataflow:: {
104
- impls:: { MaybeInitializedLocals , MaybeLiveLocals } ,
105
- ResultsCursor ,
106
- } ;
103
+ use dataflow:: impls:: { MaybeInitializedLocals , MaybeLiveLocals } ;
107
104
use rustc_data_structures:: unify:: { InPlaceUnificationTable , UnifyKey } ;
108
105
use rustc_index:: {
109
106
bit_set:: { BitMatrix , BitSet } ,
@@ -382,15 +379,11 @@ impl Conflicts {
382
379
body. local_decls . len ( ) ,
383
380
) ;
384
381
385
- let mut record_conflicts =
386
- |init : & ResultsCursor < ' _ , ' _ , _ > , live : & ResultsCursor < ' _ , ' _ , _ > | {
387
- let mut requires_storage = init. get ( ) . clone ( ) ;
388
- requires_storage. intersect ( live. get ( ) ) ;
389
-
390
- for local in requires_storage. iter ( ) {
391
- conflicts. union_row_with ( & requires_storage, local) ;
392
- }
393
- } ;
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
+ } ;
394
387
395
388
let def_id = source. def_id ( ) ;
396
389
let mut init = MaybeInitializedLocals
@@ -442,27 +435,50 @@ impl Conflicts {
442
435
} ,
443
436
) ;
444
437
438
+ let mut relevant_locals = Vec :: new ( ) ;
439
+
445
440
// Visit only reachable basic blocks. The exact order is not important.
446
441
for ( block, data) in traversal:: preorder ( body) {
447
- // Observe the dataflow state *before* all possible locations (statement or terminator) in
448
- // each basic block...
442
+ // We need to observe the dataflow state *before* all possible locations (statement or
443
+ // terminator) in each basic block, and then observe the state *after* the terminator
444
+ // effect is applied. As long as neither `init` nor `borrowed` has a "before" effect,
445
+ // we will observe all possible dataflow states.
446
+
447
+ // Since liveness is a backwards analysis, we need to walk the results backwards. To do
448
+ // that, we first collect in the `MaybeInitializedLocals` results in a forwards
449
+ // traversal.
450
+
451
+ relevant_locals. resize_with ( data. statements . len ( ) + 1 , || {
452
+ BitSet :: new_empty ( body. local_decls . len ( ) )
453
+ } ) ;
454
+
455
+ // First, go forwards for `MaybeInitializedLocals`.
449
456
for statement_index in 0 ..=data. statements . len ( ) {
450
457
let loc = Location { block, statement_index } ;
451
- trace ! ( "record conflicts at {:?}" , loc) ;
452
458
init. seek_before_primary_effect ( loc) ;
459
+
460
+ relevant_locals[ statement_index] . overwrite ( init. get ( ) ) ;
461
+ }
462
+
463
+ // Now, go backwards and union with the liveness results.
464
+ for statement_index in ( 0 ..=data. statements . len ( ) ) . rev ( ) {
465
+ let loc = Location { block, statement_index } ;
453
466
live. seek_after_primary_effect ( loc) ;
454
- // FIXME: liveness is backwards, so this is slow
455
467
456
- record_conflicts ( & init, & live) ;
468
+ relevant_locals[ statement_index] . intersect ( live. get ( ) ) ;
469
+
470
+ trace ! ( "record conflicts at {:?}" , loc) ;
471
+
472
+ record_conflicts ( & relevant_locals[ statement_index] ) ;
457
473
}
458
474
459
- // ...and then observe the state *after* the terminator effect is applied. As long as
460
- // neither `init` nor `borrowed` has a "before" effect, we will observe all possible
461
- // dataflow states here or in the loop above.
462
- trace ! ( "record conflicts at end of {:?}" , block) ;
463
475
init. seek_to_block_end ( block) ;
464
476
live. seek_to_block_end ( block) ;
465
- record_conflicts ( & init, & live) ;
477
+ let mut conflicts = init. get ( ) . clone ( ) ;
478
+ conflicts. intersect ( live. get ( ) ) ;
479
+ trace ! ( "record conflicts at end of {:?}" , block) ;
480
+
481
+ record_conflicts ( & conflicts) ;
466
482
}
467
483
468
484
Self { matrix : conflicts, unify_cache : BitSet :: new_empty ( body. local_decls . len ( ) ) }
0 commit comments