Skip to content

Commit 474da0f

Browse files
committed
add option to run dataflow on live code only
1 parent 0dab117 commit 474da0f

File tree

13 files changed

+89
-49
lines changed

13 files changed

+89
-49
lines changed

compiler/rustc_borrowck/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ use rustc_mir_dataflow::impls::{
4848
};
4949
use rustc_mir_dataflow::move_paths::{InitIndex, MoveOutIndex, MovePathIndex};
5050
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError};
51-
use rustc_mir_dataflow::Analysis;
5251
use rustc_mir_dataflow::MoveDataParamEnv;
52+
use rustc_mir_dataflow::{Analysis, Blocks};
5353

5454
use crate::session_diagnostics::VarNeedNotMut;
5555

@@ -234,7 +234,7 @@ fn do_mir_borrowck<'tcx>(
234234
let mdpe = MoveDataParamEnv { move_data, param_env };
235235

236236
let mut flow_inits = MaybeInitializedPlaces::new(tcx, &body, &mdpe)
237-
.into_engine(tcx, &body)
237+
.into_engine(tcx, &body, Blocks::All)
238238
.pass_name("borrowck")
239239
.iterate_to_fixpoint()
240240
.into_results_cursor(&body);
@@ -290,15 +290,15 @@ fn do_mir_borrowck<'tcx>(
290290
let regioncx = Rc::new(regioncx);
291291

292292
let flow_borrows = Borrows::new(tcx, body, &regioncx, &borrow_set)
293-
.into_engine(tcx, body)
293+
.into_engine(tcx, body, Blocks::All)
294294
.pass_name("borrowck")
295295
.iterate_to_fixpoint();
296296
let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe)
297-
.into_engine(tcx, body)
297+
.into_engine(tcx, body, Blocks::All)
298298
.pass_name("borrowck")
299299
.iterate_to_fixpoint();
300300
let flow_ever_inits = EverInitializedPlaces::new(tcx, body, &mdpe)
301-
.into_engine(tcx, body)
301+
.into_engine(tcx, body, Blocks::All)
302302
.pass_name("borrowck")
303303
.iterate_to_fixpoint();
304304

compiler/rustc_const_eval/src/transform/check_consts/check.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::mir::*;
1111
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
1212
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
1313
use rustc_middle::ty::{Binder, TraitRef, TypeVisitable};
14-
use rustc_mir_dataflow::{self, Analysis};
14+
use rustc_mir_dataflow::{self, Analysis, Blocks};
1515
use rustc_span::{sym, Span, Symbol};
1616
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
1717
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
@@ -58,7 +58,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
5858
let ConstCx { tcx, body, .. } = *ccx;
5959

6060
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
61-
.into_engine(tcx, &body)
61+
.into_engine(tcx, &body, Blocks::All)
6262
.iterate_to_fixpoint()
6363
.into_results_cursor(&body)
6464
});
@@ -85,7 +85,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
8585
let ConstCx { tcx, body, .. } = *ccx;
8686

8787
FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
88-
.into_engine(tcx, &body)
88+
.into_engine(tcx, &body, Blocks::All)
8989
.iterate_to_fixpoint()
9090
.into_results_cursor(&body)
9191
});
@@ -115,7 +115,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
115115
let ConstCx { tcx, body, .. } = *ccx;
116116

117117
FlowSensitiveAnalysis::new(HasMutInterior, ccx)
118-
.into_engine(tcx, &body)
118+
.into_engine(tcx, &body, Blocks::All)
119119
.iterate_to_fixpoint()
120120
.into_results_cursor(&body)
121121
});
@@ -163,7 +163,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
163163

