@@ -124,9 +124,22 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
124124 return ;
125125 }
126126
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) ;
128141 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 {
130143 // Merge locals that don't conflict.
131144 if conflicts. contains ( dest. local , src) {
132145 debug ! ( "at assignment {:?}, conflict {:?} vs. {:?}" , loc, dest. local, src) ;
@@ -370,16 +383,30 @@ struct Conflicts {
370383}
371384
372385impl 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+ ) ;
376400
377401 let mut conflicts = BitMatrix :: from_row_n (
378402 & BitSet :: new_empty ( body. local_decls . len ( ) ) ,
379403 body. local_decls . len ( ) ,
380404 ) ;
381405
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+
383410 for local in new_conflicts. iter ( ) {
384411 conflicts. union_row_with ( & new_conflicts, local) ;
385412 }
@@ -449,7 +476,7 @@ impl Conflicts {
449476 } ,
450477 ) ;
451478
452- let mut relevant_locals = Vec :: new ( ) ;
479+ let mut live_and_init_locals = Vec :: new ( ) ;
453480
454481 // Visit only reachable basic blocks. The exact order is not important.
455482 for ( block, data) in traversal:: preorder ( body) {
@@ -462,7 +489,7 @@ impl Conflicts {
462489 // that, we first collect in the `MaybeInitializedLocals` results in a forwards
463490 // traversal.
464491
465- relevant_locals . resize_with ( data. statements . len ( ) + 1 , || {
492+ live_and_init_locals . resize_with ( data. statements . len ( ) + 1 , || {
466493 BitSet :: new_empty ( body. local_decls . len ( ) )
467494 } ) ;
468495
@@ -471,19 +498,19 @@ impl Conflicts {
471498 let loc = Location { block, statement_index } ;
472499 init. seek_before_primary_effect ( loc) ;
473500
474- relevant_locals [ statement_index] . clone_from ( init. get ( ) ) ;
501+ live_and_init_locals [ statement_index] . clone_from ( init. get ( ) ) ;
475502 }
476503
477504 // Now, go backwards and union with the liveness results.
478505 for statement_index in ( 0 ..=data. statements . len ( ) ) . rev ( ) {
479506 let loc = Location { block, statement_index } ;
480507 live. seek_after_primary_effect ( loc) ;
481508
482- relevant_locals [ statement_index] . intersect ( live. get ( ) ) ;
509+ live_and_init_locals [ statement_index] . intersect ( live. get ( ) ) ;
483510
484511 trace ! ( "record conflicts at {:?}" , loc) ;
485512
486- record_conflicts ( & relevant_locals [ statement_index] ) ;
513+ record_conflicts ( & mut live_and_init_locals [ statement_index] ) ;
487514 }
488515
489516 init. seek_to_block_end ( block) ;
@@ -492,7 +519,7 @@ impl Conflicts {
492519 conflicts. intersect ( live. get ( ) ) ;
493520 trace ! ( "record conflicts at end of {:?}" , block) ;
494521
495- record_conflicts ( & conflicts) ;
522+ record_conflicts ( & mut conflicts) ;
496523 }
497524
498525 Self { matrix : conflicts, unify_cache : BitSet :: new_empty ( body. local_decls . len ( ) ) }
0 commit comments