Skip to content

Commit 5ca99b7

Browse files
committed
Avoid chain() in find_constraint_paths_between_regions().
This iterator can be hot, and chained iterators are slow. The second half of the chain is almost always empty, so this commit changes the code to avoid the chained iteration. This change reduces instruction counts for the `wg-grammar` benchmark by up to 1.5%.
1 parent 6c2c29c commit 5ca99b7

File tree

2 files changed

+22
-18
lines changed
  • src/librustc_mir

2 files changed

+22
-18
lines changed

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

+21-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::borrow_check::nll::constraints::OutlivesConstraint;
2-
use crate::borrow_check::nll::region_infer::AppliedMemberConstraint;
32
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
43
use crate::borrow_check::nll::type_check::Locations;
54
use crate::borrow_check::nll::universal_regions::DefiningTy;
@@ -253,29 +252,33 @@ impl<'tcx> RegionInferenceContext<'tcx> {
253252
let outgoing_edges_from_graph = self.constraint_graph
254253
.outgoing_edges(r, &self.constraints, fr_static);
255254

256-
257-
// But member constraints can also give rise to `'r: 'x`
258-
// edges that were not part of the graph initially, so
259-
// watch out for those.
260-
let outgoing_edges_from_picks = self.applied_member_constraints(r)
261-
.iter()
262-
.map(|&AppliedMemberConstraint { min_choice, member_constraint_index, .. }| {
263-
let p_c = &self.member_constraints[member_constraint_index];
264-
OutlivesConstraint {
265-
sup: r,
266-
sub: min_choice,
267-
locations: Locations::All(p_c.definition_span),
268-
category: ConstraintCategory::OpaqueType,
269-
}
270-
});
271-
272-
for constraint in outgoing_edges_from_graph.chain(outgoing_edges_from_picks) {
255+
// Always inline this closure because it can be hot.
256+
let mut handle_constraint = #[inline(always)] |constraint: OutlivesConstraint| {
273257
debug_assert_eq!(constraint.sup, r);
274258
let sub_region = constraint.sub;
275259
if let Trace::NotVisited = context[sub_region] {
276260
context[sub_region] = Trace::FromOutlivesConstraint(constraint);
277261
deque.push_back(sub_region);
278262
}
263+
};
264+
265+
// This loop can be hot.
266+
for constraint in outgoing_edges_from_graph {
267+
handle_constraint(constraint);
268+
}
269+
270+
// Member constraints can also give rise to `'r: 'x` edges that
271+
// were not part of the graph initially, so watch out for those.
272+
// (But they are extremely rare; this loop is very cold.)
273+
for constraint in self.applied_member_constraints(r) {
274+
let p_c = &self.member_constraints[constraint.member_constraint_index];
275+
let constraint = OutlivesConstraint {
276+
sup: r,
277+
sub: constraint.min_choice,
278+
locations: Locations::All(p_c.definition_span),
279+
category: ConstraintCategory::OpaqueType,
280+
};
281+
handle_constraint(constraint);
279282
}
280283
}
281284

src/librustc_mir/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
2525
#![feature(mem_take)]
2626
#![feature(associated_type_bounds)]
2727
#![feature(range_is_empty)]
28+
#![feature(stmt_expr_attributes)]
2829

2930
#![recursion_limit="256"]
3031

0 commit comments

Comments
 (0)