Skip to content

Commit

Permalink
Auto merge of #53314 - nikomatsakis:nll-invert-liveness, r=pnkfelix
Browse files Browse the repository at this point in the history
NLL: experiment with inverting liveness

I got inspired to see what would happen here.

Fixes #52460

r? @pnkfelix
  • Loading branch information
bors committed Aug 28, 2018
2 parents 59e52b1 + 8d231ec commit 83ddc33
Show file tree
Hide file tree
Showing 21 changed files with 1,001 additions and 608 deletions.
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 @@ -86,6 +88,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])
}

0 comments on commit 83ddc33

Please sign in to comment.