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

NLL: experiment with inverting liveness #53314

Merged
merged 14 commits into from
Aug 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,12 @@ impl<'tcx> Mir<'tcx> {
}

#[inline]
pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
pub fn predecessors(&self) -> ReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
self.cache.predecessors(self)
}

#[inline]
pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<'_, Vec<BasicBlock>> {
ReadGuard::map(self.predecessors(), |p| &p[bb])
}

Expand Down Expand Up @@ -328,6 +328,14 @@ impl<'tcx> Mir<'tcx> {
pub fn return_ty(&self) -> Ty<'tcx> {
self.local_decls[RETURN_PLACE].ty
}

/// Get the location of the terminator for the given block
pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
Location {
block: bb,
statement_index: self[bb].statements.len(),
}
}
}

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_data_structures/graph/dominators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(

// compute the post order index (rank) for each node
let mut post_order_rank: IndexVec<G::Node, usize> =
IndexVec::from_elem_n(usize::default(), graph.num_nodes());
(0..graph.num_nodes()).map(|_| 0).collect();
for (index, node) in rpo.iter().rev().cloned().enumerate() {
post_order_rank[node] = index;
}

let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
IndexVec::from_elem_n(Option::default(), graph.num_nodes());
(0..graph.num_nodes()).map(|_| None).collect();
immediate_dominators[start_node] = Some(start_node);

let mut changed = true;
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_data_structures/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(in_band_lifetimes)]
#![feature(impl_header_lifetime_elision)]
#![feature(unboxed_closures)]
#![feature(fn_traits)]
#![feature(unsize)]
Expand Down Expand Up @@ -85,6 +87,7 @@ pub mod thin_vec;
pub mod transitive_relation;
pub mod tuple_slice;
pub use ena::unify;
pub mod vec_linked_list;
pub mod work_queue;
pub mod fingerprint;

Expand Down
83 changes: 83 additions & 0 deletions src/librustc_data_structures/vec_linked_list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use indexed_vec::{Idx, IndexVec};

pub fn iter<Ls>(
first: Option<Ls::LinkIndex>,
links: &'a Ls,
) -> impl Iterator<Item = Ls::LinkIndex> + 'a
where
Ls: Links,
{
VecLinkedListIterator {
links: links,
current: first,
}
}

pub struct VecLinkedListIterator<Ls>
where
Ls: Links,
{
links: Ls,
current: Option<Ls::LinkIndex>,
}

impl<Ls> Iterator for VecLinkedListIterator<Ls>
where
Ls: Links,
{
type Item = Ls::LinkIndex;

fn next(&mut self) -> Option<Ls::LinkIndex> {
if let Some(c) = self.current {
self.current = <Ls as Links>::next(&self.links, c);
Some(c)
} else {
None
}
}
}

pub trait Links {
type LinkIndex: Copy;

fn next(links: &Self, index: Self::LinkIndex) -> Option<Self::LinkIndex>;
}

impl<Ls> Links for &Ls
where
Ls: Links,
{
type LinkIndex = Ls::LinkIndex;

fn next(links: &Self, index: Ls::LinkIndex) -> Option<Ls::LinkIndex> {
<Ls as Links>::next(links, index)
}
}

pub trait LinkElem {
type LinkIndex: Copy;

fn next(elem: &Self) -> Option<Self::LinkIndex>;
}

impl<L, E> Links for IndexVec<L, E>
where
E: LinkElem<LinkIndex = L>,
L: Idx,
{
type LinkIndex = L;

fn next(links: &Self, index: L) -> Option<L> {
<E as LinkElem>::next(&links[index])
}
}
4 changes: 4 additions & 0 deletions src/librustc_mir/borrow_check/flows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
each_flow!(self, reset_to_entry_of(bb));
}

fn reset_to_exit_of(&mut self, bb: BasicBlock) {
each_flow!(self, reset_to_exit_of(bb));
}

fn reconstruct_statement_effect(&mut self, location: Location) {
each_flow!(self, reconstruct_statement_effect(location));
}
Expand Down
32 changes: 7 additions & 25 deletions src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
use rustc::mir::{Local, Location, Mir};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use util::liveness::{self, DefUse, LivenessMode};
use util::liveness::{self, DefUse};

crate fn find<'tcx>(
mir: &Mir<'tcx>,
Expand All @@ -32,10 +32,6 @@ crate fn find<'tcx>(
tcx,
region_vid,
start_point,
liveness_mode: LivenessMode {
include_regular_use: true,
include_drops: true,
},
};

uf.find()
Expand All @@ -47,7 +43,6 @@ struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
region_vid: RegionVid,
start_point: Location,
liveness_mode: LivenessMode,
}

impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
Expand Down Expand Up @@ -108,7 +103,6 @@ impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
mir: self.mir,
tcx: self.tcx,
region_vid: self.region_vid,
liveness_mode: self.liveness_mode,
def_use_result: None,
};

