From 9b5835ec7973a52f2e9d6f4ed9a2181bebfdc399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 26 Sep 2020 00:00:00 +0000 Subject: [PATCH 1/7] liveness: Remove redundant debug logging The IrMaps::add_variable already contains debug logging. Don't duplicate it. --- compiler/rustc_passes/src/liveness.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index db9495201cf30..50ea4ed76b20f 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -367,7 +367,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)); } @@ -379,7 +378,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 { From 2fb1564457b47bd31087e2aba1b8eb6f15c000ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 26 Sep 2020 00:00:00 +0000 Subject: [PATCH 2/7] liveness: Remove redundant fields for a number of live nodes and variables --- compiler/rustc_passes/src/liveness.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 50ea4ed76b20f..346980b4199ab 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -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, variable_map: HirIdMap, capture_info_map: HirIdMap>>, @@ -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(), @@ -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)); @@ -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, _) => { @@ -672,8 +666,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { 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 num_live_nodes = ir.lnks.len(); + let num_vars = ir.var_kinds.len(); Liveness { ir, @@ -719,7 +713,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 { @@ -756,7 +750,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); } } @@ -766,7 +760,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))?; @@ -797,7 +791,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 From 70f150b51e7d13e3bcd8977ff124a348057cf7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 26 Sep 2020 00:00:00 +0000 Subject: [PATCH 3/7] liveness: Delay conversion from a symbol to a string until linting --- compiler/rustc_passes/src/liveness.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 346980b4199ab..4f9ee6df4aaa5 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -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; @@ -309,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, } } @@ -1587,7 +1587,14 @@ impl<'tcx> Liveness<'_, 'tcx> { fn should_warn(&self, var: Variable) -> Option { 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) { @@ -1659,7 +1666,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)> = <_>::default(); + let mut vars: FxIndexMap)> = <_>::default(); pat.each_binding(|_, hir_id, pat_sp, ident| { let ln = entry_ln.unwrap_or_else(|| self.live_node(hir_id, pat_sp)); From 141b91da6cb756ff5f36eebe9eee65922e295876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 26 Sep 2020 00:00:00 +0000 Subject: [PATCH 4/7] liveness: Inline contents of specials struct --- compiler/rustc_passes/src/liveness.rs | 55 ++++++++++++--------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 4f9ee6df4aaa5..cb452d3d04153 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -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::*; @@ -626,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; @@ -645,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, 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) @@ -658,14 +654,12 @@ 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 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(); @@ -673,9 +667,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { 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(), } @@ -935,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, @@ -965,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 @@ -1099,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) } @@ -1174,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 }; @@ -1189,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 }; @@ -1226,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 }; @@ -1696,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( From 49d1ce00f30a10e607dc30506d3e890d1efb6309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 26 Sep 2020 00:00:00 +0000 Subject: [PATCH 5/7] liveness: Remove unnecessary local variable exit_ln --- compiler/rustc_passes/src/liveness.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index cb452d3d04153..402f889ac8c49 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1093,9 +1093,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Ret(ref o_e) => { - // ignore succ and subst exit_ln: - let exit_ln = self.exit_ln; - self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln) + // Ignore succ and subst exit_ln. + self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), self.exit_ln) } hir::ExprKind::Break(label, ref opt_expr) => { From 57d38975cc638bcdeb7e9bcd10621615e8f9f3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 26 Sep 2020 00:00:00 +0000 Subject: [PATCH 6/7] liveness: Use newtype_index for Variable and LiveNode --- Cargo.lock | 1 + compiler/rustc_passes/Cargo.toml | 1 + compiler/rustc_passes/src/lib.rs | 2 + compiler/rustc_passes/src/liveness.rs | 109 ++++++++++---------------- 4 files changed, 47 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a5ba74174948..2bd41e68f8b9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3891,6 +3891,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_middle", + "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 4c3a96eed04c4..df6667a29d50b 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -15,5 +15,6 @@ rustc_index = { path = "../rustc_index" } rustc_session = { path = "../rustc_session" } rustc_target = { path = "../rustc_target" } rustc_ast = { path = "../rustc_ast" } +rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index c14d6aace87e0..c32c9c8eaa68c 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -5,6 +5,8 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(or_patterns)] diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 402f889ac8c49..8c6d47f992d78 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -62,13 +62,13 @@ //! - `reader`: the `LiveNode` ID of some node which will read the value //! that `V` holds on entry to `N`. Formally: a node `M` such //! that there exists a path `P` from `N` to `M` where `P` does not -//! write `V`. If the `reader` is `invalid_node()`, then the current +//! write `V`. If the `reader` is `INVALID_NODE`, then the current //! value will never be read (the variable is dead, essentially). //! //! - `writer`: the `LiveNode` ID of some node which will write the //! variable `V` and which is reachable from `N`. Formally: a node `M` //! such that there exists a path `P` from `N` to `M` and `M` writes -//! `V`. If the `writer` is `invalid_node()`, then there is no writer +//! `V`. If the `writer` is `INVALID_NODE`, then there is no writer //! of `V` that follows `N`. //! //! - `used`: a boolean value indicating whether `V` is *used*. We @@ -92,6 +92,7 @@ use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node}; +use rustc_index::vec::IndexVec; use rustc_middle::hir::map::Map; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; @@ -100,26 +101,20 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; use std::collections::VecDeque; -use std::fmt; use std::io; use std::io::prelude::*; use std::rc::Rc; -#[derive(Copy, Clone, PartialEq)] -struct Variable(u32); - -#[derive(Copy, Clone, PartialEq)] -struct LiveNode(u32); - -impl Variable { - fn get(&self) -> usize { - self.0 as usize +rustc_index::newtype_index! { + pub struct Variable { + DEBUG_FORMAT = "v({})", } } -impl LiveNode { - fn get(&self) -> usize { - self.0 as usize +rustc_index::newtype_index! { + pub struct LiveNode { + DEBUG_FORMAT = "ln({})", + const INVALID_NODE = LiveNode::MAX_AS_U32, } } @@ -183,18 +178,6 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { check_mod_liveness, ..*providers }; } -impl fmt::Debug for LiveNode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ln({})", self.get()) - } -} - -impl fmt::Debug for Variable { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "v({})", self.get()) - } -} - // ______________________________________________________________________ // Creating ir_maps // @@ -218,15 +201,11 @@ impl fmt::Debug for Variable { // assignment. And so forth. impl LiveNode { - fn is_valid(&self) -> bool { - self.0 != u32::MAX + fn is_valid(self) -> bool { + self != INVALID_NODE } } -fn invalid_node() -> LiveNode { - LiveNode(u32::MAX) -} - struct CaptureInfo { ln: LiveNode, var_hid: HirId, @@ -252,8 +231,8 @@ struct IrMaps<'tcx> { live_node_map: HirIdMap, variable_map: HirIdMap, capture_info_map: HirIdMap>>, - var_kinds: Vec, - lnks: Vec, + var_kinds: IndexVec, + lnks: IndexVec, } impl IrMaps<'tcx> { @@ -264,14 +243,13 @@ impl IrMaps<'tcx> { live_node_map: HirIdMap::default(), variable_map: HirIdMap::default(), capture_info_map: Default::default(), - var_kinds: Vec::new(), - lnks: Vec::new(), + var_kinds: IndexVec::new(), + lnks: IndexVec::new(), } } fn add_live_node(&mut self, lnk: LiveNodeKind) -> LiveNode { - let ln = LiveNode(self.lnks.len() as u32); - self.lnks.push(lnk); + let ln = self.lnks.push(lnk); debug!("{:?} is of kind {}", ln, live_node_kind_to_string(lnk, self.tcx)); @@ -286,8 +264,7 @@ impl IrMaps<'tcx> { } fn add_variable(&mut self, vk: VarKind) -> Variable { - let v = Variable(self.var_kinds.len() as u32); - self.var_kinds.push(vk); + let v = self.var_kinds.push(vk); match vk { Local(LocalInfo { id: node_id, .. }) | Param(node_id, _) | Upvar(node_id, _) => { @@ -310,13 +287,13 @@ impl IrMaps<'tcx> { } fn variable_name(&self, var: Variable) -> Symbol { - match self.var_kinds[var.get()] { + match self.var_kinds[var] { Local(LocalInfo { name, .. }) | Param(_, name) | Upvar(_, name) => name, } } fn variable_is_shorthand(&self, var: Variable) -> bool { - match self.var_kinds[var.get()] { + match self.var_kinds[var] { Local(LocalInfo { is_shorthand, .. }) => is_shorthand, Param(..) | Upvar(..) => false, } @@ -327,7 +304,7 @@ impl IrMaps<'tcx> { } fn lnk(&self, ln: LiveNode) -> LiveNodeKind { - self.lnks[ln.get()] + self.lnks[ln] } } @@ -556,10 +533,10 @@ struct RWUTable { unpacked_rwus: Vec, } -// A constant representing `RWU { reader: invalid_node(); writer: invalid_node(); used: false }`. +// A constant representing `RWU { reader: INVALID_NODE; writer: INVALID_NODE; used: false }`. const INV_INV_FALSE: u32 = u32::MAX; -// A constant representing `RWU { reader: invalid_node(); writer: invalid_node(); used: true }`. +// A constant representing `RWU { reader: INVALID_NODE; writer: INVALID_NODE; used: true }`. const INV_INV_TRUE: u32 = u32::MAX - 1; impl RWUTable { @@ -570,8 +547,8 @@ impl RWUTable { fn get(&self, idx: usize) -> RWU { let packed_rwu = self.packed_rwus[idx]; match packed_rwu { - INV_INV_FALSE => RWU { reader: invalid_node(), writer: invalid_node(), used: false }, - INV_INV_TRUE => RWU { reader: invalid_node(), writer: invalid_node(), used: true }, + INV_INV_FALSE => RWU { reader: INVALID_NODE, writer: INVALID_NODE, used: false }, + INV_INV_TRUE => RWU { reader: INVALID_NODE, writer: INVALID_NODE, used: true }, _ => self.unpacked_rwus[packed_rwu as usize], } } @@ -579,7 +556,7 @@ impl RWUTable { fn get_reader(&self, idx: usize) -> LiveNode { let packed_rwu = self.packed_rwus[idx]; match packed_rwu { - INV_INV_FALSE | INV_INV_TRUE => invalid_node(), + INV_INV_FALSE | INV_INV_TRUE => INVALID_NODE, _ => self.unpacked_rwus[packed_rwu as usize].reader, } } @@ -587,7 +564,7 @@ impl RWUTable { fn get_writer(&self, idx: usize) -> LiveNode { let packed_rwu = self.packed_rwus[idx]; match packed_rwu { - INV_INV_FALSE | INV_INV_TRUE => invalid_node(), + INV_INV_FALSE | INV_INV_TRUE => INVALID_NODE, _ => self.unpacked_rwus[packed_rwu as usize].writer, } } @@ -607,7 +584,7 @@ impl RWUTable { } fn assign_unpacked(&mut self, idx: usize, rwu: RWU) { - if rwu.reader == invalid_node() && rwu.writer == invalid_node() { + if rwu.reader == INVALID_NODE && rwu.writer == INVALID_NODE { // When we overwrite an indexing entry in `self.packed_rwus` with // `INV_INV_{TRUE,FALSE}` we don't remove the corresponding entry // from `self.unpacked_rwus`; it's not worth the effort, and we @@ -634,7 +611,7 @@ struct Liveness<'a, 'tcx> { ir: &'a mut IrMaps<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, param_env: ty::ParamEnv<'tcx>, - successors: Vec, + successors: IndexVec, rwu_table: RWUTable, /// A live node representing a point of execution before closure entry & @@ -667,7 +644,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ir, typeck_results, param_env, - successors: vec![invalid_node(); num_live_nodes], + successors: IndexVec::from_elem_n(INVALID_NODE, num_live_nodes), rwu_table: RWUTable::new(num_live_nodes * num_vars), closure_ln, exit_ln, @@ -708,7 +685,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn idx(&self, ln: LiveNode, var: Variable) -> usize { - ln.get() * self.ir.var_kinds.len() + var.get() + ln.index() * self.ir.var_kinds.len() + var.index() } fn live_on_entry(&self, ln: LiveNode, var: Variable) -> Option { @@ -719,7 +696,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Is this variable live on entry to any of its successor nodes? fn live_on_exit(&self, ln: LiveNode, var: Variable) -> Option { - let successor = self.successors[ln.get()]; + let successor = self.successors[ln]; self.live_on_entry(successor, var) } @@ -735,7 +712,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn assigned_on_exit(&self, ln: LiveNode, var: Variable) -> Option { - let successor = self.successors[ln.get()]; + let successor = self.successors[ln]; self.assigned_on_entry(successor, var) } @@ -743,8 +720,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { where F: FnMut(&mut Liveness<'a, 'tcx>, usize, usize), { - let node_base_idx = self.idx(ln, Variable(0)); - let succ_base_idx = self.idx(succ_ln, Variable(0)); + let node_base_idx = self.idx(ln, Variable::from(0u32)); + let succ_base_idx = self.idx(succ_ln, Variable::from(0u32)); for var_idx in 0..self.ir.var_kinds.len() { op(self, node_base_idx + var_idx, succ_base_idx + var_idx); } @@ -754,11 +731,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { where F: FnMut(usize) -> bool, { - let node_base_idx = self.idx(ln, Variable(0)); + let node_base_idx = self.idx(ln, Variable::from(0u32)); 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))?; + write!(wr, " {:?}", Variable::from(var_idx))?; } } Ok(()) @@ -769,14 +746,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let mut wr = Vec::new(); { let wr = &mut wr as &mut dyn Write; - write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln)); + write!(wr, "[{:?} of kind {:?} reads", ln, self.ir.lnk(ln)); self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx).is_valid()); write!(wr, " writes"); self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx).is_valid()); write!(wr, " uses"); self.write_vars(wr, ln, |idx| self.rwu_table.get_used(idx)); - write!(wr, " precedes {:?}]", self.successors[ln.get()]); + write!(wr, " precedes {:?}]", self.successors[ln]); } String::from_utf8(wr).unwrap() } @@ -787,7 +764,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { "^^ liveness computation results for body {} (entry={:?})", { for ln_idx in 0..self.ir.lnks.len() { - debug!("{:?}", self.ln_str(LiveNode(ln_idx as u32))); + debug!("{:?}", self.ln_str(LiveNode::from(ln_idx))); } hir_id }, @@ -796,7 +773,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn init_empty(&mut self, ln: LiveNode, succ_ln: LiveNode) { - self.successors[ln.get()] = succ_ln; + self.successors[ln] = succ_ln; // It is not necessary to initialize the RWUs here because they are all // set to INV_INV_FALSE when they are created, and the sets only grow @@ -805,7 +782,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn init_from_succ(&mut self, ln: LiveNode, succ_ln: LiveNode) { // more efficient version of init_empty() / merge_from_succ() - self.successors[ln.get()] = succ_ln; + self.successors[ln] = succ_ln; self.indices2(ln, succ_ln, |this, idx, succ_idx| { this.rwu_table.copy_packed(idx, succ_idx); @@ -878,7 +855,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let mut rwu = self.rwu_table.get(idx); if (acc & ACC_WRITE) != 0 { - rwu.reader = invalid_node(); + rwu.reader = INVALID_NODE; rwu.writer = ln; } From d68aa227c6b7ab9c1cfa003e752c3600a7269485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 27 Sep 2020 00:00:00 +0000 Subject: [PATCH 7/7] liveness: Access live nodes directly through self.lnks[ln] --- compiler/rustc_passes/src/liveness.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 8c6d47f992d78..9eac2f79e412c 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -302,10 +302,6 @@ impl IrMaps<'tcx> { fn set_captures(&mut self, hir_id: HirId, cs: Vec) { self.capture_info_map.insert(hir_id, Rc::new(cs)); } - - fn lnk(&self, ln: LiveNode) -> LiveNodeKind { - self.lnks[ln] - } } fn visit_fn<'tcx>( @@ -691,7 +687,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn live_on_entry(&self, ln: LiveNode, var: Variable) -> Option { assert!(ln.is_valid()); let reader = self.rwu_table.get_reader(self.idx(ln, var)); - if reader.is_valid() { Some(self.ir.lnk(reader)) } else { None } + if reader.is_valid() { Some(self.ir.lnks[reader]) } else { None } } // Is this variable live on entry to any of its successor nodes? @@ -708,7 +704,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn assigned_on_entry(&self, ln: LiveNode, var: Variable) -> Option { assert!(ln.is_valid()); let writer = self.rwu_table.get_writer(self.idx(ln, var)); - if writer.is_valid() { Some(self.ir.lnk(writer)) } else { None } + if writer.is_valid() { Some(self.ir.lnks[writer]) } else { None } } fn assigned_on_exit(&self, ln: LiveNode, var: Variable) -> Option { @@ -746,7 +742,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let mut wr = Vec::new(); { let wr = &mut wr as &mut dyn Write; - write!(wr, "[{:?} of kind {:?} reads", ln, self.ir.lnk(ln)); + write!(wr, "[{:?} of kind {:?} reads", ln, self.ir.lnks[ln]); self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx).is_valid()); write!(wr, " writes"); self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx).is_valid());