164164
hir::ConstContext::Const | hir::ConstContext::Static(_) => {
165165
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
166-
.into_engine(ccx.tcx, &ccx.body)
166+
.into_engine(ccx.tcx, &ccx.body, Blocks::All)
167167
.iterate_to_fixpoint()
168168
.into_results_cursor(&ccx.body);
169169

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::mir::{
1515
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitable};
1616
use rustc_mir_dataflow::impls::MaybeStorageLive;
1717
use rustc_mir_dataflow::storage::always_storage_live_locals;
18-
use rustc_mir_dataflow::{Analysis, ResultsCursor};
18+
use rustc_mir_dataflow::{Analysis, Blocks, ResultsCursor};
1919
use rustc_target::abi::{Size, VariantIdx};
2020

2121
#[derive(Copy, Clone, Debug)]
@@ -53,7 +53,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
5353

5454
let always_live_locals = always_storage_live_locals(body);
5555
let storage_liveness = MaybeStorageLive::new(std::borrow::Cow::Owned(always_live_locals))
56-
.into_engine(tcx, body)
56+
.into_engine(tcx, body, Blocks::All)
5757
.iterate_to_fixpoint()
5858
.into_results_cursor(body);
5959

compiler/rustc_mir_dataflow/src/framework/engine.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ where
7171
}
7272
}
7373

74+
pub enum Blocks {
75+
/// Consider all MIR blocks
76+
All,
77+
/// Consider only the MIR blocks reachable from the start
78+
Reachable,
79+
}
80+
7481
/// A solver for dataflow problems.
7582
pub struct Engine<'a, 'tcx, A>
7683
where
@@ -90,6 +97,7 @@ where
9097
// performance in practice. I've tried a few ways to avoid this, but they have downsides. See
9198
// the message for the commit that added this FIXME for more information.
9299
apply_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
100+
blocks: Blocks,
93101
}
94102

95103
impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A>
@@ -99,13 +107,18 @@ where
99107
T: Idx,
100108
{
101109
/// Creates a new `Engine` to solve a gen-kill dataflow problem.
102-
pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, analysis: A) -> Self {
110+
pub fn new_gen_kill(
111+
tcx: TyCtxt<'tcx>,
112+
body: &'a mir::Body<'tcx>,
113+
analysis: A,
114+
blocks: Blocks,
115+
) -> Self {
103116
// If there are no back-edges in the control-flow graph, we only ever need to apply the
104117
// transfer function for each block exactly once (assuming that we process blocks in RPO).
105118
//
106119
// In this case, there's no need to compute the block transfer functions ahead of time.
107120
if !body.basic_blocks.is_cfg_cyclic() {
108-
return Self::new(tcx, body, analysis, None);
121+
return Self::new(tcx, body, analysis, None, blocks);
109122
}
110123

111124
// Otherwise, compute and store the cumulative transfer function for each block.
@@ -122,7 +135,7 @@ where
122135
trans_for_block[bb].apply(state);
123136
});
124137

125-
Self::new(tcx, body, analysis, Some(apply_trans as Box<_>))
138+
Self::new(tcx, body, analysis, Some(apply_trans as Box<_>), blocks)
126139
}
127140
}
128141

@@ -136,15 +149,21 @@ where
136149
///
137150
/// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for
138151
/// better performance.
139-
pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, analysis: A) -> Self {
140-
Self::new(tcx, body, analysis, None)
152+
pub fn new_generic(
153+
tcx: TyCtxt<'tcx>,
154+
body: &'a mir::Body<'tcx>,
155+
analysis: A,
156+
blocks: Blocks,
157+
) -> Self {
158+
Self::new(tcx, body, analysis, None, blocks)
141159
}
142160

143161
fn new(
144162
tcx: TyCtxt<'tcx>,
145163
body: &'a mir::Body<'tcx>,
146164
analysis: A,
147165
apply_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
166+
blocks: Blocks,
148167
) -> Self {
149168
let bottom_value = analysis.bottom_value(body);
150169
let mut entry_sets = IndexVec::from_elem(bottom_value.clone(), &body.basic_blocks);
@@ -162,6 +181,7 @@ where
162181
pass_name: None,
163182
entry_sets,
164183
apply_trans_for_block,
184+
blocks,
165185
}
166186
}
167187

