Skip to content

Commit 507a6cf

Browse files
authored
Rollup merge of rust-lang#108681 - nnethercote:needs_process_obligation-comments, r=lqd
Improve comments in `needs_process_obligation`. And a couple of other places. r? `@lqd`
2 parents f30e546 + 3bcea5f commit 507a6cf

File tree

2 files changed

+34
-24
lines changed
  • compiler
    • rustc_data_structures/src/obligation_forest
    • rustc_trait_selection/src/traits

2 files changed

+34
-24
lines changed

Diff for: compiler/rustc_data_structures/src/obligation_forest/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ impl<O: ForestObligation> ObligationForest<O> {
426426
// nodes. Therefore we use a `while` loop.
427427
let mut index = 0;
428428
while let Some(node) = self.nodes.get_mut(index) {
429+
// This test is extremely hot.
429430
if node.state.get() != NodeState::Pending
430431
|| !processor.needs_process_obligation(&node.obligation)
431432
{
@@ -439,6 +440,7 @@ impl<O: ForestObligation> ObligationForest<O> {
439440
// out of sync with `nodes`. It's not very common, but it does
440441
// happen, and code in `compress` has to allow for it.
441442

443+
// This code is much less hot.
442444
match processor.process_obligation(&mut node.obligation) {
443445
ProcessResult::Unchanged => {
444446
// No change in state.

Diff for: compiler/rustc_trait_selection/src/traits/fulfill.rs

+32-24
Original file line numberDiff line numberDiff line change
@@ -212,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
212212

213213
/// Identifies whether a predicate obligation needs processing.
214214
///
215-
/// This is always inlined, despite its size, because it has a single
216-
/// callsite and it is called *very* frequently.
215+
/// This is always inlined because it has a single callsite and it is
216+
/// called *very* frequently. Be careful modifying this code! Several
217+
/// compile-time benchmarks are very sensitive to even small changes.
217218
#[inline(always)]
218219
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
219220
// If we were stalled on some unresolved variables, first check whether
220221
// any of them have been resolved; if not, don't bother doing more work
221222
// yet.
222-
match pending_obligation.stalled_on.len() {
223-
// Match arms are in order of frequency, which matters because this
224-
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
225-
1 => {
226-
let infer_var = pending_obligation.stalled_on[0];
227-
self.selcx.infcx.ty_or_const_infer_var_changed(infer_var)
228-
}
229-
0 => {
230-
// In this case we haven't changed, but wish to make a change.
231-
true
232-
}
233-
_ => {
234-
// This `for` loop was once a call to `all()`, but this lower-level
235-
// form was a perf win. See #64545 for details.
236-
(|| {
237-
for &infer_var in &pending_obligation.stalled_on {
238-
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
239-
return true;
240-
}
223+
let stalled_on = &pending_obligation.stalled_on;
224+
match stalled_on.len() {
225+
// This case is the hottest most of the time, being hit up to 99%
226+
// of the time. `keccak` and `cranelift-codegen-0.82.1` are
227+
// benchmarks that particularly stress this path.
228+
1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
229+
230+
// In this case we haven't changed, but wish to make a change. Note
231+
// that this is a special case, and is not equivalent to the `_`
232+
// case below, which would return `false` for an empty `stalled_on`
233+
// vector.
234+
//
235+
// This case is usually hit only 1% of the time or less, though it
236+
// reaches 20% in `wasmparser-0.101.0`.
237+
0 => true,
238+
239+
// This case is usually hit only 1% of the time or less, though it
240+
// reaches 95% in `mime-0.3.16`, 64% in `wast-54.0.0`, and 12% in
241+
// `inflate-0.4.5`.
242+
//
243+
// The obvious way of writing this, with a call to `any()` and no
244+
// closure, is currently slower than this version.
245+
_ => (|| {
246+
for &infer_var in stalled_on {
247+
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
248+
return true;
241249
}
242-
false
243-
})()
244-
}
250+
}
251+
false
252+
})(),
245253
}
246254
}
247255

0 commit comments

Comments
 (0)