Skip to content

Commit d78e7bb

Browse files
committed
Remove Engine.
It's no longer needed. `Engine::iterate_to_fixpoint` can be inlined into `Analysis::iterate_to_fixpoint` and removed. The commit also renames `engine.rs` as `results.rs`.
1 parent e54c177 commit d78e7bb

File tree

3 files changed

+80
-102
lines changed

3 files changed

+80
-102
lines changed

Diff for: compiler/rustc_mir_dataflow/src/framework/mod.rs

+72-6
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,29 @@
3333
3434
use std::cmp::Ordering;
3535

36-
use rustc_index::Idx;
36+
use rustc_data_structures::work_queue::WorkQueue;
3737
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
38-
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
38+
use rustc_index::{Idx, IndexVec};
39+
use rustc_middle::bug;
40+
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal};
3941
use rustc_middle::ty::TyCtxt;
42+
use tracing::error;
4043

44+
use self::results::write_graphviz_results;
4145
use super::fmt::DebugWithContext;
4246

4347
mod cursor;
4448
mod direction;
45-
mod engine;
4649
pub mod fmt;
4750
pub mod graphviz;
4851
pub mod lattice;
52+
mod results;
4953
mod visitor;
5054

5155
pub use self::cursor::ResultsCursor;
5256
pub use self::direction::{Backward, Direction, Forward};
53-
pub use self::engine::{Engine, Results};
5457
pub use self::lattice::{JoinSemiLattice, MaybeReachable};
58+
pub use self::results::Results;
5559
pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results};
5660

5761
/// Analysis domains are all bitsets of various kinds. This trait holds
@@ -238,7 +242,7 @@ pub trait Analysis<'tcx> {
238242
/// Without a `pass_name` to differentiates them, only the results for the latest run will be
239243
/// saved.
240244
fn iterate_to_fixpoint<'mir>(
241-
self,
245+
mut self,
242246
tcx: TyCtxt<'tcx>,
243247
body: &'mir mir::Body<'tcx>,
244248
pass_name: Option<&'static str>,
@@ -247,7 +251,69 @@ pub trait Analysis<'tcx> {
247251
Self: Sized,
248252
Self::Domain: DebugWithContext<Self>,
249253
{
250-
Engine::iterate_to_fixpoint(tcx, body, self, pass_name)
254+
let mut entry_sets =
255+
IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len());
256+
self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
257+
258+
if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) {
259+
bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
260+
}
261+
262+
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
263+
264+
if Self::Direction::IS_FORWARD {
265+
for (bb, _) in traversal::reverse_postorder(body) {
266+
dirty_queue.insert(bb);
267+
}
268+
} else {
269+
// Reverse post-order on the reverse CFG may generate a better iteration order for
270+
// backward dataflow analyses, but probably not enough to matter.
271+
for (bb, _) in traversal::postorder(body) {
272+
dirty_queue.insert(bb);
273+
}
274+
}
275+
276+
// `state` is not actually used between iterations;
277+
// this is just an optimization to avoid reallocating
278+
// every iteration.
279+
let mut state = self.bottom_value(body);
280+
while let Some(bb) = dirty_queue.pop() {
281+
let bb_data = &body[bb];
282+
283+
// Set the state to the entry state of the block.
284+
// This is equivalent to `state = entry_sets[bb].clone()`,
285+
// but it saves an allocation, thus improving compile times.
286+
state.clone_from(&entry_sets[bb]);
287+
288+
// Apply the block transfer function, using the cached one if it exists.
289+
let edges = Self::Direction::apply_effects_in_block(&mut self, &mut state, bb, bb_data);
290+
291+
Self::Direction::join_state_into_successors_of(
292+
&mut self,
293+
body,
294+
&mut state,
295+
bb,
296+
edges,
297+
|target: BasicBlock, state: &Self::Domain| {
298+
let set_changed = entry_sets[target].join(state);
299+
if set_changed {
300+
dirty_queue.insert(target);
301+
}
302+
},
303+
);
304+
}
305+
306+
let results = Results { analysis: self, entry_sets };
307+
308+
if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
309+
let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
310+
if let Err(e) = res {
311+
error!("Failed to write graphviz dataflow results: {}", e);
312+
}
313+
results
314+
} else {
315+
results
316+
}
251317
}
252318
}
253319

Diff for: compiler/rustc_mir_dataflow/src/framework/engine.rs renamed to compiler/rustc_mir_dataflow/src/framework/results.rs

+5-93
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
1-
//! A solver for dataflow problems.
1+
//! Dataflow analysis results.
22
33
use std::ffi::OsString;
44
use std::path::PathBuf;
55

