@@ -37,6 +37,7 @@ use rustc::mir::*;
3737use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
3838use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
3939use rustc_data_structures:: indexed_set:: IdxSetBuf ;
40+ use rustc_data_structures:: work_queue:: WorkQueue ;
4041use util:: pretty:: { dump_enabled, write_basic_block, write_mir_intro} ;
4142use rustc:: ty:: item_path;
4243use rustc:: mir:: visit:: MirVisitable ;
@@ -55,9 +56,6 @@ pub struct LivenessResult {
5556 /// Liveness mode in use when these results were computed.
5657 pub mode : LivenessMode ,
5758
58- /// Live variables on entry to each basic block.
59- pub ins : IndexVec < BasicBlock , LocalSet > ,
60-
6159 /// Live variables on exit to each basic block. This is equal to
6260 /// the union of the `ins` for each successor.
6361 pub outs : IndexVec < BasicBlock , LocalSet > ,
@@ -124,37 +122,38 @@ pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liveness
124122 . map ( |b| block ( mode, b, locals) )
125123 . collect ( ) ;
126124
127- let mut ins : IndexVec < _ , _ > = mir. basic_blocks ( )
125+ let mut outs : IndexVec < _ , _ > = mir. basic_blocks ( )
128126 . indices ( )
129127 . map ( |_| LocalSet :: new_empty ( locals) )
130128 . collect ( ) ;
131- let mut outs = ins. clone ( ) ;
132129
133- let mut changed = true ;
134130 let mut bits = LocalSet :: new_empty ( locals) ;
135- while changed {
136- changed = false ;
137-
138- for b in mir. basic_blocks ( ) . indices ( ) . rev ( ) {
139- // outs[b] = ∪ {ins of successors}
140- bits. clear ( ) ;
141- for & successor in mir. basic_blocks ( ) [ b] . terminator ( ) . successors ( ) {
142- bits. union ( & ins[ successor] ) ;
143- }
144- outs[ b] . overwrite ( & bits) ;
145131
146- // bits = use ∪ (bits - def)
147- def_use[ b] . apply ( & mut bits) ;
132+ // queue of things that need to be re-processed, and a set containing
133+ // the things currently in the queue
134+ let mut dirty_queue: WorkQueue < BasicBlock > = WorkQueue :: with_all ( mir. basic_blocks ( ) . len ( ) ) ;
135+
136+ let predecessors = mir. predecessors ( ) ;
148137
149- // update bits on entry and flag if they have changed
150- if ins[ b] != bits {
151- ins[ b] . overwrite ( & bits) ;
152- changed = true ;
138+ while let Some ( bb) = dirty_queue. pop ( ) {
139+ // bits = use ∪ (bits - def)
140+ bits. overwrite ( & outs[ bb] ) ;
141+ def_use[ bb] . apply ( & mut bits) ;
142+
143+ // `bits` now contains the live variables on entry. Therefore,
144+ // add `bits` to the `out` set for each predecessor; if those
145+ // bits were not already present, then enqueue the predecessor
146+ // as dirty.
147+ //
148+ // (note that `union` returns true if the `self` set changed)
149+ for & pred_bb in & predecessors[ bb] {
150+ if outs[ pred_bb] . union ( & bits) {
151+ dirty_queue. insert ( pred_bb) ;
153152 }
154153 }
155154 }
156155
157- LivenessResult { mode, ins , outs }
156+ LivenessResult { mode, outs }
158157}
159158
160159impl LivenessResult {
@@ -195,8 +194,6 @@ impl LivenessResult {
195194 statement_defs_uses. apply ( & mut bits) ;
196195 callback ( statement_location, & bits) ;
197196 }
198-
199- assert_eq ! ( bits, self . ins[ block] ) ;
200197 }
201198
202199 fn defs_uses < ' tcx , V > ( & self , mir : & Mir < ' tcx > , location : Location , thing : & V ) -> DefsUses
@@ -438,7 +435,6 @@ pub fn write_mir_fn<'a, 'tcx>(
438435 . collect ( ) ;
439436 writeln ! ( w, "{} {{{}}}" , prefix, live. join( ", " ) )
440437 } ;
441- print ( w, " " , & result. ins ) ?;
442438 write_basic_block ( tcx, block, mir, & mut |_, _| Ok ( ( ) ) , w) ?;
443439 print ( w, " " , & result. outs ) ?;
444440 if block. index ( ) + 1 != mir. basic_blocks ( ) . len ( ) {
0 commit comments