1
Fork 0

only visit reachable blocks, do not use a visitor

This commit is contained in:
Ralf Jung 2024-08-25 11:42:20 +02:00
parent 5343550142
commit 172c05cca2

View file

@ -18,7 +18,7 @@ use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor}; use rustc_mir_dataflow::Analysis;
use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
@ -275,40 +275,28 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
// A local is "transient" if it is guaranteed dead at all `Return`. // A local is "transient" if it is guaranteed dead at all `Return`.
// So first compute the say of "maybe live" locals at each program point. // So first compute the say of "maybe live" locals at each program point.
let always_live_locals = &always_storage_live_locals(&ccx.body); let always_live_locals = &always_storage_live_locals(&ccx.body);
let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) let mut maybe_storage_live =
MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
.into_engine(ccx.tcx, &ccx.body) .into_engine(ccx.tcx, &ccx.body)
.iterate_to_fixpoint() .iterate_to_fixpoint()
.into_results_cursor(&ccx.body); .into_results_cursor(&ccx.body);
// And then check all `Return` in the MIR, and if a local is "maybe live" at a // And then check all `Return` in the MIR, and if a local is "maybe live" at a
// `Return` then it is definitely not transient. // `Return` then it is definitely not transient.
struct TransientLocalVisitor<'a, 'tcx> { let mut transient = BitSet::new_filled(ccx.body.local_decls.len());
maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, // Make sure to only visit reachable blocks, the dataflow engine can ICE otherwise.
transient: BitSet<Local>, for (bb, data) in traversal::reachable(&ccx.body) {
} if matches!(data.terminator().kind, TerminatorKind::Return) {
impl<'a, 'tcx> Visitor<'tcx> for TransientLocalVisitor<'a, 'tcx> { let location = ccx.body.terminator_loc(bb);
fn visit_terminator( maybe_storage_live.seek_after_primary_effect(location);
&mut self, for local in maybe_storage_live.get().iter() {
terminator: &Terminator<'tcx>,
location: Location,
) {
if matches!(terminator.kind, TerminatorKind::Return) {
self.maybe_storage_live.seek_after_primary_effect(location);
for local in self.maybe_storage_live.get().iter() {
// If a local may be live here, it is definitely not transient. // If a local may be live here, it is definitely not transient.
self.transient.remove(local); transient.remove(local);
}
} }
} }
} }
let mut v = TransientLocalVisitor { transient
maybe_storage_live,
transient: BitSet::new_filled(ccx.body.local_decls.len()),
};
v.visit_body(&ccx.body);
v.transient
}) })
.contains(local) .contains(local)
} }