Expand All @@ -122,7 +116,6 @@ struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
mir: &'cx Mir<'tcx>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
region_vid: RegionVid,
liveness_mode: LivenessMode,
def_use_result: Option<DefUseResult>,
}

Expand All @@ -146,23 +139,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
});

if found_it {
match liveness::categorize(context, self.liveness_mode) {
Some(DefUse::Def) => {
self.def_use_result = Some(DefUseResult::Def);
}

Some(DefUse::Use) => {
self.def_use_result = if context.is_drop() {
Some(DefUseResult::UseDrop { local })
} else {
Some(DefUseResult::UseLive { local })
};
}

None => {
self.def_use_result = None;
}
}
self.def_use_result = match liveness::categorize(context) {
Some(DefUse::Def) => Some(DefUseResult::Def),
Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),
None => None,
};
}
}
}
91 changes: 4 additions & 87 deletions src/librustc_mir/borrow_check/nll/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::{LocationIndex, LocationTable};
use borrow_check::nll::facts::AllFactsExt;
use borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
use borrow_check::nll::type_check::liveness::liveness_map::{NllLivenessMap, LocalWithRegion};
use borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap;
use borrow_check::nll::region_infer::values::RegionValueElements;
use dataflow::indexes::BorrowIndex;
use dataflow::move_paths::MoveData;
Expand All @@ -22,22 +22,19 @@ use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
use rustc::ty::{self, RegionKind, RegionVid};
use rustc::util::nodemap::FxHashMap;
use rustc_errors::Diagnostic;
use std::collections::BTreeSet;
use std::fmt::Debug;
use std::env;
use std::io;
use std::path::PathBuf;
use std::rc::Rc;
use std::str::FromStr;
use transform::MirSource;
use util::liveness::{LivenessResults, LiveVarSet};

use self::mir_util::PassWhere;
use polonius_engine::{Algorithm, Output};
use util as mir_util;
use util::pretty::{self, ALIGN};
use util::pretty;

mod constraint_generation;
pub mod explain_borrow;
Expand Down Expand Up @@ -111,8 +108,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
let MirTypeckResults {
constraints,
universal_region_relations,
liveness,
liveness_map,
} = type_check::type_check(
infcx,
param_env,
Expand Down Expand Up @@ -205,8 +200,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
// write unit-tests, as well as helping with debugging.
dump_mir_results(
infcx,
&liveness,
&liveness_map,
MirSource::item(def_id),
&mir,
&regioncx,
Expand All @@ -222,8 +215,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(

fn dump_mir_results<'a, 'gcx, 'tcx>(
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
liveness: &LivenessResults<LocalWithRegion>,
liveness_map: &NllLivenessMap,
source: MirSource,
mir: &Mir<'tcx>,
regioncx: &RegionInferenceContext,
Expand All @@ -233,34 +224,6 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
return;
}

let regular_liveness_per_location: FxHashMap<_, _> = mir
.basic_blocks()
.indices()
.flat_map(|bb| {
let mut results = vec![];
liveness
.regular
.simulate_block(&mir, bb, liveness_map, |location, local_set| {
results.push((location, local_set.clone()));
});
results
})
.collect();

let drop_liveness_per_location: FxHashMap<_, _> = mir
.basic_blocks()
.indices()
.flat_map(|bb| {
let mut results = vec![];
liveness
.drop
.simulate_block(&mir, bb, liveness_map, |location, local_set| {
results.push((location, local_set.clone()));
});
results
})
.collect();

mir_util::dump_mir(
infcx.tcx,
None,
Expand All @@ -283,26 +246,10 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
}
}

PassWhere::BeforeLocation(location) => {
let s = live_variable_set(
&regular_liveness_per_location[&location],
&drop_liveness_per_location[&location],
);
writeln!(
out,
"{:ALIGN$} | Live variables on entry to {:?}: {}",
"",
location,
s,
ALIGN = ALIGN
)?;
PassWhere::BeforeLocation(_) => {
}

// After each basic block, dump out the values
// that are live on exit from the basic block.
PassWhere::AfterTerminator(bb) => {
let s = live_variable_set(&liveness.regular.outs[bb], &liveness.drop.outs[bb]);
writeln!(out, " | Live variables on exit from {:?}: {}", bb, s)?;
PassWhere::AfterTerminator(_) => {
}

PassWhere::BeforeBlock(_) | PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
Expand Down Expand Up @@ -420,33 +367,3 @@ impl ToRegionVid for RegionVid {
self
}
}

fn live_variable_set(
regular: &LiveVarSet<LocalWithRegion>,
drops: &LiveVarSet<LocalWithRegion>
) -> String {
// sort and deduplicate:
let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect();

// construct a string with each local, including `(drop)` if it is
// only dropped, versus a regular use.
let mut string = String::new();
for local in all_locals {
string.push_str(&format!("{:?}", local));

if !regular.contains(&local) {
assert!(drops.contains(&local));
string.push_str(" (drop)");
}

string.push_str(", ");
}

let len = if string.is_empty() {
0
} else {
string.len() - 2
};

format!("[{}]", &string[..len])
}
Loading