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