Skip to content

Commit 93a1611

Browse files
committed
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
2 parents ac8d1f7 + ba0bb02 commit 93a1611

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

src/librustc_mir/borrow_check/path_utils.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc::mir::{BasicBlock, Location, Mir, Place};
2121
use rustc::mir::{Projection, ProjectionElem, BorrowKind};
2222
use rustc::ty::{self, TyCtxt};
2323
use rustc_data_structures::control_flow_graph::dominators::Dominators;
24+
use rustc_data_structures::small_vec::SmallVec;
2425
use std::iter;
2526

2627
pub(super) fn allow_two_phase_borrow<'a, 'tcx, 'gcx: 'tcx>(
@@ -259,8 +260,8 @@ pub(super) fn places_conflict<'a, 'gcx: 'tcx, 'tcx>(
259260

260261
/// Return all the prefixes of `place` in reverse order, including
261262
/// downcasts.
262-
fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> Vec<&'a Place<'tcx>> {
263-
let mut result = vec![];
263+
fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> SmallVec<[&'a Place<'tcx>; 8]> {
264+
let mut result = SmallVec::new();
264265
let mut place = place;
265266
loop {
266267
result.push(place);

src/librustc_mir/dataflow/at_location.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,22 @@ where
204204
T: HasMoveData<'tcx> + BitDenotation<Idx = MovePathIndex>,
205205
{
206206
pub fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
207+
// We process `mpi` before the loop below, for two reasons:
208+
// - it's a little different from the loop case (we don't traverse its
209+
// siblings);
210+
// - ~99% of the time the loop isn't reached, and this code is hot, so
211+
// we don't want to allocate `todo` unnecessarily.
212+
if self.contains(&mpi) {
213+
return Some(mpi);
214+
}
207215
let move_data = self.operator().move_data();
216+
let move_path = &move_data.move_paths[mpi];
217+
let mut todo = if let Some(child) = move_path.first_child {
218+
vec![child]
219+
} else {
220+
return None;
221+
};
208222

209-
let mut todo = vec![mpi];
210-
let mut push_siblings = false; // don't look at siblings of original `mpi`.
211223
while let Some(mpi) = todo.pop() {
212224
if self.contains(&mpi) {
213225
return Some(mpi);
@@ -216,15 +228,10 @@ where
216228
if let Some(child) = move_path.first_child {
217229
todo.push(child);
218230
}
219-
if push_siblings {
220-
if let Some(sibling) = move_path.next_sibling {
221-
todo.push(sibling);
222-
}
223-
} else {
224-
// after we've processed the original `mpi`, we should
225-
// always traverse the siblings of any of its
226-
// children.
227-
push_siblings = true;
231+
// After we've processed the original `mpi`, we should always
232+
// traverse the siblings of any of its children.
233+
if let Some(sibling) = move_path.next_sibling {
234+
todo.push(sibling);
228235
}
229236
}
230237
return None;

0 commit comments

Comments
 (0)