@@ -197,21 +217,32 @@ where
197217
tcx,
198218
apply_trans_for_block,
199219
pass_name,
220+
blocks,
200221
..
201222
} = self;
202223

203224
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
225+
// could be tracked in `entry_sets`
226+
let mut visited = BitSet::new_empty(body.basic_blocks.len());
204227

205228
if A::Direction::IS_FORWARD {
206-
for (bb, _) in traversal::reverse_postorder(body) {
207-
dirty_queue.insert(bb);
229+
match blocks {
230+
Blocks::All => {
231+
for (bb, _) in traversal::reverse_postorder(body) {
232+
dirty_queue.insert(bb);
233+
}
234+
}
235+
Blocks::Reachable => {
236+
dirty_queue.insert(mir::START_BLOCK);
237+
}
208238
}
209239
} else {
210240
// Reverse post-order on the reverse CFG may generate a better iteration order for
211241
// backward dataflow analyses, but probably not enough to matter.
212242
for (bb, _) in traversal::postorder(body) {
213243
dirty_queue.insert(bb);
214244
}
245+
assert!(matches!(blocks, Blocks::All));
215246
}
216247

217248
// `state` is not actually used between iterations;
@@ -241,8 +272,9 @@ where
241272
(bb, bb_data),
242273
|target: BasicBlock, state: &A::Domain| {
243274
let set_changed = entry_sets[target].join(state);
244-
if set_changed {
275+
if set_changed || !visited.contains(target) {
245276
dirty_queue.insert(target);
277+
visited.insert(target);
246278
}
247279
},
248280
);

compiler/rustc_mir_dataflow/src/framework/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ mod visitor;
4747

4848
pub use self::cursor::{ResultsCursor, ResultsRefCursor};
4949
pub use self::direction::{Backward, Direction, Forward};
50-
pub use self::engine::{Engine, Results};
50+
pub use self::engine::{Blocks, Engine, Results};
5151
pub use self::lattice::{JoinSemiLattice, MeetSemiLattice};
5252
pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor};
5353

@@ -261,11 +261,12 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
261261
self,
262262
tcx: TyCtxt<'tcx>,
263263
body: &'mir mir::Body<'tcx>,
264+
blocks: Blocks,
264265
) -> Engine<'mir, 'tcx, Self>
265266
where
266267
Self: Sized,
267268
{
268-
Engine::new_generic(tcx, body, self)
269+
Engine::new_generic(tcx, body, self, blocks)
269270
}
270271
}
271272

@@ -419,11 +420,12 @@ where
419420
self,
420421
tcx: TyCtxt<'tcx>,
421422
body: &'mir mir::Body<'tcx>,
423+
blocks: Blocks,
422424
) -> Engine<'mir, 'tcx, Self>
423425
where
424426
Self: Sized,
425427
{
426-
Engine::new_gen_kill(tcx, body, self)
428+
Engine::new_gen_kill(tcx, body, self, blocks)
427429
}
428430
}
429431

compiler/rustc_mir_dataflow/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ pub use self::drop_flag_effects::{
2525
on_lookup_result_bits,
2626
};
2727
pub use self::framework::{
28-
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces,
29-
Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor,
30-
ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
28+
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Blocks,
29+
CallReturnPlaces, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice,
30+
Results, ResultsCursor, ResultsRefCursor, ResultsVisitable, ResultsVisitor,
31+
SwitchIntEdgeEffects,
3132
};
3233

3334
use self::move_paths::MoveData;

compiler/rustc_mir_dataflow/src/rustc_peek.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::errors::{
1010
PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary,
1111
PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation,
1212
};
13-
use crate::framework::BitSetExt;
13+
use crate::framework::{BitSetExt, Blocks};
1414
use crate::impls::{
1515
DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces,
1616
};
@@ -39,30 +39,31 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
3939

