@@ -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
@@ -502,9 +502,7 @@ fn dest_prop_mir_dump<'tcx>(
502
502
live : & SparseIntervalMatrix < RelevantLocal , TwoStepIndex > ,
503
503
relevant : & RelevantLocals ,
504
504
) {
505
- let locals_live_at = |location, effect| {
506
- let location = points. point_from_location ( location) ;
507
- let location = TwoStepIndex :: new ( location, effect) ;
505
+ let locals_live_at = |location| {
508
506
live. rows ( )
509
507
. filter ( |& r| live. contains ( r, location) )
510
508
. map ( |rl| relevant. original [ rl] )
@@ -514,10 +512,14 @@ fn dest_prop_mir_dump<'tcx>(
514
512
if let Some ( dumper) = MirDumper :: new ( tcx, "DestinationPropagation-dataflow" , body) {
515
513
let extra_data = & |pass_where, w : & mut dyn std:: io:: Write | {
516
514
if let PassWhere :: BeforeLocation ( loc) = pass_where {
517
- writeln ! ( w, " // before: {:?}" , locals_live_at( loc, Effect :: Before ) ) ?;
515
+ let location = TwoStepIndex :: new ( points, loc, Effect :: Before ) ;
516
+ let live = locals_live_at ( location) ;
517
+ writeln ! ( w, " // before: {:?} => {:?}" , location, live) ?;
518
518
}
519
519
if let PassWhere :: AfterLocation ( loc) = pass_where {
520
- writeln ! ( w, " // after: {:?}" , locals_live_at( loc, Effect :: After ) ) ?;
520
+ let location = TwoStepIndex :: new ( points, loc, Effect :: After ) ;
521
+ let live = locals_live_at ( location) ;
522
+ writeln ! ( w, " // after: {:?} => {:?}" , location, live) ?;
521
523
}
522
524
Ok ( ( ) )
523
525
} ;
@@ -533,19 +535,25 @@ enum Effect {
533
535
}
534
536
535
537
rustc_index:: newtype_index! {
536
- /// A `PointIndex` but with the lower bit encoding early/late inside the statement.
538
+ /// A reversed `PointIndex` but with the lower bit encoding early/late inside the statement.
539
+ /// The reversed order allows to use the more efficient `IntervalSet::append` method while we
540
+ /// iterate on the statements in reverse order.
537
541
#[ orderable]
538
542
#[ debug_format = "TwoStepIndex({})" ]
539
543
struct TwoStepIndex { }
540
544
}
541
545
542
546
impl TwoStepIndex {
543
- fn new ( point : PointIndex , effect : Effect ) -> TwoStepIndex {
547
+ fn new ( elements : & DenseLocationMap , location : Location , effect : Effect ) -> TwoStepIndex {
548
+ let point = elements. point_from_location ( location) ;
544
549
let effect = match effect {
545
550
Effect :: Before => 0 ,
546
551
Effect :: After => 1 ,
547
552
} ;
548
- TwoStepIndex :: from_u32 ( 2 * point. as_u32 ( ) + ( effect as u32 ) )
553
+ let max_index = 2 * elements. num_points ( ) as u32 - 1 ;
554
+ let index = 2 * point. as_u32 ( ) + ( effect as u32 ) ;
555
+ // Reverse the indexing to use more efficient `IntervalSet::append`.
556
+ TwoStepIndex :: from_u32 ( max_index - index)
549
557
}
550
558
}
551
559
@@ -576,21 +584,18 @@ fn save_as_intervals<'tcx>(
576
584
let mut state = MaybeLiveLocals . bottom_value ( body) ;
577
585
let reachable_blocks = traversal:: reachable_as_bitset ( body) ;
578
586
579
- let two_step_loc = |location, effect| {
580
- let point = elements. point_from_location ( location) ;
581
- TwoStepIndex :: new ( point, effect)
582
- } ;
583
- let prepend_at =
587
+ let two_step_loc = |location, effect| TwoStepIndex :: new ( elements, location, effect) ;
588
+ let append_at =
584
589
|values : & mut SparseIntervalMatrix < _ , _ > , state : & DenseBitSet < Local > , twostep| {
585
590
for ( relevant, & original) in relevant. original . iter_enumerated ( ) {
586
591
if state. contains ( original) {
587
- values. prepend ( relevant, twostep) ;
592
+ values. append ( relevant, twostep) ;
588
593
}
589
594
}
590
595
} ;
591
596
592
597
// Iterate blocks in decreasing order, to visit locations in decreasing order. This
593
- // allows to use the more efficient `prepend ` method to interval sets.
598
+ // allows to use the more efficient `append ` method to interval sets.
594
599
for block in body. basic_blocks . indices ( ) . rev ( ) {
595
600
if !reachable_blocks. contains ( block) {
596
601
continue ;
@@ -603,7 +608,7 @@ fn save_as_intervals<'tcx>(
603
608
604
609
let term = block_data. terminator ( ) ;
605
610
let mut twostep = two_step_loc ( loc, Effect :: After ) ;
606
- prepend_at ( & mut values, & state, twostep) ;
611
+ append_at ( & mut values, & state, twostep) ;
607
612
// Ensure we have a non-zero live range even for dead stores. This is done by marking all
608
613
// the written-to locals as live in the second half of the statement.
609
614
// We also ensure that operands read by terminators conflict with writes by that terminator.
@@ -618,17 +623,17 @@ fn save_as_intervals<'tcx>(
618
623
} )
619
624
. visit_terminator ( term, loc) ;
620
625
621
- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
626
+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
622
627
debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
623
628
MaybeLiveLocals . apply_early_terminator_effect ( & mut state, term, loc) ;
624
629
MaybeLiveLocals . apply_primary_terminator_effect ( & mut state, term, loc) ;
625
- prepend_at ( & mut values, & state, twostep) ;
630
+ append_at ( & mut values, & state, twostep) ;
626
631
627
632
for ( statement_index, stmt) in block_data. statements . iter ( ) . enumerate ( ) . rev ( ) {
628
633
let loc = Location { block, statement_index } ;
629
- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
634
+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
630
635
debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: After ) ) ;
631
- prepend_at ( & mut values, & state, twostep) ;
636
+ append_at ( & mut values, & state, twostep) ;
632
637
// Ensure we have a non-zero live range even for dead stores. This is done by marking
633
638
// all the written-to locals as live in the second half of the statement.
634
639
VisitPlacesWith ( |place, ctxt| match DefUse :: for_place ( place, ctxt) {
@@ -641,13 +646,13 @@ fn save_as_intervals<'tcx>(
641
646
} )
642
647
. visit_statement ( stmt, loc) ;
643
648
644
- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
649
+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
645
650
debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
646
651
MaybeLiveLocals . apply_early_statement_effect ( & mut state, stmt, loc) ;
647
652
MaybeLiveLocals . apply_primary_statement_effect ( & mut state, stmt, loc) ;
648
653
// ... but reads from operands are marked as live here so they do not conflict with
649
654
// the all the writes we manually marked as live in the second half of the statement.
650
- prepend_at ( & mut values, & state, twostep) ;
655
+ append_at ( & mut values, & state, twostep) ;
651
656
}
652
657
}
653
658
0 commit comments