Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 9100340

Browse files
Use new liveness analysis during generator transform
1 parent 4c34ec6 commit 9100340

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

src/librustc_mir/transform/generator.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@
5050
//! Otherwise it drops all the values in scope at the last suspension point.
5151
5252
use crate::dataflow::{self, Analysis};
53-
use crate::dataflow::{MaybeBorrowedLocals, MaybeRequiresStorage, MaybeStorageLive};
53+
use crate::dataflow::{
54+
MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
55+
};
5456
use crate::transform::no_landing_pads::no_landing_pads;
5557
use crate::transform::simplify;
5658
use crate::transform::{MirPass, MirSource};
5759
use crate::util::dump_mir;
58-
use crate::util::liveness;
5960
use crate::util::storage;
6061
use rustc_data_structures::fx::FxHashMap;
6162
use rustc_hir as hir;
@@ -195,7 +196,7 @@ struct SuspensionPoint<'tcx> {
195196
/// Which block to jump to if the generator is dropped in this state.
196197
drop: Option<BasicBlock>,
197198
/// Set of locals that have live storage while at this suspension point.
198-
storage_liveness: liveness::LiveVarSet,
199+
storage_liveness: BitSet<Local>,
199200
}
200201

201202
struct TransformVisitor<'tcx> {
@@ -211,7 +212,7 @@ struct TransformVisitor<'tcx> {
211212
remap: FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
212213

213214
// 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>>>,
215216

216217
// A list of suspension points, generated during the transform
217218
suspension_points: Vec<SuspensionPoint<'tcx>>,
@@ -418,7 +419,7 @@ struct LivenessInfo {
418419
/// GeneratorSavedLocal is indexed in terms of the elements in this set;
419420
/// i.e. GeneratorSavedLocal::new(1) corresponds to the second local
420421
/// included in this set.
421-
live_locals: liveness::LiveVarSet,
422+
live_locals: BitSet<Local>,
422423

423424
/// The set of saved locals live at each suspension point.
424425
live_locals_at_suspension_points: Vec<BitSet<GeneratorSavedLocal>>,
@@ -430,7 +431,7 @@ struct LivenessInfo {
430431

431432
/// For every suspending block, the locals which are storage-live across
432433
/// that suspension point.
433-
storage_liveness: IndexVec<BasicBlock, Option<liveness::LiveVarSet>>,
434+
storage_liveness: IndexVec<BasicBlock, Option<BitSet<Local>>>,
434435
}
435436

436437
fn locals_live_across_suspend_points(
@@ -467,18 +468,22 @@ fn locals_live_across_suspend_points(
467468
dataflow::ResultsCursor::new(body_ref, &requires_storage_results);
468469

469470
// 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);
472475

473476
let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks());
474477
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());
477479

478480
for (block, data) in body.basic_blocks().iter_enumerated() {
479481
if let TerminatorKind::Yield { .. } = data.terminator().kind {
480482
let loc = Location { block, statement_index: data.statements.len() };
481483

484+
liveness.seek_to_block_end(block);
485+
let mut live_locals = liveness.get().clone();
486+
482487
if !movable {
483488
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
484489
// This is correct for movable generators since borrows cannot live across
@@ -491,22 +496,19 @@ fn locals_live_across_suspend_points(
491496
// forever. Note that the final liveness is still bounded by the storage liveness
492497
// of the local, which happens using the `intersect` operation below.
493498
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());
495500
}
496501

497502
// Store the storage liveness for later use so we can restore the state
498503
// after a suspension point
499504
storage_live.seek_before_primary_effect(loc);
500505
storage_liveness_map[block] = Some(storage_live.get().clone());
501506

502-
requires_storage_cursor.seek_before_primary_effect(loc);
503-
let storage_required = requires_storage_cursor.get().clone();
504-
505507
// Locals live are live at this point only if they are used across
506508
// suspension points (the `liveness` variable)
507509
// 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());
510512

511513
// The generator argument is ignored.
512514
live_locals.remove(SELF_ARG);
@@ -551,7 +553,7 @@ fn locals_live_across_suspend_points(
551553
/// `[0, 1, 2]`. Thus, if `input = [3, 5]` we would return `[1, 2]`.
552554
fn renumber_bitset(
553555
input: &BitSet<Local>,
554-
stored_locals: &liveness::LiveVarSet,
556+
stored_locals: &BitSet<Local>,
555557
) -> BitSet<GeneratorSavedLocal> {
556558
assert!(stored_locals.superset(&input), "{:?} not a superset of {:?}", stored_locals, input);
557559
let mut out = BitSet::new_empty(stored_locals.count());
@@ -571,7 +573,7 @@ fn renumber_bitset(
571573
/// computation; see `GeneratorLayout` for more.
572574
fn compute_storage_conflicts(
573575
body: &'mir Body<'tcx>,
574-
stored_locals: &liveness::LiveVarSet,
576+
stored_locals: &BitSet<Local>,
575577
always_live_locals: storage::AlwaysLiveLocals,
576578
requires_storage: dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
577579
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
@@ -626,7 +628,7 @@ fn compute_storage_conflicts(
626628

627629
struct StorageConflictVisitor<'mir, 'tcx, 's> {
628630
body: &'mir Body<'tcx>,
629-
stored_locals: &'s liveness::LiveVarSet,
631+
stored_locals: &'s BitSet<Local>,
630632
// FIXME(tmandry): Consider using sparse bitsets here once we have good
631633
// benchmarks for generators.
632634
local_conflicts: BitMatrix<Local, Local>,
@@ -635,7 +637,7 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> {
635637
impl dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> {
636638
type FlowState = BitSet<Local>;
637639

638-
fn visit_statement(
640+
fn visit_statement_before_primary_effect(
639641
&mut self,
640642
state: &Self::FlowState,
641643
_statement: &'mir Statement<'tcx>,
@@ -644,7 +646,7 @@ impl dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx,
644646
self.apply_state(state, loc);
645647
}
646648

647-
fn visit_terminator(
649+
fn visit_terminator_before_primary_effect(
648650
&mut self,
649651
state: &Self::FlowState,
650652
_terminator: &'mir Terminator<'tcx>,
@@ -685,7 +687,7 @@ fn compute_layout<'tcx>(
685687
) -> (
686688
FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
687689
GeneratorLayout<'tcx>,
688-
IndexVec<BasicBlock, Option<liveness::LiveVarSet>>,
690+
IndexVec<BasicBlock, Option<BitSet<Local>>>,
689691
) {
690692
// Use a liveness analysis to compute locals which are live across a suspension point
691693
let LivenessInfo {

0 commit comments

Comments
 (0)