@@ -124,9 +124,22 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
124
124
return ;
125
125
}
126
126
127
- let mut conflicts = Conflicts :: build ( tcx, body, source) ;
127
+ let candidates = find_candidates ( tcx, body) ;
128
+ if candidates. is_empty ( ) {
129
+ debug ! ( "{:?}: no dest prop candidates, done" , source. def_id( ) ) ;
130
+ return ;
131
+ }
132
+
133
+ // Collect all locals we care about. We only compute conflicts for these to save time.
134
+ let mut relevant_locals = BitSet :: new_empty ( body. local_decls . len ( ) ) ;
135
+ for CandidateAssignment { dest, src, loc : _ } in & candidates {
136
+ relevant_locals. insert ( dest. local ) ;
137
+ relevant_locals. insert ( * src) ;
138
+ }
139
+
140
+ let mut conflicts = Conflicts :: build ( tcx, body, source, & relevant_locals) ;
128
141
let mut replacements = Replacements :: new ( body. local_decls . len ( ) ) ;
129
- for candidate @ CandidateAssignment { dest, src, loc } in find_candidates ( tcx , body ) {
142
+ for candidate @ CandidateAssignment { dest, src, loc } in candidates {
130
143
// Merge locals that don't conflict.
131
144
if conflicts. contains ( dest. local , src) {
132
145
debug ! ( "at assignment {:?}, conflict {:?} vs. {:?}" , loc, dest. local, src) ;
@@ -370,16 +383,30 @@ struct Conflicts {
370
383
}
371
384
372
385
impl Conflicts {
373
- fn build < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & ' _ Body < ' tcx > , source : MirSource < ' tcx > ) -> Self {
374
- // We don't have to look out for locals that have their address taken, since `find_candidates`
375
- // already takes care of that.
386
+ fn build < ' tcx > (
387
+ tcx : TyCtxt < ' tcx > ,
388
+ body : & ' _ Body < ' tcx > ,
389
+ source : MirSource < ' tcx > ,
390
+ relevant_locals : & BitSet < Local > ,
391
+ ) -> Self {
392
+ // We don't have to look out for locals that have their address taken, since
393
+ // `find_candidates` already takes care of that.
394
+
395
+ debug ! (
396
+ "Conflicts::build: {}/{} locals relevant" ,
397
+ relevant_locals. count( ) ,
398
+ body. local_decls. len( )
399
+ ) ;
376
400
377
401
let mut conflicts = BitMatrix :: from_row_n (
378
402
& BitSet :: new_empty ( body. local_decls . len ( ) ) ,
379
403
body. local_decls . len ( ) ,
380
404
) ;
381
405
382
- let mut record_conflicts = |new_conflicts : & BitSet < _ > | {
406
+ let mut record_conflicts = |new_conflicts : & mut BitSet < _ > | {
407
+ // Remove all locals that are not candidates.
408
+ new_conflicts. intersect ( relevant_locals) ;
409
+
383
410
for local in new_conflicts. iter ( ) {
384
411
conflicts. union_row_with ( & new_conflicts, local) ;
385
412
}
@@ -449,7 +476,7 @@ impl Conflicts {
449
476
} ,
450
477
) ;
451
478
452
- let mut relevant_locals = Vec :: new ( ) ;
479
+ let mut live_and_init_locals = Vec :: new ( ) ;
453
480
454
481
// Visit only reachable basic blocks. The exact order is not important.
455
482
for ( block, data) in traversal:: preorder ( body) {
@@ -462,7 +489,7 @@ impl Conflicts {
462
489
// that, we first collect in the `MaybeInitializedLocals` results in a forwards
463
490
// traversal.
464
491
465
- relevant_locals . resize_with ( data. statements . len ( ) + 1 , || {
492
+ live_and_init_locals . resize_with ( data. statements . len ( ) + 1 , || {
466
493
BitSet :: new_empty ( body. local_decls . len ( ) )
467
494
} ) ;
468
495
@@ -471,19 +498,19 @@ impl Conflicts {
471
498
let loc = Location { block, statement_index } ;
472
499
init. seek_before_primary_effect ( loc) ;
473
500
474
- relevant_locals [ statement_index] . clone_from ( init. get ( ) ) ;
501
+ live_and_init_locals [ statement_index] . clone_from ( init. get ( ) ) ;
475
502
}
476
503
477
504
// Now, go backwards and union with the liveness results.
478
505
for statement_index in ( 0 ..=data. statements . len ( ) ) . rev ( ) {
479
506
let loc = Location { block, statement_index } ;
480
507
live. seek_after_primary_effect ( loc) ;
481
508
482
- relevant_locals [ statement_index] . intersect ( live. get ( ) ) ;
509
+ live_and_init_locals [ statement_index] . intersect ( live. get ( ) ) ;
483
510
484
511
trace ! ( "record conflicts at {:?}" , loc) ;
485
512
486
- record_conflicts ( & relevant_locals [ statement_index] ) ;
513
+ record_conflicts ( & mut live_and_init_locals [ statement_index] ) ;
487
514
}
488
515
489
516
init. seek_to_block_end ( block) ;
@@ -492,7 +519,7 @@ impl Conflicts {
492
519
conflicts. intersect ( live. get ( ) ) ;
493
520
trace ! ( "record conflicts at end of {:?}" , block) ;
494
521
495
- record_conflicts ( & conflicts) ;
522
+ record_conflicts ( & mut conflicts) ;
496
523
}
497
524
498
525
Self { matrix : conflicts, unify_cache : BitSet :: new_empty ( body. local_decls . len ( ) ) }
0 commit comments