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
This commit is contained in:
bors 2018-06-20 01:39:43 +00:00
commit 93a161170f
2 changed files with 21 additions and 13 deletions

View File

@ -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);

View File

@ -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,16 +228,11 @@ where
if let Some(child) = move_path.first_child {
todo.push(child);
}
if push_siblings {
// 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);
}
} else {
// after we've processed the original `mpi`, we should
// always traverse the siblings of any of its
// children.
push_siblings = true;
}
}
return None;
}