@@ -317,6 +317,8 @@ fn find_inevitable_calls_in_body<'tcx>(
317
317
let mut worklist: VecDeque < _ > =
318
318
inevitable_calls. indices ( ) . flat_map ( |bb| & predecessors[ bb] ) . collect ( ) ;
319
319
320
+ let mut successors = Vec :: with_capacity ( 2 ) ;
321
+
320
322
while let Some ( & bb) = worklist. pop_front ( ) {
321
323
// Determine all "relevant" successors. We ignore successors only reached via unwinding.
322
324
let terminator = body[ bb] . terminator ( ) ;
@@ -347,43 +349,15 @@ fn find_inevitable_calls_in_body<'tcx>(
347
349
}
348
350
} ;
349
351
350
- // All callees that are guaranteed to be reached by every successor will also be reached by
351
- // `bb`. Compute the intersection.
352
- let successors = relevant_successors. copied ( ) ;
353
-
354
- // For efficiency, we initially only consider the smallest set.
355
- let ( smallest_successor_set_index, smallest_successor_set_bb) = match successors
356
- . clone ( )
357
- . enumerate ( )
358
- . min_by_key ( |( _, bb) | inevitable_calls[ * bb] . len ( ) )
359
- {
360
- Some ( ( i, bb) ) => ( i, bb) ,
361
- None => continue , // No callees will be added
362
- } ;
352
+ successors. clear ( ) ;
353
+ successors. extend ( relevant_successors. copied ( ) ) ;
363
354
364
355
let mut dest_set = mem:: take ( & mut inevitable_calls[ bb] ) ;
365
- let len = dest_set. len ( ) ;
366
- for callee in & inevitable_calls[ smallest_successor_set_bb] {
367
- if dest_set. contains ( callee) {
368
- continue ;
369
- }
370
356
371
- // `callee` must be contained in *every* successor's set.
372
- let add = successors. clone ( ) . enumerate ( ) . all ( |( i, bb) | {
373
- if i == smallest_successor_set_index {
374
- return true ;
375
- }
376
- let callee_set = & inevitable_calls[ bb] ;
377
- callee_set. contains ( callee)
378
- } ) ;
379
-
380
- if add {
381
- dest_set. insert ( callee. clone ( ) ) ;
382
- }
383
- }
357
+ let changed = propagate_successors ( & mut dest_set, & inevitable_calls, & successors) ;
384
358
385
359
inevitable_calls[ bb] = dest_set;
386
- if inevitable_calls [ bb ] . len ( ) != len {
360
+ if changed {
387
361
// `bb`s inevitable callees were modified, so propagate that backwards.
388
362
worklist. extend ( & predecessors[ bb] ) ;
389
363
}
@@ -395,6 +369,58 @@ fn find_inevitable_calls_in_body<'tcx>(
395
369
} )
396
370
}
397
371
372
+ /// Propagates inevitable calls from `successors` into their predecessor's `dest_set`.
373
+ ///
374
+ /// Returns `true` if `dest_set` was changed.
375
+ fn propagate_successors < ' tcx > (
376
+ dest_set : & mut FxHashSet < Callee < ' tcx > > ,
377
+ inevitable_calls : & IndexVec < BasicBlock , FxHashSet < Callee < ' tcx > > > ,
378
+ successors : & [ BasicBlock ] ,
379
+ ) -> bool {
380
+ let len = dest_set. len ( ) ;
381
+
382
+ match successors {
383
+ [ successor] => {
384
+ // If there's only one successor, just add all of its calls to `dest_set`.
385
+ dest_set. extend ( inevitable_calls[ * successor] . iter ( ) . copied ( ) ) ;
386
+ }
387
+ _ => {
388
+ // All callees that are guaranteed to be reached by every successor will also be reached by
389
+ // `bb`. Compute the intersection.
390
+ // For efficiency, we initially only consider the smallest set.
391
+ let ( smallest_successor_set_index, smallest_successor_set_bb) = match successors
392
+ . iter ( )
393
+ . enumerate ( )
394
+ . min_by_key ( |( _, & bb) | inevitable_calls[ bb] . len ( ) )
395
+ {
396
+ Some ( ( i, bb) ) => ( i, * bb) ,
397
+ None => return false , // No callees will be added
398
+ } ;
399
+
400
+ for callee in & inevitable_calls[ smallest_successor_set_bb] {
401
+ if dest_set. contains ( callee) {
402
+ continue ;
403
+ }
404
+
405
+ // `callee` must be contained in *every* successor's set.
406
+ let add = successors. iter ( ) . enumerate ( ) . all ( |( i, bb) | {
407
+ if i == smallest_successor_set_index {
408
+ return true ;
409
+ }
410
+ let callee_set = & inevitable_calls[ * bb] ;
411
+ callee_set. contains ( callee)
412
+ } ) ;
413
+
414
+ if add {
415
+ dest_set. insert ( callee. clone ( ) ) ;
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ dest_set. len ( ) != len
422
+ }
423
+
398
424
/// Information about a callee tracked by this algorithm.
399
425
#[ derive( Debug , Eq , PartialEq , Hash , Copy , Clone ) ]
400
426
struct Callee < ' tcx > {
0 commit comments