Skip to content

Commit 02c65e1

Browse files
Use new utility in transform/generator.rs
1 parent 335fd6b commit 02c65e1

File tree

1 file changed

+40
-34
lines changed

1 file changed

+40
-34
lines changed

src/librustc_mir/transform/generator.rs

+40-34
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,13 @@ use crate::transform::simplify;
5656
use crate::transform::{MirPass, MirSource};
5757
use crate::util::dump_mir;
5858
use crate::util::liveness;
59+
use crate::util::storage;
5960
use rustc_data_structures::fx::FxHashMap;
6061
use rustc_hir as hir;
6162
use rustc_hir::def_id::DefId;
6263
use rustc_index::bit_set::{BitMatrix, BitSet};
6364
use rustc_index::vec::{Idx, IndexVec};
64-
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
65+
use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
6566
use rustc_middle::mir::*;
6667
use rustc_middle::ty::subst::SubstsRef;
6768
use rustc_middle::ty::GeneratorSubsts;
@@ -222,6 +223,9 @@ struct TransformVisitor<'tcx> {
222223
// A list of suspension points, generated during the transform
223224
suspension_points: Vec<SuspensionPoint<'tcx>>,
224225

226+
// The set of locals that have no `StorageLive`/`StorageDead` annotations.
227+
always_live_locals: storage::AlwaysLiveLocals,
228+
225229
// The original RETURN_PLACE local
226230
new_ret_local: Local,
227231
}
@@ -416,19 +420,6 @@ fn replace_local<'tcx>(
416420
new_local
417421
}
418422

