Skip to content

Commit 0066acf

Browse files
committed
Merge apply_effects_in_block and join_state_into_successors_of.
They are always called in succession, so it's simpler if they are merged into a single function.
1 parent 481b5fa commit 0066acf

File tree

2 files changed

+132
-162
lines changed

2 files changed

+132
-162
lines changed

compiler/rustc_mir_dataflow/src/framework/direction.rs

Lines changed: 130 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ pub trait Direction {
1212

1313
const IS_BACKWARD: bool = !Self::IS_FORWARD;
1414

15+
fn apply_effects_in_block<'mir, 'tcx, A>(
16+
analysis: &mut A,
17+
body: &mir::Body<'tcx>,
18+
state: &mut A::Domain,
19+
block: BasicBlock,
20+
block_data: &'mir mir::BasicBlockData<'tcx>,
21+
propagate: impl FnMut(BasicBlock, &A::Domain),
22+
) where
23+
A: Analysis<'tcx>;
24+
1525
/// Applies all effects between the given `EffectIndex`s.
1626
///
1727
/// `effects.start()` must precede or equal `effects.end()` in this direction.
@@ -24,15 +34,6 @@ pub trait Direction {
2434
) where
2535
A: Analysis<'tcx>;
2636

27-
fn apply_effects_in_block<'mir, 'tcx, A>(
28-
analysis: &mut A,
29-
state: &mut A::Domain,
30-
block: BasicBlock,
31-
block_data: &'mir mir::BasicBlockData<'tcx>,
32-
) -> TerminatorEdges<'mir, 'tcx>
33-
where
34-
A: Analysis<'tcx>;
35-
3637
fn visit_results_in_block<'mir, 'tcx, A>(
3738
state: &mut A::Domain,
3839
block: BasicBlock,
@@ -41,16 +42,6 @@ pub trait Direction {
4142
vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
4243
) where
4344
A: Analysis<'tcx>;
44-
45-
fn join_state_into_successors_of<'tcx, A>(
46-
analysis: &mut A,
47-
body: &mir::Body<'tcx>,
48-
exit_state: &mut A::Domain,
49-
block: BasicBlock,
50-
edges: TerminatorEdges<'_, 'tcx>,
51-
propagate: impl FnMut(BasicBlock, &A::Domain),
52-
) where
53-
A: Analysis<'tcx>;
5445
}
5546

5647
/// Dataflow that runs from the exit of a block (terminator), to its entry (the first statement).
@@ -61,23 +52,84 @@ impl Direction for Backward {
6152

6253
fn apply_effects_in_block<'mir, 'tcx, A>(
6354
analysis: &mut A,
55+
body: &mir::Body<'tcx>,
6456
state: &mut A::Domain,
6557
block: BasicBlock,
6658
block_data: &'mir mir::BasicBlockData<'tcx>,
67-
) -> TerminatorEdges<'mir, 'tcx>
68-
where
59+
mut propagate: impl FnMut(BasicBlock, &A::Domain),
60+
) where
6961
A: Analysis<'tcx>,
7062
{
7163
let terminator = block_data.terminator();
7264
let location = Location { block, statement_index: block_data.statements.len() };
7365
analysis.apply_before_terminator_effect(state, terminator, location);
74-
let edges = analysis.apply_terminator_effect(state, terminator, location);
66+
analysis.apply_terminator_effect(state, terminator, location);
7567
for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
7668
let location = Location { block, statement_index };
7769
analysis.apply_before_statement_effect(state, statement, location);
7870
analysis.apply_statement_effect(state, statement, location);
7971
}
80-
edges
72+
73+
let exit_state = state;
74+
for pred in body.basic_blocks.predecessors()[block].iter().copied() {
75+
match body[pred].terminator().kind {
76+
// Apply terminator-specific edge effects.
77+
//
78+
// FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally.
79+
mir::TerminatorKind::Call { destination, target: Some(dest), .. }
80+
if dest == block =>
81+
{
82+
let mut tmp = exit_state.clone();
83+
analysis.apply_call_return_effect(
84+
&mut tmp,
85+
pred,
86+
CallReturnPlaces::Call(destination),
87+
);
88+
propagate(pred, &tmp);
89+
}
90+
91+
mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. }
92+
if targets.contains(&block) =>
93+
{
94+
let mut tmp = exit_state.clone();
95+
analysis.apply_call_return_effect(
96+
&mut tmp,
97+
pred,
98+
CallReturnPlaces::InlineAsm(operands),
99+
);
100+
propagate(pred, &tmp);
101+
}
102+
103+
mir::TerminatorKind::Yield { resume, resume_arg, .. } if resume == block => {
104+
let mut tmp = exit_state.clone();
105+
analysis.apply_call_return_effect(
106+
&mut tmp,
107+
resume,
108+
CallReturnPlaces::Yield(resume_arg),
109+
);
110+
propagate(pred, &tmp);
111+
}
112+
113+
mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
114+
let mut applier = BackwardSwitchIntEdgeEffectsApplier {
115+
body,
116+
pred,
117+
exit_state,
118+
block,
119+
propagate: &mut propagate,
120+
effects_applied: false,
121+
};
122+
123+
analysis.apply_switch_int_edge_effects(pred, discr, &mut applier);
124+
125+
if !applier.effects_applied {
126+
propagate(pred, exit_state)
127+
}
128+
}
129+
130+
_ => propagate(pred, exit_state),
131+
}
132+
}
81133
}
82134

