@@ -212,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
212
212
213
213
/// Identifies whether a predicate obligation needs processing.
214
214
///
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.
217
218
#[ inline( always) ]
218
219
fn needs_process_obligation ( & self , pending_obligation : & Self :: Obligation ) -> bool {
219
220
// If we were stalled on some unresolved variables, first check whether
220
221
// any of them have been resolved; if not, don't bother doing more work
221
222
// 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 ;
241
249
}
242
- false
243
- } ) ( )
244
- }
250
+ }
251
+ false
252
+ } ) ( ) ,
245
253
}
246
254
}
247
255
0 commit comments