419-
struct StorageIgnored(liveness::LiveVarSet);
420-
421-
impl<'tcx> Visitor<'tcx> for StorageIgnored {
422-
fn visit_statement(&mut self, statement: &Statement<'tcx>, _location: Location) {
423-
match statement.kind {
424-
StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => {
425-
self.0.remove(l);
426-
}
427-
_ => (),
428-
}
429-
}
430-
}
431-
432423
struct LivenessInfo {
433424
/// Which locals are live across any suspension point.
434425
///
@@ -454,23 +445,19 @@ fn locals_live_across_suspend_points(
454445
tcx: TyCtxt<'tcx>,
455446
body: ReadOnlyBodyAndCache<'_, 'tcx>,
456447
source: MirSource<'tcx>,
448+
always_live_locals: &storage::AlwaysLiveLocals,
457449
movable: bool,
458450
) -> LivenessInfo {
459451
let def_id = source.def_id();
460452
let body_ref: &Body<'_> = &body;
461453

462454
// Calculate when MIR locals have live storage. This gives us an upper bound of their
463455
// lifetimes.
464-
let mut storage_live = MaybeStorageLive
456+
let mut storage_live = MaybeStorageLive::new(always_live_locals.clone())
465457
.into_engine(tcx, body_ref, def_id)
466458
.iterate_to_fixpoint()
467459
.into_results_cursor(body_ref);
468460

469-
// Find the MIR locals which do not use StorageLive/StorageDead statements.
470-
// The storage of these locals are always live.
471-
let mut ignored = StorageIgnored(BitSet::new_filled(body.local_decls.len()));
472-
ignored.visit_body(&body);
473-
474461
// Calculate the MIR locals which have been previously
475462
// borrowed (even if they are still active).
476463
let borrowed_locals_results =
@@ -515,11 +502,13 @@ fn locals_live_across_suspend_points(
515502
}
516503

517504
storage_live.seek_before(loc);
518-
let storage_liveness = storage_live.get();
505+
let mut storage_liveness = storage_live.get().clone();
506+
507+
storage_liveness.remove(SELF_ARG);
519508

520509
// Store the storage liveness for later use so we can restore the state
521510
// after a suspension point
522-
storage_liveness_map.insert(block, storage_liveness.clone());
511+
storage_liveness_map.insert(block, storage_liveness);
523512

524513
requires_storage_cursor.seek_before(loc);
525514
let storage_required = requires_storage_cursor.get().clone();
@@ -551,8 +540,12 @@ fn locals_live_across_suspend_points(
551540
.map(|live_here| renumber_bitset(&live_here, &live_locals))
552541
.collect();
553542

554-
let storage_conflicts =
555-
compute_storage_conflicts(body_ref, &live_locals, &ignored, requires_storage_results);
543+
let storage_conflicts = compute_storage_conflicts(
544+
body_ref,
545+
&live_locals,
546+
always_live_locals.clone(),
547+
requires_storage_results,
548+
);
556549

557550
LivenessInfo {
558551
live_locals,
@@ -590,18 +583,18 @@ fn renumber_bitset(
590583
fn compute_storage_conflicts(
591584
body: &'mir Body<'tcx>,
592585
stored_locals: &liveness::LiveVarSet,
593-
ignored: &StorageIgnored,
586+
always_live_locals: storage::AlwaysLiveLocals,
594587
requires_storage: dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
595588
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
596-
assert_eq!(body.local_decls.len(), ignored.0.domain_size());
597589
assert_eq!(body.local_decls.len(), stored_locals.domain_size());
590+
598591
debug!("compute_storage_conflicts({:?})", body.span);
599-
debug!("ignored = {:?}", ignored.0);
592+
debug!("always_live = {:?}", always_live_locals);
600593

601-
// Storage ignored locals are not eligible for overlap, since their storage
602-
// is always live.
603-
let mut ineligible_locals = ignored.0.clone();
604-
ineligible_locals.intersect(&stored_locals);
594+
// Locals that are always live or ones that need to be stored across
595+
// suspension points are not eligible for overlap.
596+
let mut ineligible_locals = always_live_locals.into_inner();
597+
ineligible_locals.intersect(stored_locals);
605598

606599
// Compute the storage conflicts for all eligible locals.
607600
let mut visitor = StorageConflictVisitor {
@@ -697,6 +690,7 @@ fn compute_layout<'tcx>(
697690
source: MirSource<'tcx>,
698691
upvars: &Vec<Ty<'tcx>>,
699692
interior: Ty<'tcx>,
693+
always_live_locals: &storage::AlwaysLiveLocals,
700694
movable: bool,
701695
body: &mut BodyAndCache<'tcx>,
702696
) -> (
@@ -710,7 +704,13 @@ fn compute_layout<'tcx>(
710704
live_locals_at_suspension_points,
711705
storage_conflicts,
712706
storage_liveness,
713-
} = locals_live_across_suspend_points(tcx, read_only!(body), source, movable);
707+
} = locals_live_across_suspend_points(
708+
tcx,
709+
read_only!(body),
710+
source,
711+
always_live_locals,
712+
movable,
713+
);
714714

715715
// Erase regions from the types passed in from typeck so we can compare them with
716716
// MIR types
@@ -1180,7 +1180,10 @@ fn create_cases<'tcx>(
11801180
}
11811181

11821182
let l = Local::new(i);
1183-
if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) {
1183+
let needs_storage_live = point.storage_liveness.contains(l)
1184+
&& !transform.remap.contains_key(&l)
1185+
&& !transform.always_live_locals.contains(l);
1186+
if needs_storage_live {
11841187
statements
11851188
.push(Statement { source_info, kind: StatementKind::StorageLive(l) });
11861189
}
@@ -1276,11 +1279,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
12761279
},
12771280
);
12781281

1282+
let always_live_locals = storage::AlwaysLiveLocals::new(&body);
1283+
12791284
// Extract locals which are live across suspension point into `layout`
12801285
// `remap` gives a mapping from local indices onto generator struct indices
12811286
// `storage_liveness` tells us which locals have live storage at suspension points
12821287
let (remap, layout, storage_liveness) =
1283-
compute_layout(tcx, source, &upvars, interior, movable, body);
1288+
compute_layout(tcx, source, &upvars, interior, &always_live_locals, movable, body);
12841289

12851290
let can_return = can_return(tcx, body);
12861291

@@ -1294,6 +1299,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
12941299
state_substs,
12951300
remap,
12961301
storage_liveness,
1302+
always_live_locals,
12971303
suspension_points: Vec::new(),
12981304
new_ret_local,
12991305
discr_ty,

0 commit comments

Comments
 (0)