@@ -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
@@ -494,20 +494,22 @@ fn dest_prop_mir_dump<'tcx>(
494494 live : & SparseIntervalMatrix < RelevantLocal , TwoStepIndex > ,
495495 relevant : & RelevantLocals ,
496496) {
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| {
500498 live. rows ( )
501499 . filter ( |& r| live. contains ( r, location) )
502500 . map ( |rl| relevant. original [ rl] )
503501 . collect :: < Vec < _ > > ( )
504502 } ;
505503 dump_mir ( tcx, false , "DestinationPropagation-dataflow" , & 0 , body, |pass_where, w| {
506504 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) ?;
508508 }
509509 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) ?;
511513 }
512514
513515 Ok ( ( ) )
@@ -521,19 +523,25 @@ enum Effect {
521523}
522524
523525rustc_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.
525529 #[ orderable]
526530 #[ debug_format = "TwoStepIndex({})" ]
527531 struct TwoStepIndex { }
528532}
529533
530534impl 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) ;
532537 let effect = match effect {
533538 Effect :: Before => 0 ,
534539 Effect :: After => 1 ,
535540 } ;
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)
537545 }
538546}
539547
@@ -564,21 +572,18 @@ fn save_as_intervals<'tcx>(
564572 let mut state = MaybeLiveLocals . bottom_value ( body) ;
565573 let reachable_blocks = traversal:: reachable_as_bitset ( body) ;
566574
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 =
572577 |values : & mut SparseIntervalMatrix < _ , _ > , state : & DenseBitSet < Local > , twostep| {
573578 for ( relevant, & original) in relevant. original . iter_enumerated ( ) {
574579 if state. contains ( original) {
575- values. prepend ( relevant, twostep) ;
580+ values. append ( relevant, twostep) ;
576581 }
577582 }
578583 } ;
579584
580585 // 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.
582587 for block in body. basic_blocks . indices ( ) . rev ( ) {
583588 if !reachable_blocks. contains ( block) {
584589 continue ;
@@ -591,7 +596,7 @@ fn save_as_intervals<'tcx>(
591596
592597 let term = block_data. terminator ( ) ;
593598 let mut twostep = two_step_loc ( loc, Effect :: After ) ;
594- prepend_at ( & mut values, & state, twostep) ;
599+ append_at ( & mut values, & state, twostep) ;
595600 // Ensure we have a non-zero live range even for dead stores. This is done by marking all
596601 // the written-to locals as live in the second half of the statement.
597602 // We also ensure that operands read by terminators conflict with writes by that terminator.
@@ -606,17 +611,17 @@ fn save_as_intervals<'tcx>(
606611 } )
607612 . visit_terminator ( term, loc) ;
608613
609- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
614+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
610615 debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
611616 MaybeLiveLocals . apply_early_terminator_effect ( & mut state, term, loc) ;
612617 MaybeLiveLocals . apply_primary_terminator_effect ( & mut state, term, loc) ;
613- prepend_at ( & mut values, & state, twostep) ;
618+ append_at ( & mut values, & state, twostep) ;
614619
615620 for ( statement_index, stmt) in block_data. statements . iter ( ) . enumerate ( ) . rev ( ) {
616621 let loc = Location { block, statement_index } ;
617- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
622+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
618623 debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: After ) ) ;
619- prepend_at ( & mut values, & state, twostep) ;
624+ append_at ( & mut values, & state, twostep) ;
620625 // Ensure we have a non-zero live range even for dead stores. This is done by marking
621626 // all the written-to locals as live in the second half of the statement.
622627 VisitPlacesWith ( |place, ctxt| match DefUse :: for_place ( place, ctxt) {
@@ -629,13 +634,13 @@ fn save_as_intervals<'tcx>(
629634 } )
630635 . visit_statement ( stmt, loc) ;
631636
632- twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) - 1 ) ;
637+ twostep = TwoStepIndex :: from_u32 ( twostep. as_u32 ( ) + 1 ) ;
633638 debug_assert_eq ! ( twostep, two_step_loc( loc, Effect :: Before ) ) ;
634639 MaybeLiveLocals . apply_early_statement_effect ( & mut state, stmt, loc) ;
635640 MaybeLiveLocals . apply_primary_statement_effect ( & mut state, stmt, loc) ;
636641 // ... but reads from operands are marked as live here so they do not conflict with
637642 // 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) ;
639644 }
640645 }
641646
0 commit comments