83135
fn apply_effects_in_range<'tcx, A>(
@@ -188,82 +240,13 @@ impl Direction for Backward {
188240

189241
vis.visit_block_start(state);
190242
}
191-
192-
fn join_state_into_successors_of<'tcx, A>(
193-
analysis: &mut A,
194-
body: &mir::Body<'tcx>,
195-
exit_state: &mut A::Domain,
196-
bb: BasicBlock,
197-
_edges: TerminatorEdges<'_, 'tcx>,
198-
mut propagate: impl FnMut(BasicBlock, &A::Domain),
199-
) where
200-
A: Analysis<'tcx>,
201-
{
202-
for pred in body.basic_blocks.predecessors()[bb].iter().copied() {
203-
match body[pred].terminator().kind {
204-
// Apply terminator-specific edge effects.
205-
//
206-
// FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally.
207-
mir::TerminatorKind::Call { destination, target: Some(dest), .. } if dest == bb => {
208-
let mut tmp = exit_state.clone();
209-
analysis.apply_call_return_effect(
210-
&mut tmp,
211-
pred,
212-
CallReturnPlaces::Call(destination),
213-
);
214-
propagate(pred, &tmp);
215-
}
216-
217-
mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. }
218-
if targets.contains(&bb) =>
219-
{
220-
let mut tmp = exit_state.clone();
221-
analysis.apply_call_return_effect(
222-
&mut tmp,
223-
pred,
224-
CallReturnPlaces::InlineAsm(operands),
225-
);
226-
propagate(pred, &tmp);
227-
}
228-
229-
mir::TerminatorKind::Yield { resume, resume_arg, .. } if resume == bb => {
230-
let mut tmp = exit_state.clone();
231-
analysis.apply_call_return_effect(
232-
&mut tmp,
233-
resume,
234-
CallReturnPlaces::Yield(resume_arg),
235-
);
236-
propagate(pred, &tmp);
237-
}
238-
239-
mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
240-
let mut applier = BackwardSwitchIntEdgeEffectsApplier {
241-
body,
242-
pred,
243-
exit_state,
244-
bb,
245-
propagate: &mut propagate,
246-
effects_applied: false,
247-
};
248-
249-
analysis.apply_switch_int_edge_effects(pred, discr, &mut applier);
250-
251-
if !applier.effects_applied {
252-
propagate(pred, exit_state)
253-
}
254-
}
255-
256-
_ => propagate(pred, exit_state),
257-
}
258-
}
259-
}
260243
}
261244

