@@ -145,7 +145,7 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
145145use rustc_middle:: mir:: * ;
146146use rustc_middle:: ty:: TyCtxt ;
147147use rustc_mir_dataflow:: impls:: { DefUse , MaybeLiveLocals } ;
148- use rustc_mir_dataflow:: points:: { DenseLocationMap , PointIndex } ;
148+ use rustc_mir_dataflow:: points:: DenseLocationMap ;
149149use rustc_mir_dataflow:: { Analysis , Results } ;
150150use tracing:: { debug, trace} ;
151151
@@ -502,9 +502,7 @@ fn dest_prop_mir_dump<'tcx>(
502502 live : & SparseIntervalMatrix < RelevantLocal , TwoStepIndex > ,
503503 relevant : & RelevantLocals ,
504504) {
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| {
508506 live. rows ( )
509507 . filter ( |& r| live. contains ( r, location) )
510508 . map ( |rl| relevant. original [ rl] )
@@ -514,10 +512,14 @@ fn dest_prop_mir_dump<'tcx>(
514512 if let Some ( dumper) = MirDumper :: new ( tcx, "DestinationPropagation-dataflow" , body) {
515513 let extra_data = & |pass_where, w : & mut dyn std:: io:: Write | {
516514 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) ?;
518518 }
519519 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) ?;
521523 }
522524 Ok ( ( ) )
523525 } ;
@@ -533,19 +535,25 @@ enum Effect {
533535}
534536
535537rustc_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.
537541 #[ orderable]
538542 #[ debug_format = "TwoStepIndex({})" ]
539543 struct TwoStepIndex { }
540544}
541545
542546impl 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) ;
544549 let effect = match effect {
545550 Effect :: Before => 0 ,
546551 Effect :: After => 1 ,
547552 } ;
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)
549557 }
550558}
551559
@@ -576,21 +584,18 @@ fn save_as_intervals<'tcx>(
576584 let mut state = MaybeLiveLocals . bottom_value ( body) ;
577585 let reachable_blocks = traversal:: reachable_as_bitset ( body) ;
578586
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 =
584589 |values : & mut SparseIntervalMatrix < _ , _ > , state : & DenseBitSet < Local > , twostep| {
585590 for ( relevant, & original) in relevant. original . iter_enumerated ( ) {
586591 if state. contains ( original) {
587- values. prepend ( relevant, twostep) ;
592+ values. append ( relevant, twostep) ;
588593 }
589594 }
590595 } ;
591596
592597 // 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.
594599 for block in body. basic_blocks . indices ( ) . rev ( ) {
595600 if !reachable_blocks. contains ( block) {
596601 continue ;
@@ -603,7 +608,7 @@ fn save_as_intervals<'tcx>(
603608
604609 let term = block_data. terminator ( ) ;
605610 let mut twostep = two_step_loc ( loc, Effect :: After ) ;
606- prepend_at ( & mut values, & state, twostep) ;
611+ append_at ( & mut values, & state, twostep) ;
607612 // Ensure we have a non-zero live range even for dead stores. This is done by marking all
608613 // the written-to locals as live in the second half of the statement.
609614 // We also ensure that operands read by terminators conflict with writes by that terminator.
@@ -618,17 +623,17 @@ fn save_as_intervals<'tcx>(
618623 } )
619624 . visit_terminator ( term, loc) ;
620625
621- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
626+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
622627 debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
623628 MaybeLiveLocals . apply_early_terminator_effect ( & mut state, term, loc) ;
624629 MaybeLiveLocals . apply_primary_terminator_effect ( & mut state, term, loc) ;
625- prepend_at ( & mut values, & state, twostep) ;
630+ append_at ( & mut values, & state, twostep) ;
626631
627632 for ( statement_index, stmt) in block_data. statements . iter ( ) . enumerate ( ) . rev ( ) {
628633 let loc = Location { block, statement_index } ;
629- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
634+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
630635 debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: After ) ) ;
631- prepend_at ( & mut values, & state, twostep) ;
636+ append_at ( & mut values, & state, twostep) ;
632637 // Ensure we have a non-zero live range even for dead stores. This is done by marking
633638 // all the written-to locals as live in the second half of the statement.
634639 VisitPlacesWith ( |place, ctxt| match DefUse :: for_place ( place, ctxt) {
@@ -641,13 +646,13 @@ fn save_as_intervals<'tcx>(
641646 } )
642647 . visit_statement ( stmt, loc) ;
643648
644- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
649+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
645650 debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
646651 MaybeLiveLocals . apply_early_statement_effect ( & mut state, stmt, loc) ;
647652 MaybeLiveLocals . apply_primary_statement_effect ( & mut state, stmt, loc) ;
648653 // ... but reads from operands are marked as live here so they do not conflict with
649654 // 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) ;
651656 }
652657 }
653658
0 commit comments