Skip to content

Commit cb56ff5

Browse files
committed
reorder liveness to bring the more significant code up top
1 parent 899c7ad commit cb56ff5

File tree

1 file changed

+107
-107
lines changed

1 file changed

+107
-107
lines changed

src/librustc_mir/util/liveness.rs

Lines changed: 107 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,113 @@ use std::io::{self, Write};
4747

4848
pub type LocalSet = IdxSetBuf<Local>;
4949

50+
// This gives the result of the liveness analysis at the boundary of basic blocks
51+
pub struct LivenessResult {
52+
pub ins: IndexVec<BasicBlock, LocalSet>,
53+
pub outs: IndexVec<BasicBlock, LocalSet>,
54+
}
55+
56+
pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>) -> LivenessResult {
57+
let locals = mir.local_decls.len();
58+
let def_use: IndexVec<_, _> = mir.basic_blocks().iter().map(|b| {
59+
block(b, locals)
60+
}).collect();
61+
62+
let mut ins: IndexVec<_, _> = mir.basic_blocks()
63+
.indices()
64+
.map(|_| LocalSet::new_empty(locals))
65+
.collect();
66+
let mut outs = ins.clone();
67+
68+
let mut changed = true;
69+
let mut bits = LocalSet::new_empty(locals);
70+
while changed {
71+
changed = false;
72+
73+
for b in mir.basic_blocks().indices().rev() {
74+
// outs[b] = ∪ {ins of successors}
75+
bits.clear();
76+
for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
77+
bits.union(&ins[successor]);
78+
}
79+
outs[b].clone_from(&bits);
80+
81+
// bits = use ∪ (bits - def)
82+
def_use[b].apply(&mut bits);
83+
84+
// update bits on entry and flag if they have changed
85+
if ins[b] != bits {
86+
ins[b].clone_from(&bits);
87+
changed = true;
88+
}
89+
}
90+
}
91+
92+
LivenessResult {
93+
ins,
94+
outs,
95+
}
96+
}
97+
98+
impl LivenessResult {
99+
/// Walks backwards through the statements/terminator in the given
100+
/// basic block `block`. At each point within `block`, invokes
101+
/// the callback `op` with the current location and the set of
102+
/// variables that are live on entry to that location.
103+
pub fn simulate_block<'tcx, OP>(&self,
104+
mir: &Mir<'tcx>,
105+
block: BasicBlock,
106+
mut callback: OP)
107+
where OP: FnMut(Location, &LocalSet)
108+
{
109+
let data = &mir[block];
110+
111+
// Get a copy of the bits on exit from the block.
112+
let mut bits = self.outs[block].clone();
113+
114+
// Start with the maximal statement index -- i.e., right before
115+
// the terminator executes.
116+
let mut statement_index = data.statements.len();
117+
118+
// Compute liveness right before terminator and invoke callback.
119+
let terminator_location = Location { block, statement_index };
120+
let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
121+
terminator_defs_uses.apply(&mut bits);
122+
callback(terminator_location, &bits);
123+
124+
// Compute liveness before each statement (in rev order) and invoke callback.
125+
for statement in data.statements.iter().rev() {
126+
statement_index -= 1;
127+
let statement_location = Location { block, statement_index };
128+
let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
129+
statement_defs_uses.apply(&mut bits);
130+
callback(statement_location, &bits);
131+
}
132+
133+
assert_eq!(bits, self.ins[block]);
134+
}
135+
136+
fn defs_uses<'tcx, V>(&self,
137+
mir: &Mir<'tcx>,
138+
location: Location,
139+
thing: &V)
140+
-> DefsUses
141+
where V: MirVisitable<'tcx>,
142+
{
143+
let locals = mir.local_decls.len();
144+
let mut visitor = DefsUses {
145+
defs: LocalSet::new_empty(locals),
146+
uses: LocalSet::new_empty(locals),
147+
};
148+
149+
// Visit the various parts of the basic block in reverse. If we go
150+
// forward, the logic in `add_def` and `add_use` would be wrong.
151+
thing.apply(location, &mut visitor);
152+
153+
visitor
154+
}
155+
}
156+
50157
#[derive(Eq, PartialEq, Clone)]
51158
struct DefsUses {
52159
defs: LocalSet,
@@ -159,113 +266,6 @@ fn block<'tcx>(b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses {
159266
visitor
160267
}
161268

