Skip to content

Commit

Permalink
Auto merge of #51987 - nikomatsakis:nll-region-infer-scc, r=pnkfelix
Browse files Browse the repository at this point in the history
nll experiment: compute SCCs instead of iterative region solving

This is an attempt to speed up region solving by replacing the current iterative dataflow with a SCC computation. The idea is to detect cycles (SCCs) amongst region constraints and then compute just one value per cycle. The graph with all cycles removed is of course a DAG, so we can then solve constraints "bottom up" once the liveness values are known.

I kinda ran out of time this morning so the last commit is a bit sloppy but I wanted to get this posted, let travis run on it, and maybe do a perf run, before I clean it up.
  • Loading branch information
bors committed Jul 13, 2018
2 parents c0955a3 + 6918c17 commit bce32b5
Show file tree
Hide file tree
Showing 43 changed files with 1,728 additions and 919 deletions.
4 changes: 2 additions & 2 deletions src/librustc/cfg/construct.rs
Expand Up @@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc_data_structures::graph;
use cfg::*;
use middle::region;
use ty::{self, TyCtxt};
use rustc_data_structures::graph::implementation as graph;
use syntax::ptr::P;
use ty::{self, TyCtxt};

use hir::{self, PatKind};
use hir::def_id::DefId;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/cfg/mod.rs
Expand Up @@ -11,7 +11,7 @@
//! Module that constructs a control-flow graph representing an item.
//! Uses `Graph` as the underlying representation.

use rustc_data_structures::graph;
use rustc_data_structures::graph::implementation as graph;
use ty::TyCtxt;
use hir;
use hir::def_id::DefId;
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/dep_graph/query.rs
Expand Up @@ -9,7 +9,9 @@
// except according to those terms.

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph::{Direction, INCOMING, Graph, NodeIndex, OUTGOING};
use rustc_data_structures::graph::implementation::{
Direction, INCOMING, Graph, NodeIndex, OUTGOING
};

use super::DepNode;

Expand Down
10 changes: 5 additions & 5 deletions src/librustc/infer/lexical_region_resolve/mod.rs
Expand Up @@ -20,7 +20,7 @@ use infer::region_constraints::VerifyBound;
use middle::free_region::RegionRelations;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING};
use rustc_data_structures::graph::implementation::{Graph, Direction, NodeIndex, INCOMING, OUTGOING};
use std::fmt;
use std::u32;
use ty::{self, TyCtxt};
Expand Down Expand Up @@ -99,7 +99,7 @@ struct RegionAndOrigin<'tcx> {
origin: SubregionOrigin<'tcx>,
}

type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>;

struct LexicalResolver<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
region_rels: &'cx RegionRelations<'cx, 'gcx, 'tcx>,
Expand Down Expand Up @@ -501,7 +501,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
fn construct_graph(&self) -> RegionGraph<'tcx> {
let num_vars = self.num_vars();

let mut graph = graph::Graph::new();
let mut graph = Graph::new();

