@@ -13,6 +13,7 @@ use syntax::ast::{self, MetaItem};
13
13
use rustc_data_structures:: indexed_set:: { IdxSet , IdxSetBuf } ;
14
14
use rustc_data_structures:: indexed_vec:: Idx ;
15
15
use rustc_data_structures:: bitslice:: { bitwise, BitwiseOperator } ;
16
+ use rustc_data_structures:: work_queue:: WorkQueue ;
16
17
17
18
use rustc:: ty:: { self , TyCtxt } ;
18
19
use rustc:: mir:: { self , Mir , BasicBlock , BasicBlockData , Location , Statement , Terminator } ;
@@ -176,7 +177,6 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD
176
177
struct PropagationContext < ' b , ' a : ' b , ' tcx : ' a , O > where O : ' b + BitDenotation
177
178
{
178
179
builder : & ' b mut DataflowAnalysis < ' a , ' tcx , O > ,
179
- changed : bool ,
180
180
}
181
181
182
182
impl < ' a , ' tcx : ' a , BD > DataflowAnalysis < ' a , ' tcx , BD > where BD : BitDenotation
@@ -185,12 +185,9 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
185
185
let mut temp = IdxSetBuf :: new_empty ( self . flow_state . sets . bits_per_block ) ;
186
186
let mut propcx = PropagationContext {
187
187
builder : self ,
188
- changed : true ,
189
188
} ;
190
- while propcx. changed {
191
- propcx. changed = false ;
192
- propcx. walk_cfg ( & mut temp) ;
193
- }
189
+ propcx. walk_cfg ( & mut temp) ;
190
+
194
191
}
195
192
196
193
fn build_sets ( & mut self ) {
@@ -236,18 +233,20 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
236
233
impl < ' b , ' a : ' b , ' tcx : ' a , BD > PropagationContext < ' b , ' a , ' tcx , BD > where BD : BitDenotation
237
234
{
238
235
fn walk_cfg ( & mut self , in_out : & mut IdxSet < BD :: Idx > ) {
236
+ let mut dirty_queue: WorkQueue < mir:: BasicBlock > =
237
+ WorkQueue :: with_all ( self . builder . mir . basic_blocks ( ) . len ( ) ) ;
239
238
let mir = self . builder . mir ;
240
- for ( bb_idx , bb_data ) in mir . basic_blocks ( ) . iter ( ) . enumerate ( ) {
241
- let builder = & mut self . builder ;
239
+ while let Some ( bb ) = dirty_queue . pop ( ) {
240
+ let bb_data = & mir [ bb ] ;
242
241
{
243
- let sets = builder. flow_state . sets . for_block ( bb_idx ) ;
242
+ let sets = self . builder . flow_state . sets . for_block ( bb . index ( ) ) ;
244
243
debug_assert ! ( in_out. words( ) . len( ) == sets. on_entry. words( ) . len( ) ) ;
245
244
in_out. overwrite ( sets. on_entry ) ;
246
245
in_out. union ( sets. gen_set ) ;
247
246
in_out. subtract ( sets. kill_set ) ;
248
247
}
249
- builder. propagate_bits_into_graph_successors_of (
250
- in_out, & mut self . changed , ( mir :: BasicBlock :: new ( bb_idx ) , bb_data) ) ;
248
+ self . builder . propagate_bits_into_graph_successors_of (
249
+ in_out, ( bb , bb_data) , & mut dirty_queue ) ;
251
250
}
252
251
}
253
252
}
@@ -806,68 +805,68 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
806
805
fn propagate_bits_into_graph_successors_of (
807
806
& mut self ,
808
807
in_out : & mut IdxSet < D :: Idx > ,
809
- changed : & mut bool ,
810
- ( bb , bb_data ) : ( mir :: BasicBlock , & mir:: BasicBlockData ) )
808
+ ( bb , bb_data ) : ( mir :: BasicBlock , & mir :: BasicBlockData ) ,
809
+ dirty_list : & mut WorkQueue < mir:: BasicBlock > )
811
810
{
812
811
match bb_data. terminator ( ) . kind {
813
812
mir:: TerminatorKind :: Return |
814
813
mir:: TerminatorKind :: Resume |
815
814
mir:: TerminatorKind :: Abort |
816
815
mir:: TerminatorKind :: GeneratorDrop |
817
816
mir:: TerminatorKind :: Unreachable => { }
818
- mir:: TerminatorKind :: Goto { ref target } |
819
- mir:: TerminatorKind :: Assert { ref target, cleanup : None , .. } |
820
- mir:: TerminatorKind :: Yield { resume : ref target, drop : None , .. } |
821
- mir:: TerminatorKind :: Drop { ref target, location : _, unwind : None } |
817
+ mir:: TerminatorKind :: Goto { target } |
818
+ mir:: TerminatorKind :: Assert { target, cleanup : None , .. } |
819
+ mir:: TerminatorKind :: Yield { resume : target, drop : None , .. } |
820
+ mir:: TerminatorKind :: Drop { target, location : _, unwind : None } |
822
821
mir:: TerminatorKind :: DropAndReplace {
823
- ref target, value : _, location : _, unwind : None
822
+ target, value : _, location : _, unwind : None
824
823
} => {
825
- self . propagate_bits_into_entry_set_for ( in_out, changed , target ) ;
824
+ self . propagate_bits_into_entry_set_for ( in_out, target , dirty_list ) ;
826
825
}
827
- mir:: TerminatorKind :: Yield { resume : ref target, drop : Some ( ref drop) , .. } => {
828
- self . propagate_bits_into_entry_set_for ( in_out, changed , target ) ;
829
- self . propagate_bits_into_entry_set_for ( in_out, changed , drop ) ;
826
+ mir:: TerminatorKind :: Yield { resume : target, drop : Some ( drop) , .. } => {
827
+ self . propagate_bits_into_entry_set_for ( in_out, target , dirty_list ) ;
828
+ self . propagate_bits_into_entry_set_for ( in_out, drop , dirty_list ) ;
830
829
}
831
- mir:: TerminatorKind :: Assert { ref target, cleanup : Some ( ref unwind) , .. } |
832
- mir:: TerminatorKind :: Drop { ref target, location : _, unwind : Some ( ref unwind) } |
830
+ mir:: TerminatorKind :: Assert { target, cleanup : Some ( unwind) , .. } |
831
+ mir:: TerminatorKind :: Drop { target, location : _, unwind : Some ( unwind) } |
833
832
mir:: TerminatorKind :: DropAndReplace {
834
- ref target, value : _, location : _, unwind : Some ( ref unwind)
833
+ target, value : _, location : _, unwind : Some ( unwind)
835
834
} => {
836
- self . propagate_bits_into_entry_set_for ( in_out, changed , target ) ;
835
+ self . propagate_bits_into_entry_set_for ( in_out, target , dirty_list ) ;
837
836
if !self . dead_unwinds . contains ( & bb) {
838
- self . propagate_bits_into_entry_set_for ( in_out, changed , unwind ) ;
837
+ self . propagate_bits_into_entry_set_for ( in_out, unwind , dirty_list ) ;
839
838
}
840
839
}
841
840
mir:: TerminatorKind :: SwitchInt { ref targets, .. } => {
842
841
for target in targets {
843
- self . propagate_bits_into_entry_set_for ( in_out, changed , target ) ;
842
+ self . propagate_bits_into_entry_set_for ( in_out, * target , dirty_list ) ;
844
843
}
845
844
}
846
- mir:: TerminatorKind :: Call { ref cleanup, ref destination, func : _, args : _ } => {
847
- if let Some ( ref unwind) = * cleanup {
845
+ mir:: TerminatorKind :: Call { cleanup, ref destination, func : _, args : _ } => {
846
+ if let Some ( unwind) = cleanup {
848
847
if !self . dead_unwinds . contains ( & bb) {
849
- self . propagate_bits_into_entry_set_for ( in_out, changed , unwind ) ;
848
+ self . propagate_bits_into_entry_set_for ( in_out, unwind , dirty_list ) ;
850
849
}
851
850
}
852
- if let Some ( ( ref dest_place, ref dest_bb) ) = * destination {
851
+ if let Some ( ( ref dest_place, dest_bb) ) = * destination {
853
852
// N.B.: This must be done *last*, after all other
854
853
// propagation, as documented in comment above.
855
854
self . flow_state . operator . propagate_call_return (
856
- in_out, bb, * dest_bb, dest_place) ;
857
- self . propagate_bits_into_entry_set_for ( in_out, changed , dest_bb ) ;
855
+ in_out, bb, dest_bb, dest_place) ;
856
+ self . propagate_bits_into_entry_set_for ( in_out, dest_bb , dirty_list ) ;
858
857
}
859
858
}
860
- mir:: TerminatorKind :: FalseEdges { ref real_target, ref imaginary_targets } => {
861
- self . propagate_bits_into_entry_set_for ( in_out, changed , real_target ) ;
859
+ mir:: TerminatorKind :: FalseEdges { real_target, ref imaginary_targets } => {
860
+ self . propagate_bits_into_entry_set_for ( in_out, real_target , dirty_list ) ;
862
861
for target in imaginary_targets {
863
- self . propagate_bits_into_entry_set_for ( in_out, changed , target ) ;
862
+ self . propagate_bits_into_entry_set_for ( in_out, * target , dirty_list ) ;
864
863
}
865
864
}
866
- mir:: TerminatorKind :: FalseUnwind { ref real_target, unwind } => {
867
- self . propagate_bits_into_entry_set_for ( in_out, changed , real_target ) ;
868
- if let Some ( ref unwind) = unwind {
865
+ mir:: TerminatorKind :: FalseUnwind { real_target, unwind } => {
866
+ self . propagate_bits_into_entry_set_for ( in_out, real_target , dirty_list ) ;
867
+ if let Some ( unwind) = unwind {
869
868
if !self . dead_unwinds . contains ( & bb) {
870
- self . propagate_bits_into_entry_set_for ( in_out, changed , unwind ) ;
869
+ self . propagate_bits_into_entry_set_for ( in_out, unwind , dirty_list ) ;
871
870
}
872
871
}
873
872
}
@@ -876,14 +875,15 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
876
875
877
876
fn propagate_bits_into_entry_set_for ( & mut self ,
878
877
in_out : & IdxSet < D :: Idx > ,
879
- changed : & mut bool ,
880
- bb : & mir:: BasicBlock ) {
878
+ bb : mir :: BasicBlock ,
879
+ dirty_queue : & mut WorkQueue < mir:: BasicBlock > ) {
881
880
let entry_set = self . flow_state . sets . for_block ( bb. index ( ) ) . on_entry ;
882
881
let set_changed = bitwise ( entry_set. words_mut ( ) ,
883
882
in_out. words ( ) ,
884
883
& self . flow_state . operator ) ;
885
884
if set_changed {
886
- * changed = true ;
885
+ dirty_queue . insert ( bb ) ;
887
886
}
888
887
}
888
+
889
889
}
0 commit comments