4040
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() {
4141
let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe)
42-
.into_engine(tcx, body)
42+
.into_engine(tcx, body, Blocks::All)
4343
.iterate_to_fixpoint();
4444

4545
sanity_check_via_rustc_peek(tcx, body, &flow_inits);
4646
}
4747

4848
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() {
4949
let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe)
50-
.into_engine(tcx, body)
50+
.into_engine(tcx, body, Blocks::All)
5151
.iterate_to_fixpoint();
5252

5353
sanity_check_via_rustc_peek(tcx, body, &flow_uninits);
5454
}
5555

5656
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() {
5757
let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe)
58-
.into_engine(tcx, body)
58+
.into_engine(tcx, body, Blocks::All)
5959
.iterate_to_fixpoint();
6060

6161
sanity_check_via_rustc_peek(tcx, body, &flow_def_inits);
6262
}
6363

6464
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() {
65-
let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint();
65+
let flow_liveness =
66+
MaybeLiveLocals.into_engine(tcx, body, Blocks::All).iterate_to_fixpoint();
6667

6768
sanity_check_via_rustc_peek(tcx, body, &flow_liveness);
6869
}

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use rustc_middle::mir::visit::{MutVisitor, Visitor};
99
use rustc_middle::mir::*;
1010
use rustc_middle::ty::{self, Ty, TyCtxt};
1111
use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace};
12-
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
12+
use rustc_mir_dataflow::{
13+
lattice::FlatSet, Analysis, Blocks, ResultsVisitor, SwitchIntEdgeEffects,
14+
};
1315
use rustc_span::DUMMY_SP;
1416
use rustc_target::abi::Align;
1517

@@ -53,7 +55,7 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
5355
// Perform the actual dataflow analysis.
5456
let analysis = ConstAnalysis::new(tcx, body, map);
5557
let results = debug_span!("analyze")
56-
.in_scope(|| analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint());
58+
.in_scope(|| analysis.wrap().into_engine(tcx, body, Blocks::All).iterate_to_fixpoint());
5759

5860
// Collect results and patch the body afterwards.
5961
let mut visitor = CollectAndPatch::new(tcx, &results.analysis.0.map);

compiler/rustc_mir_transform/src/dead_store_elimination.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ use rustc_index::bit_set::BitSet;
1616
use rustc_middle::mir::*;
1717
use rustc_middle::ty::TyCtxt;
1818
use rustc_mir_dataflow::impls::{borrowed_locals, MaybeTransitiveLiveLocals};
19-
use rustc_mir_dataflow::Analysis;
19+
use rustc_mir_dataflow::{Analysis, Blocks};
2020

2121
/// Performs the optimization on the body
2222
///
2323
/// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
2424
/// can be generated via the [`borrowed_locals`] function.
2525
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
2626
let mut live = MaybeTransitiveLiveLocals::new(borrowed)
27-
.into_engine(tcx, body)
27+
.into_engine(tcx, body, Blocks::All)
2828
.iterate_to_fixpoint()
2929
.into_results_cursor(body);
3030

compiler/rustc_mir_transform/src/dest_prop.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ use rustc_middle::mir::{
141141
};
142142
use rustc_middle::ty::TyCtxt;
143143
use rustc_mir_dataflow::impls::MaybeLiveLocals;
144-
use rustc_mir_dataflow::{Analysis, ResultsCursor};
144+
use rustc_mir_dataflow::{Analysis, Blocks, ResultsCursor};
145145

146146
pub struct DestinationPropagation;
147147

@@ -189,7 +189,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
189189
);
190190
trace!(?candidates);
191191
let mut live = MaybeLiveLocals
192-
.into_engine(tcx, body)
192+
.into_engine(tcx, body, Blocks::All)
193193
.iterate_to_fixpoint()
194194
.into_results_cursor(body);
195195
dest_prop_mir_dump(tcx, body, &mut live, round_count);

0 commit comments

Comments
 (0)