50
50
//! Otherwise it drops all the values in scope at the last suspension point.
51
51
52
52
use crate :: dataflow:: { self , Analysis } ;
53
- use crate :: dataflow:: { MaybeBorrowedLocals , MaybeRequiresStorage , MaybeStorageLive } ;
53
+ use crate :: dataflow:: {
54
+ MaybeBorrowedLocals , MaybeLiveLocals , MaybeRequiresStorage , MaybeStorageLive ,
55
+ } ;
54
56
use crate :: transform:: no_landing_pads:: no_landing_pads;
55
57
use crate :: transform:: simplify;
56
58
use crate :: transform:: { MirPass , MirSource } ;
57
59
use crate :: util:: dump_mir;
58
- use crate :: util:: liveness;
59
60
use crate :: util:: storage;
60
61
use rustc_data_structures:: fx:: FxHashMap ;
61
62
use rustc_hir as hir;
@@ -195,7 +196,7 @@ struct SuspensionPoint<'tcx> {
195
196
/// Which block to jump to if the generator is dropped in this state.
196
197
drop : Option < BasicBlock > ,
197
198
/// Set of locals that have live storage while at this suspension point.
198
- storage_liveness : liveness :: LiveVarSet ,
199
+ storage_liveness : BitSet < Local > ,
199
200
}
200
201
201
202
struct TransformVisitor < ' tcx > {
@@ -211,7 +212,7 @@ struct TransformVisitor<'tcx> {
211
212
remap : FxHashMap < Local , ( Ty < ' tcx > , VariantIdx , usize ) > ,
212
213
213
214
// A map from a suspension point in a block to the locals which have live storage at that point
214
- storage_liveness : IndexVec < BasicBlock , Option < liveness :: LiveVarSet > > ,
215
+ storage_liveness : IndexVec < BasicBlock , Option < BitSet < Local > > > ,
215
216
216
217
// A list of suspension points, generated during the transform
217
218
suspension_points : Vec < SuspensionPoint < ' tcx > > ,
@@ -418,7 +419,7 @@ struct LivenessInfo {
418
419
/// GeneratorSavedLocal is indexed in terms of the elements in this set;
419
420
/// i.e. GeneratorSavedLocal::new(1) corresponds to the second local
420
421
/// included in this set.
421
- live_locals : liveness :: LiveVarSet ,
422
+ live_locals : BitSet < Local > ,
422
423
423
424
/// The set of saved locals live at each suspension point.
424
425
live_locals_at_suspension_points : Vec < BitSet < GeneratorSavedLocal > > ,
@@ -430,7 +431,7 @@ struct LivenessInfo {
430
431
431
432
/// For every suspending block, the locals which are storage-live across
432
433
/// that suspension point.
433
- storage_liveness : IndexVec < BasicBlock , Option < liveness :: LiveVarSet > > ,
434
+ storage_liveness : IndexVec < BasicBlock , Option < BitSet < Local > > > ,
434
435
}
435
436
436
437
fn locals_live_across_suspend_points (
@@ -467,18 +468,22 @@ fn locals_live_across_suspend_points(
467
468
dataflow:: ResultsCursor :: new ( body_ref, & requires_storage_results) ;
468
469
469
470
// Calculate the liveness of MIR locals ignoring borrows.
470
- let mut liveness = liveness:: liveness_of_locals ( body) ;
471
- liveness:: dump_mir ( tcx, "generator_liveness" , source, body_ref, & liveness) ;
471
+ let mut liveness = MaybeLiveLocals
472
+ . into_engine ( tcx, body_ref, def_id)
473
+ . iterate_to_fixpoint ( )
474
+ . into_results_cursor ( body_ref) ;
472
475
473
476
let mut storage_liveness_map = IndexVec :: from_elem ( None , body. basic_blocks ( ) ) ;
474
477
let mut live_locals_at_suspension_points = Vec :: new ( ) ;
475
- let mut live_locals_at_any_suspension_point =
476
- liveness:: LiveVarSet :: new_empty ( body. local_decls . len ( ) ) ;
478
+ let mut live_locals_at_any_suspension_point = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
477
479
478
480
for ( block, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
479
481
if let TerminatorKind :: Yield { .. } = data. terminator ( ) . kind {
480
482
let loc = Location { block, statement_index : data. statements . len ( ) } ;
481
483
484
+ liveness. seek_to_block_end ( block) ;
485
+ let mut live_locals = liveness. get ( ) . clone ( ) ;
486
+
482
487
if !movable {
483
488
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
484
489
// This is correct for movable generators since borrows cannot live across
@@ -491,22 +496,19 @@ fn locals_live_across_suspend_points(
491
496
// forever. Note that the final liveness is still bounded by the storage liveness
492
497
// of the local, which happens using the `intersect` operation below.
493
498
borrowed_locals_cursor. seek_before_primary_effect ( loc) ;
494
- liveness . outs [ block ] . union ( borrowed_locals_cursor. get ( ) ) ;
499
+ live_locals . union ( borrowed_locals_cursor. get ( ) ) ;
495
500
}
496
501
497
502
// Store the storage liveness for later use so we can restore the state
498
503
// after a suspension point
499
504
storage_live. seek_before_primary_effect ( loc) ;
500
505
storage_liveness_map[ block] = Some ( storage_live. get ( ) . clone ( ) ) ;
501
506
502
- requires_storage_cursor. seek_before_primary_effect ( loc) ;
503
- let storage_required = requires_storage_cursor. get ( ) . clone ( ) ;
504
-
505
507
// Locals live are live at this point only if they are used across
506
508
// suspension points (the `liveness` variable)
507
509
// and their storage is required (the `storage_required` variable)
508
- let mut live_locals = storage_required ;
509
- live_locals. intersect ( & liveness . outs [ block ] ) ;
510
+ requires_storage_cursor . seek_before_primary_effect ( loc ) ;
511
+ live_locals. intersect ( requires_storage_cursor . get ( ) ) ;
510
512
511
513
// The generator argument is ignored.
512
514
live_locals. remove ( SELF_ARG ) ;
@@ -551,7 +553,7 @@ fn locals_live_across_suspend_points(
551
553
/// `[0, 1, 2]`. Thus, if `input = [3, 5]` we would return `[1, 2]`.
552
554
fn renumber_bitset (
553
555
input : & BitSet < Local > ,
554
- stored_locals : & liveness :: LiveVarSet ,
556
+ stored_locals : & BitSet < Local > ,
555
557
) -> BitSet < GeneratorSavedLocal > {
556
558
assert ! ( stored_locals. superset( & input) , "{:?} not a superset of {:?}" , stored_locals, input) ;
557
559
let mut out = BitSet :: new_empty ( stored_locals. count ( ) ) ;
@@ -571,7 +573,7 @@ fn renumber_bitset(
571
573
/// computation; see `GeneratorLayout` for more.
572
574
fn compute_storage_conflicts (
573
575
body : & ' mir Body < ' tcx > ,
574
- stored_locals : & liveness :: LiveVarSet ,
576
+ stored_locals : & BitSet < Local > ,
575
577
always_live_locals : storage:: AlwaysLiveLocals ,
576
578
requires_storage : dataflow:: Results < ' tcx , MaybeRequiresStorage < ' mir , ' tcx > > ,
577
579
) -> BitMatrix < GeneratorSavedLocal , GeneratorSavedLocal > {
@@ -626,7 +628,7 @@ fn compute_storage_conflicts(
626
628
627
629
struct StorageConflictVisitor < ' mir , ' tcx , ' s > {
628
630
body : & ' mir Body < ' tcx > ,
629
- stored_locals : & ' s liveness :: LiveVarSet ,
631
+ stored_locals : & ' s BitSet < Local > ,
630
632
// FIXME(tmandry): Consider using sparse bitsets here once we have good
631
633
// benchmarks for generators.
632
634
local_conflicts : BitMatrix < Local , Local > ,
@@ -635,7 +637,7 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> {
635
637
impl dataflow:: ResultsVisitor < ' mir , ' tcx > for StorageConflictVisitor < ' mir , ' tcx , ' _ > {
636
638
type FlowState = BitSet < Local > ;
637
639
638
- fn visit_statement (
640
+ fn visit_statement_before_primary_effect (
639
641
& mut self ,
640
642
state : & Self :: FlowState ,
641
643
_statement : & ' mir Statement < ' tcx > ,
@@ -644,7 +646,7 @@ impl dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx,
644
646
self . apply_state ( state, loc) ;
645
647
}
646
648
647
- fn visit_terminator (
649
+ fn visit_terminator_before_primary_effect (
648
650
& mut self ,
649
651
state : & Self :: FlowState ,
650
652
_terminator : & ' mir Terminator < ' tcx > ,
@@ -685,7 +687,7 @@ fn compute_layout<'tcx>(
685
687
) -> (
686
688
FxHashMap < Local , ( Ty < ' tcx > , VariantIdx , usize ) > ,
687
689
GeneratorLayout < ' tcx > ,
688
- IndexVec < BasicBlock , Option < liveness :: LiveVarSet > > ,
690
+ IndexVec < BasicBlock , Option < BitSet < Local > > > ,
689
691
) {
690
692
// Use a liveness analysis to compute locals which are live across a suspension point
691
693
let LivenessInfo {
0 commit comments