162-
// This gives the result of the liveness analysis at the boundary of basic blocks
163-
pub struct LivenessResult {
164-
pub ins: IndexVec<BasicBlock, LocalSet>,
165-
pub outs: IndexVec<BasicBlock, LocalSet>,
166-
}
167-
168-
pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>) -> LivenessResult {
169-
let locals = mir.local_decls.len();
170-
let def_use: IndexVec<_, _> = mir.basic_blocks().iter().map(|b| {
171-
block(b, locals)
172-
}).collect();
173-
174-
let mut ins: IndexVec<_, _> = mir.basic_blocks()
175-
.indices()
176-
.map(|_| LocalSet::new_empty(locals))
177-
.collect();
178-
let mut outs = ins.clone();
179-
180-
let mut changed = true;
181-
let mut bits = LocalSet::new_empty(locals);
182-
while changed {
183-
changed = false;
184-
185-
for b in mir.basic_blocks().indices().rev() {
186-
// outs[b] = ∪ {ins of successors}
187-
bits.clear();
188-
for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
189-
bits.union(&ins[successor]);
190-
}
191-
outs[b].clone_from(&bits);
192-
193-
// bits = use ∪ (bits - def)
194-
def_use[b].apply(&mut bits);
195-
196-
// update bits on entry and flag if they have changed
197-
if ins[b] != bits {
198-
ins[b].clone_from(&bits);
199-
changed = true;
200-
}
201-
}
202-
}
203-
204-
LivenessResult {
205-
ins,
206-
outs,
207-
}
208-
}
209-
210-
impl LivenessResult {
211-
/// Walks backwards through the statements/terminator in the given
212-
/// basic block `block`. At each point within `block`, invokes
213-
/// the callback `op` with the current location and the set of
214-
/// variables that are live on entry to that location.
215-
pub fn simulate_block<'tcx, OP>(&self,
216-
mir: &Mir<'tcx>,
217-
block: BasicBlock,
218-
mut callback: OP)
219-
where OP: FnMut(Location, &LocalSet)
220-
{
221-
let data = &mir[block];
222-
223-
// Get a copy of the bits on exit from the block.
224-
let mut bits = self.outs[block].clone();
225-
226-
// Start with the maximal statement index -- i.e., right before
227-
// the terminator executes.
228-
let mut statement_index = data.statements.len();
229-
230-
// Compute liveness right before terminator and invoke callback.
231-
let terminator_location = Location { block, statement_index };
232-
let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
233-
terminator_defs_uses.apply(&mut bits);
234-
callback(terminator_location, &bits);
235-
236-
// Compute liveness before each statement (in rev order) and invoke callback.
237-
for statement in data.statements.iter().rev() {
238-
statement_index -= 1;
239-
let statement_location = Location { block, statement_index };
240-
let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
241-
statement_defs_uses.apply(&mut bits);
242-
callback(statement_location, &bits);
243-
}
244-
245-
assert_eq!(bits, self.ins[block]);
246-
}
247-
248-
fn defs_uses<'tcx, V>(&self,
249-
mir: &Mir<'tcx>,
250-
location: Location,
251-
thing: &V)
252-
-> DefsUses
253-
where V: MirVisitable<'tcx>,
254-
{
255-
let locals = mir.local_decls.len();
256-
let mut visitor = DefsUses {
257-
defs: LocalSet::new_empty(locals),
258-
uses: LocalSet::new_empty(locals),
259-
};
260-
261-
// Visit the various parts of the basic block in reverse. If we go
262-
// forward, the logic in `add_def` and `add_use` would be wrong.
263-
thing.apply(location, &mut visitor);
264-
265-
visitor
266-
}
267-
}
268-
269269
trait MirVisitable<'tcx> {
270270
fn apply<V>(&self, location: Location, visitor: &mut V)
271271
where V: Visitor<'tcx>;

0 commit comments

Comments
 (0)