kill dead code from util/liveness
This commit is contained in:
parent
af3ff10c7d
commit
57f39ee79b
2 changed files with 9 additions and 171 deletions
|
@ -66,7 +66,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
|
|||
use rustc::ty::{self, TyCtxt, AdtDef, Ty};
|
||||
use rustc::ty::subst::Substs;
|
||||
use util::dump_mir;
|
||||
use util::liveness::{self, IdentityMap, LivenessMode};
|
||||
use util::liveness::{self, IdentityMap};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::indexed_set::IdxSet;
|
||||
use std::collections::HashMap;
|
||||
|
@ -402,10 +402,6 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let mut set = liveness::LiveVarSet::new_empty(mir.local_decls.len());
|
||||
let mut liveness = liveness::liveness_of_locals(
|
||||
mir,
|
||||
LivenessMode {
|
||||
include_regular_use: true,
|
||||
include_drops: true,
|
||||
},
|
||||
&IdentityMap::new(mir),
|
||||
);
|
||||
liveness::dump_mir(
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
//! generator yield points, all pre-existing references are invalidated, so this
|
||||
//! doesn't matter).
|
||||
|
||||
use rustc::mir::visit::MirVisitable;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc::mir::Local;
|
||||
use rustc::mir::*;
|
||||
|
@ -50,17 +49,13 @@ use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
|
|||
pub type LiveVarSet<V> = IdxSet<V>;
|
||||
|
||||
/// This gives the result of the liveness analysis at the boundary of
|
||||
/// basic blocks. You can use `simulate_block` to obtain the
|
||||
/// intra-block results.
|
||||
/// basic blocks.
|
||||
///
|
||||
/// The `V` type defines the set of variables that we computed
|
||||
/// liveness for. This is often `Local`, in which case we computed
|
||||
/// liveness for all variables -- but it can also be some other type,
|
||||
/// which indicates a subset of the variables within the graph.
|
||||
pub struct LivenessResult<V: Idx> {
|
||||
/// Liveness mode in use when these results were computed.
|
||||
pub mode: LivenessMode,
|
||||
|
||||
/// Live variables on exit to each basic block. This is equal to
|
||||
/// the union of the `ins` for each successor.
|
||||
pub outs: IndexVec<BasicBlock, LiveVarSet<V>>,
|
||||
|
@ -104,78 +99,23 @@ impl<'a, 'tcx> LiveVariableMap for IdentityMap<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct LivenessMode {
|
||||
/// If true, then we will consider "regular uses" of a variable to be live.
|
||||
/// For example, if the user writes `foo(x)`, then this is a regular use of
|
||||
/// the variable `x`.
|
||||
pub include_regular_use: bool,
|
||||
|
||||
/// If true, then we will consider (implicit) drops of a variable
|
||||
/// to be live. For example, if the user writes `{ let x =
|
||||
/// vec![...]; .. }`, then the drop at the end of the block is an
|
||||
/// implicit drop.
|
||||
///
|
||||
/// NB. Despite its name, a call like `::std::mem::drop(x)` is
|
||||
/// **not** considered a drop for this purposes, but rather a
|
||||
/// regular use.
|
||||
pub include_drops: bool,
|
||||
}
|
||||
|
||||
/// A combination of liveness results, used in NLL.
|
||||
pub struct LivenessResults<V: Idx> {
|
||||
/// Liveness results where a regular use makes a variable X live,
|
||||
/// but not a drop.
|
||||
pub regular: LivenessResult<V>,
|
||||
|
||||
/// Liveness results where a drop makes a variable X live,
|
||||
/// but not a regular use.
|
||||
pub drop: LivenessResult<V>,
|
||||
}
|
||||
|
||||
impl<V: Idx> LivenessResults<V> {
|
||||
pub fn compute<'tcx>(
|
||||
mir: &Mir<'tcx>,
|
||||
map: &impl LiveVariableMap<LiveVar = V>,
|
||||
) -> LivenessResults<V> {
|
||||
LivenessResults {
|
||||
regular: liveness_of_locals(
|
||||
&mir,
|
||||
LivenessMode {
|
||||
include_regular_use: true,
|
||||
include_drops: false,
|
||||
},
|
||||
map,
|
||||
),
|
||||
|
||||
drop: liveness_of_locals(
|
||||
&mir,
|
||||
LivenessMode {
|
||||
include_regular_use: false,
|
||||
include_drops: true,
|
||||
},
|
||||
map,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute which local variables are live within the given function
|
||||
/// `mir`. The liveness mode `mode` determines what sorts of uses are
|
||||
/// considered to make a variable live (e.g., do drops count?).
|
||||
pub fn liveness_of_locals<'tcx, V: Idx>(
|
||||
mir: &Mir<'tcx>,
|
||||
mode: LivenessMode,
|
||||
map: &impl LiveVariableMap<LiveVar = V>,
|
||||
) -> LivenessResult<V> {
|
||||
let num_live_vars = map.num_variables();
|
||||
|
||||
let def_use: IndexVec<_, DefsUses<V>> = mir.basic_blocks()
|
||||
let def_use: IndexVec<_, DefsUses<V>> = mir
|
||||
.basic_blocks()
|
||||
.iter()
|
||||
.map(|b| block(mode, map, b, num_live_vars))
|
||||
.map(|b| block(map, b, num_live_vars))
|
||||
.collect();
|
||||
|
||||
let mut outs: IndexVec<_, LiveVarSet<V>> = mir.basic_blocks()
|
||||
let mut outs: IndexVec<_, LiveVarSet<V>> = mir
|
||||
.basic_blocks()
|
||||
.indices()
|
||||
.map(|_| LiveVarSet::new_empty(num_live_vars))
|
||||
.collect();
|
||||
|
@ -206,71 +146,7 @@ pub fn liveness_of_locals<'tcx, V: Idx>(
|
|||
}
|
||||
}
|
||||
|
||||
LivenessResult { mode, outs }
|
||||
}
|
||||
|
||||
impl<V: Idx> LivenessResult<V> {
|
||||
/// Walks backwards through the statements/terminator in the given
|
||||
/// basic block `block`. At each point within `block`, invokes
|
||||
/// the callback `op` with the current location and the set of
|
||||
/// variables that are live on entry to that location.
|
||||
pub fn simulate_block<'tcx, OP>(
|
||||
&self,
|
||||
mir: &Mir<'tcx>,
|
||||
block: BasicBlock,
|
||||
map: &impl LiveVariableMap<LiveVar = V>,
|
||||
mut callback: OP,
|
||||
) where
|
||||
OP: FnMut(Location, &LiveVarSet<V>),
|
||||
{
|
||||
let data = &mir[block];
|
||||
|
||||
// Get a copy of the bits on exit from the block.
|
||||
let mut bits = self.outs[block].clone();
|
||||
|
||||
// Start with the maximal statement index -- i.e., right before
|
||||
// the terminator executes.
|
||||
let mut statement_index = data.statements.len();
|
||||
|
||||
// Compute liveness right before terminator and invoke callback.
|
||||
let terminator_location = Location {
|
||||
block,
|
||||
statement_index,
|
||||
};
|
||||
let num_live_vars = map.num_variables();
|
||||
let mut visitor = DefsUsesVisitor {
|
||||
mode: self.mode,
|
||||
map,
|
||||
defs_uses: DefsUses {
|
||||
defs: LiveVarSet::new_empty(num_live_vars),
|
||||
uses: LiveVarSet::new_empty(num_live_vars),
|
||||
},
|
||||
};
|
||||
// Visit the various parts of the basic block in reverse. If we go
|
||||
// forward, the logic in `add_def` and `add_use` would be wrong.
|
||||
visitor.update_bits_and_do_callback(
|
||||
terminator_location,
|
||||
&data.terminator,
|
||||
&mut bits,
|
||||
&mut callback,
|
||||
);
|
||||
|
||||
// Compute liveness before each statement (in rev order) and invoke callback.
|
||||
for statement in data.statements.iter().rev() {
|
||||
statement_index -= 1;
|
||||
let statement_location = Location {
|
||||
block,
|
||||
statement_index,
|
||||
};
|
||||
visitor.defs_uses.clear();
|
||||
visitor.update_bits_and_do_callback(
|
||||
statement_location,
|
||||
statement,
|
||||
&mut bits,
|
||||
&mut callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
LivenessResult { outs }
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone)]
|
||||
|
@ -342,7 +218,6 @@ where
|
|||
V: Idx,
|
||||
M: LiveVariableMap<LiveVar = V> + 'lv,
|
||||
{
|
||||
mode: LivenessMode,
|
||||
map: &'lv M,
|
||||
defs_uses: DefsUses<V>,
|
||||
}
|
||||
|
@ -354,11 +229,6 @@ struct DefsUses<V: Idx> {
|
|||
}
|
||||
|
||||
impl<V: Idx> DefsUses<V> {
|
||||
fn clear(&mut self) {
|
||||
self.uses.clear();
|
||||
self.defs.clear();
|
||||
}
|
||||
|
||||
fn apply(&self, bits: &mut LiveVarSet<V>) -> bool {
|
||||
bits.subtract(&self.defs) | bits.union(&self.uses)
|
||||
}
|
||||
|
@ -393,29 +263,6 @@ impl<V: Idx> DefsUses<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'lv, V, M> DefsUsesVisitor<'lv, V, M>
|
||||
where
|
||||
V: Idx,
|
||||
M: LiveVariableMap<LiveVar = V>,
|
||||
{
|
||||
/// Update `bits` with the effects of `value` and call `callback`. We
|
||||
/// should always visit in reverse order. This method assumes that we have
|
||||
/// not visited anything before; if you have, clear `bits` first.
|
||||
fn update_bits_and_do_callback<'tcx, OP>(
|
||||
&mut self,
|
||||
location: Location,
|
||||
value: &impl MirVisitable<'tcx>,
|
||||
bits: &mut LiveVarSet<V>,
|
||||
callback: &mut OP,
|
||||
) where
|
||||
OP: FnMut(Location, &LiveVarSet<V>),
|
||||
{
|
||||
value.apply(location, self);
|
||||
self.defs_uses.apply(bits);
|
||||
callback(location, bits);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, 'lv, V, M> Visitor<'tcx> for DefsUsesVisitor<'lv, V, M>
|
||||
where
|
||||
V: Idx,
|
||||
|
@ -425,10 +272,7 @@ where
|
|||
if let Some(v_index) = self.map.from_local(local) {
|
||||
match categorize(context) {
|
||||
Some(DefUse::Def) => self.defs_uses.add_def(v_index),
|
||||
Some(DefUse::Use) if self.mode.include_regular_use => {
|
||||
self.defs_uses.add_use(v_index)
|
||||
}
|
||||
Some(DefUse::Drop) if self.mode.include_drops => self.defs_uses.add_use(v_index),
|
||||
Some(DefUse::Use) | Some(DefUse::Drop) => self.defs_uses.add_use(v_index),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -436,13 +280,11 @@ where
|
|||
}
|
||||
|
||||
fn block<'tcx, V: Idx>(
|
||||
mode: LivenessMode,
|
||||
map: &impl LiveVariableMap<LiveVar = V>,
|
||||
b: &BasicBlockData<'tcx>,
|
||||
locals: usize,
|
||||
) -> DefsUses<V> {
|
||||
let mut visitor = DefsUsesVisitor {
|
||||
mode,
|
||||
map,
|
||||
defs_uses: DefsUses {
|
||||
defs: LiveVarSet::new_empty(locals),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue