diff options
| author | bors <bors@rust-lang.org> | 2018-06-20 01:39:43 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-06-20 01:39:43 +0000 |
| commit | 93a161170f6dd7b9f6605a23e332a07ab73fc804 (patch) | |
| tree | cbe210ff67a7a45e2849a6e381ec73d688b178c6 | |
| parent | ac8d1f7623f55746ff8f59d6b26f03c39cee5844 (diff) | |
| parent | ba0bb02f6ff241297281784d2aed7dd8c2c78c4d (diff) | |
| download | rust-93a161170f6dd7b9f6605a23e332a07ab73fc804.tar.gz rust-93a161170f6dd7b9f6605a23e332a07ab73fc804.zip | |
Auto merge of #51617 - nnethercote:nll-allocs, r=pnkfelix
Reduce number of allocations done by NLL
A couple of easy wins. Here are the NLL speedups that exceed 1%:
```
sentry-cli-check
avg: -3.5% min: -3.5% max: -3.5%
inflate-check
avg: -1.9% min: -1.9% max: -1.9%
inflate
avg: -1.7% min: -1.7% max: -1.7%
clap-rs-check
avg: -1.6% min: -1.6% max: -1.6%
cargo-check
avg: -1.6% min: -1.6% max: -1.6%
ripgrep-check
avg: -1.4% min: -1.4% max: -1.4%
serde-check
avg: -1.2% min: -1.2% max: -1.2%
regex-check
avg: -1.0% min: -1.0% max: -1.0%
sentry-cli
avg: -1.0% min: -1.0% max: -1.0%
```
r? @nikomatsakis
| -rw-r--r-- | src/librustc_mir/borrow_check/path_utils.rs | 5 | ||||
| -rw-r--r-- | src/librustc_mir/dataflow/at_location.rs | 29 |
2 files changed, 21 insertions, 13 deletions
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs index 4871d427d07..b692ffbb250 100644 --- a/src/librustc_mir/borrow_check/path_utils.rs +++ b/src/librustc_mir/borrow_check/path_utils.rs @@ -21,6 +21,7 @@ use rustc::mir::{BasicBlock, Location, Mir, Place}; use rustc::mir::{Projection, ProjectionElem, BorrowKind}; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::control_flow_graph::dominators::Dominators; +use rustc_data_structures::small_vec::SmallVec; use std::iter; pub(super) fn allow_two_phase_borrow<'a, 'tcx, 'gcx: 'tcx>( @@ -259,8 +260,8 @@ pub(super) fn places_conflict<'a, 'gcx: 'tcx, 'tcx>( /// Return all the prefixes of `place` in reverse order, including /// downcasts. -fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> Vec<&'a Place<'tcx>> { - let mut result = vec![]; +fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> SmallVec<[&'a Place<'tcx>; 8]> { + let mut result = SmallVec::new(); let mut place = place; loop { result.push(place); diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index 0fbb54e8e0a..a89d1afae86 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -204,10 +204,22 @@ where T: HasMoveData<'tcx> + BitDenotation<Idx = MovePathIndex>, { pub fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> { + // We process `mpi` before the loop below, for two reasons: + // - it's a little different from the loop case (we don't traverse its + // siblings); + // - ~99% of the time the loop isn't reached, and this code is hot, so + // we don't want to allocate `todo` unnecessarily. + if self.contains(&mpi) { + return Some(mpi); + } let move_data = self.operator().move_data(); + let move_path = &move_data.move_paths[mpi]; + let mut todo = if let Some(child) = move_path.first_child { + vec![child] + } else { + return None; + }; - let mut todo = vec![mpi]; - let mut push_siblings = false; // don't look at siblings of original `mpi`. while let Some(mpi) = todo.pop() { if self.contains(&mpi) { return Some(mpi); @@ -216,15 +228,10 @@ where if let Some(child) = move_path.first_child { todo.push(child); } - if push_siblings { - if let Some(sibling) = move_path.next_sibling { - todo.push(sibling); - } - } else { - // after we've processed the original `mpi`, we should - // always traverse the siblings of any of its - // children. - push_siblings = true; + // After we've processed the original `mpi`, we should always + // traverse the siblings of any of its children. + if let Some(sibling) = move_path.next_sibling { + todo.push(sibling); } } return None; |
