Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small improvements in liveness pass #77229

Merged
merged 7 commits into from
Sep 27, 2020
96 changes: 45 additions & 51 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
//! ## Special nodes and variables
//!
//! We generate various special nodes for various, well, special purposes.
//! These are described in the `Specials` struct.
//! These are described in the `Liveness` struct.

use self::LiveNodeKind::*;
use self::VarKind::*;
Expand All @@ -96,7 +96,7 @@ use rustc_middle::hir::map::Map;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;

use std::collections::VecDeque;
Expand Down Expand Up @@ -249,8 +249,6 @@ enum VarKind {
struct IrMaps<'tcx> {
tcx: TyCtxt<'tcx>,
body_owner: LocalDefId,
num_live_nodes: usize,
num_vars: usize,
live_node_map: HirIdMap<LiveNode>,
variable_map: HirIdMap<Variable>,
capture_info_map: HirIdMap<Rc<Vec<CaptureInfo>>>,
Expand All @@ -263,8 +261,6 @@ impl IrMaps<'tcx> {
IrMaps {
tcx,
body_owner,
num_live_nodes: 0,
num_vars: 0,
live_node_map: HirIdMap::default(),
variable_map: HirIdMap::default(),
capture_info_map: Default::default(),
Expand All @@ -274,9 +270,8 @@ impl IrMaps<'tcx> {
}

fn add_live_node(&mut self, lnk: LiveNodeKind) -> LiveNode {
let ln = LiveNode(self.num_live_nodes as u32);
let ln = LiveNode(self.lnks.len() as u32);
self.lnks.push(lnk);
self.num_live_nodes += 1;

debug!("{:?} is of kind {}", ln, live_node_kind_to_string(lnk, self.tcx));

Expand All @@ -291,9 +286,8 @@ impl IrMaps<'tcx> {
}

fn add_variable(&mut self, vk: VarKind) -> Variable {
let v = Variable(self.num_vars as u32);
let v = Variable(self.var_kinds.len() as u32);
self.var_kinds.push(vk);
self.num_vars += 1;

match vk {
Local(LocalInfo { id: node_id, .. }) | Param(node_id, _) | Upvar(node_id, _) => {
Expand All @@ -315,9 +309,9 @@ impl IrMaps<'tcx> {
}
}

fn variable_name(&self, var: Variable) -> String {
fn variable_name(&self, var: Variable) -> Symbol {
match self.var_kinds[var.get()] {
Local(LocalInfo { name, .. }) | Param(_, name) | Upvar(_, name) => name.to_string(),
Local(LocalInfo { name, .. }) | Param(_, name) | Upvar(_, name) => name,
}
}

Expand Down Expand Up @@ -367,7 +361,6 @@ fn visit_fn<'tcx>(

if let Some(upvars) = ir.tcx.upvars_mentioned(def_id) {
for (&var_hir_id, _upvar) in upvars {
debug!("adding upvar {:?}", var_hir_id);
let var_name = ir.tcx.hir().name(var_hir_id);
fn_maps.add_variable(Upvar(var_hir_id, var_name));
}
Expand All @@ -379,7 +372,6 @@ fn visit_fn<'tcx>(
_ => false,
};
param.pat.each_binding(|_bm, hir_id, _x, ident| {
debug!("adding parameters {:?}", hir_id);
let var = if is_shorthand {
Local(LocalInfo { id: hir_id, name: ident.name, is_shorthand: true })
} else {
Expand Down Expand Up @@ -634,17 +626,6 @@ impl RWUTable {
}
}

#[derive(Copy, Clone)]
struct Specials {
/// A live node representing a point of execution before closure entry &
/// after closure exit. Used to calculate liveness of captured variables
/// through calls to the same closure. Used for Fn & FnMut closures only.
closure_ln: LiveNode,
/// A live node representing every 'exit' from the function, whether it be
/// by explicit return, panic, or other means.
exit_ln: LiveNode,
}

const ACC_READ: u32 = 1;
const ACC_WRITE: u32 = 2;
const ACC_USE: u32 = 4;
Expand All @@ -653,10 +634,17 @@ struct Liveness<'a, 'tcx> {
ir: &'a mut IrMaps<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
param_env: ty::ParamEnv<'tcx>,
s: Specials,
successors: Vec<LiveNode>,
rwu_table: RWUTable,

/// A live node representing a point of execution before closure entry &
/// after closure exit. Used to calculate liveness of captured variables
/// through calls to the same closure. Used for Fn & FnMut closures only.
closure_ln: LiveNode,
/// A live node representing every 'exit' from the function, whether it be
/// by explicit return, panic, or other means.
exit_ln: LiveNode,

// mappings from loop node ID to LiveNode
// ("break" label should map to loop node ID,
// it probably doesn't now)
Expand All @@ -666,24 +654,23 @@ struct Liveness<'a, 'tcx> {

impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn new(ir: &'a mut IrMaps<'tcx>, def_id: LocalDefId) -> Liveness<'a, 'tcx> {
let specials = Specials {
closure_ln: ir.add_live_node(ClosureNode),
exit_ln: ir.add_live_node(ExitNode),
};

let typeck_results = ir.tcx.typeck(def_id);
let param_env = ir.tcx.param_env(def_id);

let num_live_nodes = ir.num_live_nodes;
let num_vars = ir.num_vars;
let closure_ln = ir.add_live_node(ClosureNode);
let exit_ln = ir.add_live_node(ExitNode);

let num_live_nodes = ir.lnks.len();
let num_vars = ir.var_kinds.len();

Liveness {
ir,
typeck_results,
param_env,
s: specials,
successors: vec![invalid_node(); num_live_nodes],
rwu_table: RWUTable::new(num_live_nodes * num_vars),
closure_ln,
exit_ln,
break_ln: Default::default(),
cont_ln: Default::default(),
}
Expand Down Expand Up @@ -721,7 +708,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}

fn idx(&self, ln: LiveNode, var: Variable) -> usize {
ln.get() * self.ir.num_vars + var.get()
ln.get() * self.ir.var_kinds.len() + var.get()
}

fn live_on_entry(&self, ln: LiveNode, var: Variable) -> Option<LiveNodeKind> {
Expand Down Expand Up @@ -758,7 +745,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
{
let node_base_idx = self.idx(ln, Variable(0));
let succ_base_idx = self.idx(succ_ln, Variable(0));
for var_idx in 0..self.ir.num_vars {
for var_idx in 0..self.ir.var_kinds.len() {
op(self, node_base_idx + var_idx, succ_base_idx + var_idx);
}
}
Expand All @@ -768,7 +755,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
F: FnMut(usize) -> bool,
{
let node_base_idx = self.idx(ln, Variable(0));
for var_idx in 0..self.ir.num_vars {
for var_idx in 0..self.ir.var_kinds.len() {
let idx = node_base_idx + var_idx;
if test(idx) {
write!(wr, " {:?}", Variable(var_idx as u32))?;
Expand Down Expand Up @@ -799,7 +786,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
debug!(
"^^ liveness computation results for body {} (entry={:?})",
{
for ln_idx in 0..self.ir.num_live_nodes {
for ln_idx in 0..self.ir.lnks.len() {
debug!("{:?}", self.ln_str(LiveNode(ln_idx as u32)));
}
hir_id
Expand Down Expand Up @@ -943,14 +930,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match self.typeck_results.upvar_capture(upvar_id) {
ty::UpvarCapture::ByRef(_) => {
let var = self.variable(var_hir_id, upvar.span);
self.acc(self.s.exit_ln, var, ACC_READ | ACC_USE);
self.acc(self.exit_ln, var, ACC_READ | ACC_USE);
}
ty::UpvarCapture::ByValue(_) => {}
}
}
}

let succ = self.propagate_through_expr(&body.value, self.s.exit_ln);
let succ = self.propagate_through_expr(&body.value, self.exit_ln);

match fk {
FnKind::Method(..) | FnKind::ItemFn(..) => return succ,
Expand All @@ -973,19 +960,19 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// Propagate through calls to the closure.
let mut first_merge = true;
loop {
self.init_from_succ(self.s.closure_ln, succ);
self.init_from_succ(self.closure_ln, succ);
for param in body.params {
param.pat.each_binding(|_bm, hir_id, _x, ident| {
let var = self.variable(hir_id, ident.span);
self.define(self.s.closure_ln, var);
self.define(self.closure_ln, var);
})
}

if !self.merge_from_succ(self.s.exit_ln, self.s.closure_ln, first_merge) {
if !self.merge_from_succ(self.exit_ln, self.closure_ln, first_merge) {
break;
}
first_merge = false;
assert_eq!(succ, self.propagate_through_expr(&body.value, self.s.exit_ln));
assert_eq!(succ, self.propagate_through_expr(&body.value, self.exit_ln));
}

succ
Expand Down Expand Up @@ -1107,7 +1094,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

hir::ExprKind::Ret(ref o_e) => {
// ignore succ and subst exit_ln:
let exit_ln = self.s.exit_ln;
let exit_ln = self.exit_ln;
self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln)
}

Expand Down Expand Up @@ -1182,7 +1169,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.typeck_results.expr_ty(expr),
self.param_env,
) {
self.s.exit_ln
self.exit_ln
} else {
succ
};
Expand All @@ -1197,7 +1184,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.typeck_results.expr_ty(expr),
self.param_env,
) {
self.s.exit_ln
self.exit_ln
} else {
succ
};
Expand Down Expand Up @@ -1234,7 +1221,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::InlineAsm(ref asm) => {
// Handle non-returning asm
let mut succ = if asm.options.contains(InlineAsmOptions::NORETURN) {
self.s.exit_ln
self.exit_ln
} else {
succ
};
Expand Down Expand Up @@ -1595,7 +1582,14 @@ impl<'tcx> Liveness<'_, 'tcx> {

fn should_warn(&self, var: Variable) -> Option<String> {
let name = self.ir.variable_name(var);
if name.is_empty() || name.as_bytes()[0] == b'_' { None } else { Some(name) }
if name == kw::Invalid {
return None;
}
let name: &str = &name.as_str();
if name.as_bytes()[0] == b'_' {
return None;
}
Some(name.to_owned())
}

fn warn_about_unused_upvars(&self, entry_ln: LiveNode) {
Expand Down Expand Up @@ -1667,7 +1661,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
// bindings, and we also consider the first pattern to be the "authoritative" set of ids.
// However, we should take the ids and spans of variables with the same name from the later
// patterns so the suggestions to prefix with underscores will apply to those too.
let mut vars: FxIndexMap<String, (LiveNode, Variable, Vec<(HirId, Span)>)> = <_>::default();
let mut vars: FxIndexMap<Symbol, (LiveNode, Variable, Vec<(HirId, Span)>)> = <_>::default();

pat.each_binding(|_, hir_id, pat_sp, ident| {
let ln = entry_ln.unwrap_or_else(|| self.live_node(hir_id, pat_sp));
Expand Down Expand Up @@ -1697,7 +1691,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
// {ret}`, there is only one node, so asking about
// assigned_on_exit() is not meaningful.
let is_assigned =
if ln == self.s.exit_ln { false } else { self.assigned_on_exit(ln, var).is_some() };
if ln == self.exit_ln { false } else { self.assigned_on_exit(ln, var).is_some() };

if is_assigned {
self.ir.tcx.struct_span_lint_hir(
Expand Down