@@ -37,6 +37,7 @@ use rustc::mir::*;
37
37
use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
38
38
use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
39
39
use rustc_data_structures:: indexed_set:: IdxSetBuf ;
40
+ use rustc_data_structures:: work_queue:: WorkQueue ;
40
41
use util:: pretty:: { dump_enabled, write_basic_block, write_mir_intro} ;
41
42
use rustc:: ty:: item_path;
42
43
use rustc:: mir:: visit:: MirVisitable ;
@@ -55,9 +56,6 @@ pub struct LivenessResult {
55
56
/// Liveness mode in use when these results were computed.
56
57
pub mode : LivenessMode ,
57
58
58
- /// Live variables on entry to each basic block.
59
- pub ins : IndexVec < BasicBlock , LocalSet > ,
60
-
61
59
/// Live variables on exit to each basic block. This is equal to
62
60
/// the union of the `ins` for each successor.
63
61
pub outs : IndexVec < BasicBlock , LocalSet > ,
@@ -124,37 +122,38 @@ pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liveness
124
122
. map ( |b| block ( mode, b, locals) )
125
123
. collect ( ) ;
126
124
127
- let mut ins : IndexVec < _ , _ > = mir. basic_blocks ( )
125
+ let mut outs : IndexVec < _ , _ > = mir. basic_blocks ( )
128
126
. indices ( )
129
127
. map ( |_| LocalSet :: new_empty ( locals) )
130
128
. collect ( ) ;
131
- let mut outs = ins. clone ( ) ;
132
129
133
- let mut changed = true ;
134
130
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) ;
145
131
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 ( ) ;
148
137
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) ;
153
152
}
154
153
}
155
154
}
156
155
157
- LivenessResult { mode, ins , outs }
156
+ LivenessResult { mode, outs }
158
157
}
159
158
160
159
impl LivenessResult {
@@ -195,8 +194,6 @@ impl LivenessResult {
195
194
statement_defs_uses. apply ( & mut bits) ;
196
195
callback ( statement_location, & bits) ;
197
196
}
198
-
199
- assert_eq ! ( bits, self . ins[ block] ) ;
200
197
}
201
198
202
199
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>(
438
435
. collect ( ) ;
439
436
writeln ! ( w, "{} {{{}}}" , prefix, live. join( ", " ) )
440
437
} ;
441
- print ( w, " " , & result. ins ) ?;
442
438
write_basic_block ( tcx, block, mir, & mut |_, _| Ok ( ( ) ) , w) ?;
443
439
print ( w, " " , & result. outs ) ?;
444
440
if block. index ( ) + 1 != mir. basic_blocks ( ) . len ( ) {
0 commit comments