@@ -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
}
@@ -435,7 +462,7 @@ impl Conflicts {
435
462
} ,
436
463
) ;
437
464
438
- let mut relevant_locals = Vec :: new ( ) ;
465
+ let mut live_and_init_locals = Vec :: new ( ) ;
439
466
440
467
// Visit only reachable basic blocks. The exact order is not important.
441
468
for ( block, data) in traversal:: preorder ( body) {
@@ -448,7 +475,7 @@ impl Conflicts {
448
475
// that, we first collect in the `MaybeInitializedLocals` results in a forwards
449
476
// traversal.
450
477
451
- relevant_locals . resize_with ( data. statements . len ( ) + 1 , || {
478
+ live_and_init_locals . resize_with ( data. statements . len ( ) + 1 , || {
452
479
BitSet :: new_empty ( body. local_decls . len ( ) )
453
480
} ) ;
454
481
@@ -457,19 +484,19 @@ impl Conflicts {
457
484
let loc = Location { block, statement_index } ;
458
485
init. seek_before_primary_effect ( loc) ;
459
486
460
- relevant_locals [ statement_index] . overwrite ( init. get ( ) ) ;
487
+ live_and_init_locals [ statement_index] . overwrite ( init. get ( ) ) ;
461
488
}
462
489
463
490
// Now, go backwards and union with the liveness results.
464
491
for statement_index in ( 0 ..=data. statements . len ( ) ) . rev ( ) {
465
492
let loc = Location { block, statement_index } ;
466
493
live. seek_after_primary_effect ( loc) ;
467
494
468
- relevant_locals [ statement_index] . intersect ( live. get ( ) ) ;
495
+ live_and_init_locals [ statement_index] . intersect ( live. get ( ) ) ;
469
496
470
497
trace ! ( "record conflicts at {:?}" , loc) ;
471
498
472
- record_conflicts ( & relevant_locals [ statement_index] ) ;
499
+ record_conflicts ( & mut live_and_init_locals [ statement_index] ) ;
473
500
}
474
501
475
502
init. seek_to_block_end ( block) ;
@@ -478,7 +505,7 @@ impl Conflicts {
478
505
conflicts. intersect ( live. get ( ) ) ;
479
506
trace ! ( "record conflicts at end of {:?}" , block) ;
480
507
481
- record_conflicts ( & conflicts) ;
508
+ record_conflicts ( & mut conflicts) ;
482
509
}
483
510
484
511
Self { matrix : conflicts, unify_cache : BitSet :: new_empty ( body. local_decls . len ( ) ) }
0 commit comments