for _ in 0..num_vars {
graph.add_node(());
Expand Down Expand Up @@ -550,9 +550,9 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
// Errors in expanding nodes result from a lower-bound that is
// not contained by an upper-bound.
let (mut lower_bounds, lower_dup) =
self.collect_concrete_regions(graph, node_idx, graph::INCOMING, dup_vec);
self.collect_concrete_regions(graph, node_idx, INCOMING, dup_vec);
let (mut upper_bounds, upper_dup) =
self.collect_concrete_regions(graph, node_idx, graph::OUTGOING, dup_vec);
self.collect_concrete_regions(graph, node_idx, OUTGOING, dup_vec);

if lower_dup || upper_dup {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/dataflow.rs
Expand Up @@ -22,7 +22,7 @@ use std::mem;
use std::usize;
use syntax::print::pprust::PrintState;

use rustc_data_structures::graph::OUTGOING;
use rustc_data_structures::graph::implementation::OUTGOING;

use util::nodemap::FxHashMap;
use hir;
Expand Down
20 changes: 14 additions & 6 deletions src/librustc/mir/mod.rs
Expand Up @@ -21,9 +21,8 @@ use mir::interpret::{EvalErrorKind, Scalar, Value};
use mir::visit::MirVisitable;
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
use rustc_data_structures::control_flow_graph::dominators::{dominators, Dominators};
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
use rustc_data_structures::graph::dominators::{dominators, Dominators};
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::small_vec::SmallVec;
use rustc_data_structures::sync::Lrc;
Expand Down Expand Up @@ -2289,23 +2288,32 @@ fn item_path_str(def_id: DefId) -> String {
ty::tls::with(|tcx| tcx.item_path_str(def_id))
}

impl<'tcx> ControlFlowGraph for Mir<'tcx> {
impl<'tcx> graph::DirectedGraph for Mir<'tcx> {
type Node = BasicBlock;
}

impl<'tcx> graph::WithNumNodes for Mir<'tcx> {
fn num_nodes(&self) -> usize {
self.basic_blocks.len()
}
}

impl<'tcx> graph::WithStartNode for Mir<'tcx> {
fn start_node(&self) -> Self::Node {
START_BLOCK
}
}

impl<'tcx> graph::WithPredecessors for Mir<'tcx> {
fn predecessors<'graph>(
&'graph self,
node: Self::Node,
) -> <Self as GraphPredecessors<'graph>>::Iter {
self.predecessors_for(node).clone().into_iter()
}
}

impl<'tcx> graph::WithSuccessors for Mir<'tcx> {
fn successors<'graph>(
&'graph self,
node: Self::Node,
Expand All @@ -2314,12 +2322,12 @@ impl<'tcx> ControlFlowGraph for Mir<'tcx> {
}
}

impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {
impl<'a, 'b> graph::GraphPredecessors<'b> for Mir<'a> {
type Item = BasicBlock;
type Iter = IntoIter<BasicBlock>;
}

impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> {
impl<'a, 'b> graph::GraphSuccessors<'b> for Mir<'a> {
type Item = BasicBlock;
type Iter = iter::Cloned<Successors<'b>>;
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/mir/analyze.rs
Expand Up @@ -12,7 +12,7 @@
//! which do not.

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::control_flow_graph::dominators::Dominators;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::mir::{self, Location, TerminatorKind};
use rustc::mir::visit::{Visitor, PlaceContext};
Expand Down
42 changes: 0 additions & 42 deletions src/librustc_data_structures/control_flow_graph/mod.rs

This file was deleted.

Expand Up @@ -14,9 +14,9 @@
//! Rice Computer Science TS-06-33870
//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>

use super::ControlFlowGraph;
use super::super::indexed_vec::{Idx, IndexVec};
use super::iterate::reverse_post_order;
use super::super::indexed_vec::{IndexVec, Idx};
use super::ControlFlowGraph;

use std::fmt;

Expand All @@ -29,15 +29,16 @@ pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
dominators_given_rpo(graph, &rpo)
}

pub fn dominators_given_rpo<G: ControlFlowGraph>(graph: &G,
rpo: &[G::Node])
-> Dominators<G::Node> {
pub fn dominators_given_rpo<G: ControlFlowGraph>(
graph: &G,
rpo: &[G::Node],
) -> Dominators<G::Node> {
let start_node = graph.start_node();
assert_eq!(rpo[0], start_node);

// 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());
let mut post_order_rank: IndexVec<G::Node, usize> =
IndexVec::from_elem_n(usize::default(), graph.num_nodes());
for (index, node) in rpo.iter().rev().cloned().enumerate() {
post_order_rank[node] = index;
}
Expand All @@ -56,10 +57,12 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(graph: &G,
if immediate_dominators[pred].is_some() {
// (*)
// (*) dominators for `pred` have been calculated
new_idom = intersect_opt(&post_order_rank,
&immediate_dominators,
new_idom,
Some(pred));
new_idom = intersect_opt(
&post_order_rank,
&immediate_dominators,
new_idom,
Some(pred),
);
}
}

Expand All @@ -76,23 +79,25 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(graph: &G,
}
}

fn intersect_opt<Node: Idx>(post_order_rank: &IndexVec<Node, usize>,
immediate_dominators: &IndexVec<Node, Option<Node>>,
node1: Option<Node>,
node2: Option<Node>)
-> Option<Node> {
fn intersect_opt<Node: Idx>(
post_order_rank: &IndexVec<Node, usize>,
immediate_dominators: &IndexVec<Node, Option<Node>>,
node1: Option<Node>,
node2: Option<Node>,
) -> Option<Node> {
match (node1, node2) {
(None, None) => None,
(Some(n), None) | (None, Some(n)) => Some(n),
(Some(n1), Some(n2)) => Some(intersect(post_order_rank, immediate_dominators, n1, n2)),
}
}

fn intersect<Node: Idx>(post_order_rank: &IndexVec<Node, usize>,
immediate_dominators: &IndexVec<Node, Option<Node>>,
mut node1: Node,
mut node2: Node)
-> Node {
fn intersect<Node: Idx>(
post_order_rank: &IndexVec<Node, usize>,
immediate_dominators: &IndexVec<Node, Option<Node>>,
mut node1: Node,
mut node2: Node,
) -> Node {
while node1 != node2 {
while post_order_rank[node1] < post_order_rank[node2] {
node1 = immediate_dominators[node1].unwrap();
Expand Down Expand Up @@ -176,11 +181,13 @@ impl<Node: Idx> DominatorTree<Node> {

impl<Node: Idx> fmt::Debug for DominatorTree<Node> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&DominatorTreeNode {
tree: self,
node: self.root,
},
fmt)
fmt::Debug::fmt(
&DominatorTreeNode {
tree: self,
node: self.root,
},
fmt,
)
}
}

Expand All @@ -194,11 +201,9 @@ impl<'tree, Node: Idx> fmt::Debug for DominatorTreeNode<'tree, Node> {
let subtrees: Vec<_> = self.tree
.children(self.node)
.iter()
.map(|&child| {
DominatorTreeNode {
tree: self.tree,
node: child,
}
.map(|&child| DominatorTreeNode {
tree: self.tree,
node: child,
})
.collect();
fmt.debug_tuple("")
Expand Down

0 comments on commit bce32b5

Please sign in to comment.