262245
struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> {
263246
body: &'mir mir::Body<'tcx>,
264247
pred: BasicBlock,
265248
exit_state: &'mir mut D,
266-
bb: BasicBlock,
249+
block: BasicBlock,
267250
propagate: &'mir mut F,
268251
effects_applied: bool,
269252
}
@@ -276,8 +259,8 @@ where
276259
fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) {
277260
assert!(!self.effects_applied);
278261

279-
let values = &self.body.basic_blocks.switch_sources()[&(self.bb, self.pred)];
280-
let targets = values.iter().map(|&value| SwitchIntTarget { value, target: self.bb });
262+
let values = &self.body.basic_blocks.switch_sources()[&(self.block, self.pred)];
263+
let targets = values.iter().map(|&value| SwitchIntTarget { value, target: self.block });
281264

282265
let mut tmp = None;
283266
for target in targets {
@@ -298,11 +281,12 @@ impl Direction for Forward {
298281

299282
fn apply_effects_in_block<'mir, 'tcx, A>(
300283
analysis: &mut A,
284+
_body: &mir::Body<'tcx>,
301285
state: &mut A::Domain,
302286
block: BasicBlock,
303287
block_data: &'mir mir::BasicBlockData<'tcx>,
304-
) -> TerminatorEdges<'mir, 'tcx>
305-
where
288+
mut propagate: impl FnMut(BasicBlock, &A::Domain),
289+
) where
306290
A: Analysis<'tcx>,
307291
{
308292
for (statement_index, statement) in block_data.statements.iter().enumerate() {
@@ -313,7 +297,53 @@ impl Direction for Forward {
313297
let terminator = block_data.terminator();
314298
let location = Location { block, statement_index: block_data.statements.len() };
315299
analysis.apply_before_terminator_effect(state, terminator, location);
316-
analysis.apply_terminator_effect(state, terminator, location)
300+
let edges = analysis.apply_terminator_effect(state, terminator, location);
301+
302+
let exit_state = state;
303+
match edges {
304+
TerminatorEdges::None => {}
305+
TerminatorEdges::Single(target) => propagate(target, exit_state),
306+
TerminatorEdges::Double(target, unwind) => {
307+
propagate(target, exit_state);
308+
propagate(unwind, exit_state);
309+
}
310+
TerminatorEdges::AssignOnReturn { return_, cleanup, place } => {
311+
// This must be done *first*, otherwise the unwind path will see the assignments.
312+
if let Some(cleanup) = cleanup {
313+
propagate(cleanup, exit_state);
314+
}
315+
316+
if !return_.is_empty() {
317+
analysis.apply_call_return_effect(exit_state, block, place);
318+
for &target in return_ {
319+
propagate(target, exit_state);
320+
}
321+
}
322+
}
323+
TerminatorEdges::SwitchInt { targets, discr } => {
324+
let mut applier = ForwardSwitchIntEdgeEffectsApplier {
325+
exit_state,
326+
targets,
327+
propagate,
328+
effects_applied: false,
329+
};
330+
331+
analysis.apply_switch_int_edge_effects(block, discr, &mut applier);
332+
333+
let ForwardSwitchIntEdgeEffectsApplier {
334+
exit_state,
335+
mut propagate,
336+
effects_applied,
337+
..
338+
} = applier;
339+
340+
if !effects_applied {
341+
for target in targets.all_targets() {
342+
propagate(*target, exit_state);
343+
}
344+
}
345+
}
346+
}
317347
}
318348

319349
fn apply_effects_in_range<'tcx, A>(
@@ -351,7 +381,8 @@ impl Direction for Forward {
351381
let statement = &block_data.statements[from.statement_index];
352382
analysis.apply_statement_effect(state, statement, location);
353383

354-
// If we only needed to apply the after effect of the statement at `idx`, we are done.
384+
// If we only needed to apply the after effect of the statement at `idx`, we are
385+
// done.
355386
if from == to {
356387
return;
357388
}
@@ -419,62 +450,6 @@ impl Direction for Forward {
419450

420451
vis.visit_block_end(state);
421452
}
422-
423-
fn join_state_into_successors_of<'tcx, A>(
424-
analysis: &mut A,
425-
_body: &mir::Body<'tcx>,
426-
exit_state: &mut A::Domain,
427-
bb: BasicBlock,
428-
edges: TerminatorEdges<'_, 'tcx>,
429-
mut propagate: impl FnMut(BasicBlock, &A::Domain),
430-
) where
431-
A: Analysis<'tcx>,
432-
{
433-
match edges {
434-
TerminatorEdges::None => {}
435-
TerminatorEdges::Single(target) => propagate(target, exit_state),
436-
TerminatorEdges::Double(target, unwind) => {
437-
propagate(target, exit_state);
438-
propagate(unwind, exit_state);
439-
}
440-
TerminatorEdges::AssignOnReturn { return_, cleanup, place } => {
441-
// This must be done *first*, otherwise the unwind path will see the assignments.
442-
if let Some(cleanup) = cleanup {
443-
propagate(cleanup, exit_state);
444-
}
445-
446-
if !return_.is_empty() {
447-
analysis.apply_call_return_effect(exit_state, bb, place);
448-
for &target in return_ {
449-
propagate(target, exit_state);
450-
}
451-
}
452-
}
453-
TerminatorEdges::SwitchInt { targets, discr } => {
454-
let mut applier = ForwardSwitchIntEdgeEffectsApplier {
455-
exit_state,
456-
targets,
457-
propagate,
458-
effects_applied: false,
459-
};
460-
461-
analysis.apply_switch_int_edge_effects(bb, discr, &mut applier);
462-
463-
let ForwardSwitchIntEdgeEffectsApplier {
464-
exit_state,
465-
mut propagate,
466-
effects_applied,
467-
..
468-
} = applier;
469-
470-
if !effects_applied {
471-
for target in targets.all_targets() {
472-
propagate(*target, exit_state);
473-
}
474-
}
475-
}
476-
}
477-
}
478453
}
479454

480455
struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> {

0 commit comments

Comments
 (0)