@@ -145,7 +145,7 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
145
145
use rustc_middle:: mir:: * ;
146
146
use rustc_middle:: ty:: TyCtxt ;
147
147
use rustc_mir_dataflow:: impls:: { DefUse , MaybeLiveLocals } ;
148
- use rustc_mir_dataflow:: points:: { DenseLocationMap , PointIndex } ;
148
+ use rustc_mir_dataflow:: points:: DenseLocationMap ;
149
149
use rustc_mir_dataflow:: { Analysis , Results } ;
150
150
use tracing:: { debug, trace} ;
151
151
@@ -494,20 +494,22 @@ fn dest_prop_mir_dump<'tcx>(
494
494
live : & SparseIntervalMatrix < RelevantLocal , TwoStepIndex > ,
495
495
relevant : & RelevantLocals ,
496
496
) {
497
- let locals_live_at = |location, effect| {
498
- let location = points. point_from_location ( location) ;
499
- let location = TwoStepIndex :: new ( location, effect) ;
497
+ let locals_live_at = |location| {
500
498
live. rows ( )
501
499
. filter ( |& r| live. contains ( r, location) )
502
500
. map ( |rl| relevant. original [ rl] )
503
501
. collect :: < Vec < _ > > ( )
504
502
} ;
505
503
dump_mir ( tcx, false , "DestinationPropagation-dataflow" , & 0 , body, |pass_where, w| {
506
504
if let PassWhere :: BeforeLocation ( loc) = pass_where {
507
- writeln ! ( w, " // before: {:?}" , locals_live_at( loc, Effect :: Before ) ) ?;
505
+ let location = TwoStepIndex :: new ( points, loc, Effect :: Before ) ;
506
+ let live = locals_live_at ( location) ;
507
+ writeln ! ( w, " // before: {:?} => {:?}" , location, live) ?;
508
508
}
509
509
if let PassWhere :: AfterLocation ( loc) = pass_where {
510
- writeln ! ( w, " // after: {:?}" , locals_live_at( loc, Effect :: After ) ) ?;
510
+ let location = TwoStepIndex :: new ( points, loc, Effect :: After ) ;
511
+ let live = locals_live_at ( location) ;
512
+ writeln ! ( w, " // after: {:?} => {:?}" , location, live) ?;
511
513
}
512
514
513
515
Ok ( ( ) )
@@ -521,19 +523,25 @@ enum Effect {
521
523
}
522
524
523
525
rustc_index:: newtype_index! {
524
- /// A `PointIndex` but with the lower bit encoding early/late inside the statement.
526
+ /// A reversed `PointIndex` but with the lower bit encoding early/late inside the statement.
527
+ /// The reversed order allows to use the more efficient `IntervalSet::append` method while we
528
+ /// iterate on the statements in reverse order.
525
529
#[ orderable]
526
530
#[ debug_format = "TwoStepIndex({})" ]
527
531
struct TwoStepIndex { }
528
532
}
529
533
530
534
impl TwoStepIndex {
531
- fn new ( point : PointIndex , effect : Effect ) -> TwoStepIndex {
535
+ fn new ( elements : & DenseLocationMap , location : Location , effect : Effect ) -> TwoStepIndex {
536
+ let point = elements. point_from_location ( location) ;
532
537
let effect = match effect {
533
538
Effect :: Before => 0 ,
534
539
Effect :: After => 1 ,
535
540
} ;
536
- TwoStepIndex :: from_u32 ( 2 * point. as_u32 ( ) + ( effect as u32 ) )
541
+ let max_index = 2 * elements. num_points ( ) as u32 - 1 ;
542
+ let index = 2 * point. as_u32 ( ) + ( effect as u32 ) ;
543
+ // Reverse the indexing to use more efficient `IntervalSet::append`.
544
+ TwoStepIndex :: from_u32 ( max_index - index)
537
545
}
538
546
}
539
547
@@ -564,21 +572,18 @@ fn save_as_intervals<'tcx>(
564
572
let mut state = MaybeLiveLocals . bottom_value ( body) ;
565
573
let reachable_blocks = traversal:: reachable_as_bitset ( body) ;
566
574
567
- let two_step_loc = |location, effect| {
568
- let point = elements. point_from_location ( location) ;
569
- TwoStepIndex :: new ( point, effect)
570
- } ;
571
- let prepend_at =
575
+ let two_step_loc = |location, effect| TwoStepIndex :: new ( elements, location, effect) ;
576
+ let append_at =
572
577
|values : & mut SparseIntervalMatrix < _ , _ > , state : & DenseBitSet < Local > , twostep| {
573
578
for ( relevant, & original) in relevant. original . iter_enumerated ( ) {
574
579
if state. contains ( original) {
575
- values. prepend ( relevant, twostep) ;
580
+ values. append ( relevant, twostep) ;
576
581
}
577
582
}
578
583
} ;
579
584
580
585
// Iterate blocks in decreasing order, to visit locations in decreasing order. This
581
- // allows to use the more efficient `prepend ` method to interval sets.
586
+ // allows to use the more efficient `append ` method to interval sets.
582
587
for block in body. basic_blocks . indices ( ) . rev ( ) {
583
588
if !reachable_blocks. contains ( block) {
584
589
continue ;
@@ -591,7 +596,7 @@ fn save_as_intervals<'tcx>(
591
596
592
597
let term = block_data. terminator ( ) ;
593
598
let mut twostep = two_step_loc ( loc, Effect :: After ) ;
594
- prepend_at ( & mut values, & state, twostep) ;
599
+ append_at ( & mut values, & state, twostep) ;
595
600
// Ensure we have a non-zero live range even for dead stores. This is done by marking all
596
601
// the written-to locals as live in the second half of the statement.
597
602
// We also ensure that operands read by terminators conflict with writes by that terminator.
@@ -606,17 +611,17 @@ fn save_as_intervals<'tcx>(
606
611
} )
607
612
. visit_terminator ( term, loc) ;
608
613
609
- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
614
+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
610
615
debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
611
616
MaybeLiveLocals . apply_early_terminator_effect ( & mut state, term, loc) ;
612
617
MaybeLiveLocals . apply_primary_terminator_effect ( & mut state, term, loc) ;
613
- prepend_at ( & mut values, & state, twostep) ;
618
+ append_at ( & mut values, & state, twostep) ;
614
619
615
620
for ( statement_index, stmt) in block_data. statements . iter ( ) . enumerate ( ) . rev ( ) {
616
621
let loc = Location { block, statement_index } ;
617
- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
622
+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
618
623
debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: After ) ) ;
619
- prepend_at ( & mut values, & state, twostep) ;
624
+ append_at ( & mut values, & state, twostep) ;
620
625
// Ensure we have a non-zero live range even for dead stores. This is done by marking
621
626
// all the written-to locals as live in the second half of the statement.
622
627
VisitPlacesWith ( |place, ctxt| match DefUse :: for_place ( place, ctxt) {
@@ -629,13 +634,13 @@ fn save_as_intervals<'tcx>(
629
634
} )
630
635
. visit_statement ( stmt, loc) ;
631
636
632
- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
637
+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
633
638
debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
634
639
MaybeLiveLocals . apply_early_statement_effect ( & mut state, stmt, loc) ;
635
640
MaybeLiveLocals . apply_primary_statement_effect ( & mut state, stmt, loc) ;
636
641
// ... but reads from operands are marked as live here so they do not conflict with
637
642
// the all the writes we manually marked as live in the second half of the statement.
638
- prepend_at ( & mut values, & state, twostep) ;
643
+ append_at ( & mut values, & state, twostep) ;
639
644
}
640
645
}
641
646
0 commit comments