6-
use rustc_data_structures::work_queue::WorkQueue;
76
use rustc_hir::def_id::DefId;
87
use rustc_index::IndexVec;
9-
use rustc_middle::bug;
108
use rustc_middle::mir::{self, BasicBlock, create_dump_file, dump_enabled, traversal};
119
use rustc_middle::ty::TyCtxt;
1210
use rustc_middle::ty::print::with_no_trimmed_paths;
1311
use rustc_span::symbol::{Symbol, sym};
14-
use tracing::{debug, error};
12+
use tracing::debug;
1513
use {rustc_ast as ast, rustc_graphviz as dot};
1614

1715
use super::fmt::DebugWithContext;
18-
use super::{
19-
Analysis, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, visit_results,
20-
};
16+
use super::{Analysis, ResultsCursor, ResultsVisitor, graphviz, visit_results};
2117
use crate::errors::{
2218
DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
2319
};
@@ -65,101 +61,17 @@ where
6561
body: &'mir mir::Body<'tcx>,
6662
vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>,
6763
) {
68-
let blocks = mir::traversal::reachable(body);
64+
let blocks = traversal::reachable(body);
6965
visit_results(body, blocks.map(|(bb, _)| bb), self, vis)
7066
}
7167
}
7268

73-
/// A solver for dataflow problems.
74-
pub struct Engine;
75-
76-
impl Engine {
77-
/// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer
78-
/// function.
79-
pub(crate) fn iterate_to_fixpoint<'mir, 'tcx, A>(
80-
tcx: TyCtxt<'tcx>,
81-
body: &'mir mir::Body<'tcx>,
82-
mut analysis: A,
83-
pass_name: Option<&'static str>,
84-
) -> Results<'tcx, A>
85-
where
86-
A: Analysis<'tcx>,
87-
A::Domain: DebugWithContext<A> + Clone + JoinSemiLattice,
88-
{
89-
let mut entry_sets =
90-
IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len());
91-
analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
92-
93-
if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != analysis.bottom_value(body)
94-
{
95-
bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
96-
}
97-
98-
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
99-
100-
if A::Direction::IS_FORWARD {
101-
for (bb, _) in traversal::reverse_postorder(body) {
102-
dirty_queue.insert(bb);
103-
}
104-
} else {
105-
// Reverse post-order on the reverse CFG may generate a better iteration order for
106-
// backward dataflow analyses, but probably not enough to matter.
107-
for (bb, _) in traversal::postorder(body) {
108-
dirty_queue.insert(bb);
109-
}
110-
}
111-
112-
// `state` is not actually used between iterations;
113-
// this is just an optimization to avoid reallocating
114-
// every iteration.
115-
let mut state = analysis.bottom_value(body);
116-
while let Some(bb) = dirty_queue.pop() {
117-
let bb_data = &body[bb];
118-
119-
// Set the state to the entry state of the block.
120-
// This is equivalent to `state = entry_sets[bb].clone()`,
121-
// but it saves an allocation, thus improving compile times.
122-
state.clone_from(&entry_sets[bb]);
123-
124-
// Apply the block transfer function, using the cached one if it exists.
125-
let edges =
126-
A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data);
127-
128-
A::Direction::join_state_into_successors_of(
129-
&mut analysis,
130-
body,
131-
&mut state,
132-
bb,
133-
edges,
134-
|target: BasicBlock, state: &A::Domain| {
135-
let set_changed = entry_sets[target].join(state);
136-
if set_changed {
137-
dirty_queue.insert(target);
138-
}
139-
},
140-
);
141-
}
142-
143-
let results = Results { analysis, entry_sets };
144-
145-
if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
146-
let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
147-
if let Err(e) = res {
148-
error!("Failed to write graphviz dataflow results: {}", e);
149-
}
150-
results
151-
} else {
152-
results
153-
}
154-
}
155-
}
156-
15769
// Graphviz
15870

15971
/// Writes a DOT file containing the results of a dataflow analysis if the user requested it via
16072
/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are
16173
/// the same.
162-
fn write_graphviz_results<'tcx, A>(
74+
pub(super) fn write_graphviz_results<'tcx, A>(
16375
tcx: TyCtxt<'tcx>,
16476
body: &mir::Body<'tcx>,
16577
results: Results<'tcx, A>,

Diff for: compiler/rustc_mir_dataflow/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ pub use self::drop_flag_effects::{
1818
move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
1919
};
2020
pub use self::framework::{
21-
Analysis, Backward, Direction, Engine, Forward, GenKill, JoinSemiLattice, MaybeReachable,
22-
Results, ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz,
23-
lattice, visit_results,
21+
Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results,
22+
ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice,
23+
visit_results,
2424
};
2525
use self::move_paths::MoveData;
2626

0 commit comments

Comments
 (0)