134
134
use rustc_data_structures:: fx:: FxIndexMap ;
135
135
use rustc_index:: bit_set:: { BitMatrix , DenseBitSet } ;
136
136
use rustc_index:: interval:: SparseIntervalMatrix ;
137
+ use rustc_index:: { IndexVec , newtype_index} ;
137
138
use rustc_middle:: bug;
138
139
use rustc_middle:: mir:: visit:: { MutVisitor , PlaceContext , Visitor } ;
139
140
use rustc_middle:: mir:: {
@@ -186,8 +187,13 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
186
187
trace ! ( ?candidates) ;
187
188
dest_prop_mir_dump ( tcx, body, & points, & live, round_count) ;
188
189
189
- let mut filter =
190
- FilterInformation :: filter_liveness ( & points, & live, & mut write_info, body) ;
190
+ let mut filter = FilterInformation :: filter_liveness (
191
+ & points,
192
+ & live,
193
+ & mut write_info,
194
+ body,
195
+ & candidates,
196
+ ) ;
191
197
192
198
// This is the set of merges we will apply this round. It is a subset of the candidates.
193
199
let mut merges = FxIndexMap :: default ( ) ;
@@ -316,6 +322,45 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
316
322
}
317
323
}
318
324
325
+ //////////////////////////////////////////////////////////
326
+ // Relevant locals
327
+ //
328
+ // Small utility to reduce size of the conflict matrix by only considering locals that appear in
329
+ // the candidates
330
+
331
+ newtype_index ! {
332
+ /// Represent a subset of locals which appear in candidates.
333
+ struct RelevantLocal { }
334
+ }
335
+
336
+ #[ derive( Debug ) ]
337
+ struct RelevantLocals {
338
+ original : IndexVec < RelevantLocal , Local > ,
339
+ shrink : IndexVec < Local , Option < RelevantLocal > > ,
340
+ }
341
+
342
+ impl RelevantLocals {
343
+ #[ tracing:: instrument( level = "trace" , skip( candidates, num_locals) , ret) ]
344
+ fn compute ( candidates : & Candidates , num_locals : usize ) -> RelevantLocals {
345
+ let mut original = IndexVec :: with_capacity ( candidates. c . len ( ) ) ;
346
+ let mut shrink = IndexVec :: from_elem_n ( None , num_locals) ;
347
+
348
+ // Mark a local as relevant and record it into the maps.
349
+ let mut declare = |local| {
350
+ shrink. get_or_insert_with ( local, || original. push ( local) ) ;
351
+ } ;
352
+
353
+ for ( & src, destinations) in candidates. c . iter ( ) {
354
+ declare ( src) ;
355
+ for & dest in destinations {
356
+ declare ( dest)
357
+ }
358
+ }
359
+
360
+ RelevantLocals { original, shrink }
361
+ }
362
+ }
363
+
319
364
//////////////////////////////////////////////////////////
320
365
// Liveness filtering
321
366
//
@@ -324,7 +369,8 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
324
369
struct FilterInformation < ' a , ' tcx > {
325
370
body : & ' a Body < ' tcx > ,
326
371
points : & ' a DenseLocationMap ,
327
- conflicts : BitMatrix < Local , Local > ,
372
+ relevant : RelevantLocals ,
373
+ conflicts : BitMatrix < RelevantLocal , RelevantLocal > ,
328
374
write_info : & ' a mut WriteInfo ,
329
375
at : Location ,
330
376
}
@@ -371,12 +417,16 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
371
417
live : & SparseIntervalMatrix < Local , PointIndex > ,
372
418
write_info : & ' a mut WriteInfo ,
373
419
body : & ' a Body < ' tcx > ,
420
+ candidates : & Candidates ,
374
421
) -> Self {
375
422
let num_locals = body. local_decls . len ( ) ;
423
+ let relevant = RelevantLocals :: compute ( candidates, num_locals) ;
424
+ let num_relevant = relevant. original . len ( ) ;
376
425
let mut this = FilterInformation {
377
426
body,
427
+ relevant,
378
428
points,
379
- conflicts : BitMatrix :: new ( num_locals , num_locals ) ,
429
+ conflicts : BitMatrix :: new ( num_relevant , num_relevant ) ,
380
430
// We don't actually store anything at this scope, we just keep things here to be able
381
431
// to reuse the allocation.
382
432
write_info,
@@ -404,22 +454,28 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
404
454
}
405
455
406
456
fn record_conflicts ( & mut self , live : & SparseIntervalMatrix < Local , PointIndex > ) {
407
- let writes = & self . write_info . writes ;
408
- let skip_pair = self . write_info . skip_pair ;
457
+ let writes = self . write_info . writes . iter ( ) . filter_map ( |& p| self . relevant . shrink [ p] ) ;
458
+
459
+ let skip_pair = self . write_info . skip_pair . and_then ( |( p, q) | {
460
+ let p = self . relevant . shrink [ p] ?;
461
+ let q = self . relevant . shrink [ q] ?;
462
+ Some ( ( p, q) )
463
+ } ) ;
464
+
409
465
let at = self . points . point_from_location ( self . at ) ;
410
466
411
- for & p in writes {
412
- for & q in writes {
467
+ for p in writes. clone ( ) {
468
+ for q in writes. clone ( ) {
413
469
if p != q && skip_pair != Some ( ( p, q) ) && skip_pair != Some ( ( q, p) ) {
414
470
self . conflicts . insert ( p, q) ;
415
471
}
416
472
}
417
473
418
- for q in live . rows ( ) {
474
+ for ( q , & original_q ) in self . relevant . original . iter_enumerated ( ) {
419
475
if p != q
420
476
&& skip_pair != Some ( ( p, q) )
421
477
&& skip_pair != Some ( ( q, p) )
422
- && live. contains ( q , at)
478
+ && live. contains ( original_q , at)
423
479
{
424
480
self . conflicts . insert ( p, q) ;
425
481
}
@@ -430,14 +486,18 @@ impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
430
486
#[ tracing:: instrument( level = "trace" , skip( self ) ) ]
431
487
fn record_merge ( & mut self , src : Local , dest : Local ) {
432
488
trace ! ( ?self . conflicts, "pre" ) ;
489
+ let src = self . relevant . shrink [ src] . expect ( "merged locals are relevant" ) ;
490
+ let dest = self . relevant . shrink [ dest] . expect ( "merged locals are relevant" ) ;
433
491
self . conflicts . union_rows ( src, dest) ;
434
492
self . conflicts . union_cols ( src, dest) ;
435
493
trace ! ( ?self . conflicts, "post" ) ;
436
494
}
437
495
438
496
#[ tracing:: instrument( level = "trace" , skip( self ) , ret) ]
439
497
fn find_non_conflicting ( & self , src : Local , candidates : & Vec < Local > ) -> Option < Local > {
498
+ let src = self . relevant . shrink [ src] . expect ( "merged locals are relevant" ) ;
440
499
candidates. iter ( ) . copied ( ) . find ( |& dest| {
500
+ let dest = self . relevant . shrink [ dest] . expect ( "merged locals are relevant" ) ;
441
501
!self . conflicts . contains ( src, dest) && !self . conflicts . contains ( dest, src)
442
502
} )
443
503
}
0 commit comments