Skip to content

Commit 6f8409f

Browse files
committed
perf: Filter out and process fixed constraints first in region expansion
Should reduce the number of elements as well as branches in the extremely hot loop and process_constraint in benchmarks such as unicode_normalization
1 parent f48e576 commit 6f8409f

File tree

1 file changed

+32
-15
lines changed
  • src/librustc/infer/lexical_region_resolve

1 file changed

+32
-15
lines changed

src/librustc/infer/lexical_region_resolve/mod.rs

+32-15
Original file line numberDiff line numberDiff line change
@@ -297,48 +297,65 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
297297
}
298298

299299
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
300-
let mut process_constraint = |constraint: &Constraint<'tcx>| {
301-
let (a_region, b_vid, b_data, retain) = match *constraint {
300+
let mut changed = false;
301+
let mut constraints = Vec::new();
302+
for constraint in self.data.constraints.keys() {
303+
let (a_region, b_vid, b_data) = match *constraint {
302304
Constraint::RegSubVar(a_region, b_vid) => {
303305
let b_data = var_values.value_mut(b_vid);
304-
(a_region, b_vid, b_data, false)
306+
(a_region, b_vid, b_data)
305307
}
306308
Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
307-
VarValue::ErrorValue => return (false, false),
309+
VarValue::ErrorValue => continue,
308310
VarValue::Value(a_region) => {
309311
let b_data = var_values.value_mut(b_vid);
310-
let retain = match *b_data {
311-
VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
312-
_ => true,
313-
};
314-
(a_region, b_vid, b_data, retain)
312+
match *b_data {
313+
VarValue::Value(ReStatic) | VarValue::ErrorValue => (),
314+
_ => constraints.push((a_vid, b_vid)),
315+
}
316+
(a_region, b_vid, b_data)
315317
}
316318
},
317319
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
318320
// These constraints are checked after expansion
319321
// is done, in `collect_errors`.
320-
return (false, false);
322+
continue;
321323
}
322324
};
325+
let edge_changed = self.expand_node(a_region, b_vid, b_data);
326+
if edge_changed {
327+
changed = true
328+
}
329+
}
323330

331+
let mut process_constraint = |a_vid, b_vid| {
332+
let (a_region, b_data, retain) = match *var_values.value(a_vid) {
333+
VarValue::ErrorValue => return (false, false),
334+
VarValue::Value(a_region) => {
335+
let b_data = var_values.value_mut(b_vid);
336+
let retain = match *b_data {
337+
VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
338+
_ => true,
339+
};
340+
(a_region, b_data, retain)
341+
}
342+
};
324343
let changed = self.expand_node(a_region, b_vid, b_data);
325344
(changed, retain)
326345
};
327346

328347
// Using bitsets to track the remaining elements is faster than using a
329348
// `Vec` by itself (which requires removing elements, which requires
330349
// element shuffling, which is slow).
331-
let constraints: Vec<_> = self.data.constraints.keys().collect();
332350
let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len());
333351
let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len());
334-
let mut changed = true;
335352
while changed {
336353
changed = false;
337354
for index in live_indices.iter() {
338-
let constraint = constraints[index];
339-
let (edge_changed, retain) = process_constraint(constraint);
355+
let (a_vid, b_vid) = constraints[index];
356+
let (edge_changed, retain) = process_constraint(a_vid, b_vid);
340357
if edge_changed {
341-
changed = true;
358+
changed = true
342359
}
343360
if !retain {
344361
let changed = killed_indices.insert(index);

0 commit comments

Comments
 (0)