Skip to content

Commit f19cd3f

Browse files
committed
Use TerminatorEdge for dataflow-const-prop.
1 parent 3acfa09 commit f19cd3f

File tree

2 files changed

+49
-63
lines changed

2 files changed

+49
-63
lines changed

compiler/rustc_mir_dataflow/src/value_analysis.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,19 @@ pub trait ValueAnalysis<'tcx> {
241241

242242
/// The effect of a successful function call return should not be
243243
/// applied here, see [`Analysis::apply_terminator_effect`].
244-
fn handle_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State<Self::Value>) {
244+
fn handle_terminator<'mir>(
245+
&self,
246+
terminator: &'mir Terminator<'tcx>,
247+
state: &mut State<Self::Value>,
248+
) -> TerminatorEdge<'mir, 'tcx> {
245249
self.super_terminator(terminator, state)
246250
}
247251

248-
fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State<Self::Value>) {
252+
fn super_terminator<'mir>(
253+
&self,
254+
terminator: &'mir Terminator<'tcx>,
255+
state: &mut State<Self::Value>,
256+
) -> TerminatorEdge<'mir, 'tcx> {
249257
match &terminator.kind {
250258
TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => {
251259
// Effect is applied by `handle_call_return`.
@@ -257,8 +265,10 @@ pub trait ValueAnalysis<'tcx> {
257265
// They would have an effect, but are not allowed in this phase.
258266
bug!("encountered disallowed terminator");
259267
}
268+
TerminatorKind::SwitchInt { discr, targets } => {
269+
return self.handle_switch_int(discr, targets, state);
270+
}
260271
TerminatorKind::Goto { .. }
261-
| TerminatorKind::SwitchInt { .. }
262272
| TerminatorKind::Resume
263273
| TerminatorKind::Terminate
264274
| TerminatorKind::Return
@@ -270,6 +280,7 @@ pub trait ValueAnalysis<'tcx> {
270280
// These terminators have no effect on the analysis.
271281
}
272282
}
283+
terminator.edges()
273284
}
274285

275286
fn handle_call_return(
@@ -290,19 +301,22 @@ pub trait ValueAnalysis<'tcx> {
290301
})
291302
}
292303

293-
fn handle_switch_int(
304+
fn handle_switch_int<'mir>(
294305
&self,
295-
discr: &Operand<'tcx>,
296-
apply_edge_effects: &mut impl SwitchIntEdgeEffects<State<Self::Value>>,
297-
) {
298-
self.super_switch_int(discr, apply_edge_effects)
306+
discr: &'mir Operand<'tcx>,
307+
targets: &'mir SwitchTargets,
308+
state: &mut State<Self::Value>,
309+
) -> TerminatorEdge<'mir, 'tcx> {
310+
self.super_switch_int(discr, targets, state)
299311
}
300312

301-
fn super_switch_int(
313+
fn super_switch_int<'mir>(
302314
&self,
303-
_discr: &Operand<'tcx>,
304-
_apply_edge_effects: &mut impl SwitchIntEdgeEffects<State<Self::Value>>,
305-
) {
315+
discr: &'mir Operand<'tcx>,
316+
targets: &'mir SwitchTargets,
317+
_state: &mut State<Self::Value>,
318+
) -> TerminatorEdge<'mir, 'tcx> {
319+
TerminatorEdge::SwitchInt { discr, targets }
306320
}
307321

308322
fn wrap(self) -> ValueAnalysisWrapper<Self>
@@ -359,9 +373,10 @@ where
359373
_location: Location,
360374
) -> TerminatorEdge<'mir, 'tcx> {
361375
if state.is_reachable() {
362-
self.0.handle_terminator(terminator, state);
376+
self.0.handle_terminator(terminator, state)
377+
} else {
378+
TerminatorEdge::None
363379
}
364-
terminator.edges()
365380
}
366381

367382
fn apply_call_return_effect(
@@ -378,11 +393,9 @@ where
378393
fn apply_switch_int_edge_effects(
379394
&mut self,
380395
_block: BasicBlock,
381-
discr: &Operand<'tcx>,
382-
apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
396+
_discr: &Operand<'tcx>,
397+
_apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
383398
) {
384-
// FIXME: Dataflow framework provides no access to current state here.
385-
self.0.handle_switch_int(discr, apply_edge_effects)
386399
}
387400
}
388401

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
1313
use rustc_mir_dataflow::value_analysis::{
1414
Map, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
1515
};
16-
use rustc_mir_dataflow::{
17-
lattice::FlatSet, Analysis, Results, ResultsVisitor, SwitchIntEdgeEffects,
18-
};
16+
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor};
1917
use rustc_span::DUMMY_SP;
2018
use rustc_target::abi::{Align, FieldIdx, VariantIdx};
2119

@@ -249,49 +247,24 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
249247
.unwrap_or(FlatSet::Top)
250248
}
251249

252-
fn handle_switch_int(
250+
fn handle_switch_int<'mir>(
253251
&self,
254-
discr: &Operand<'tcx>,
255-
apply_edge_effects: &mut impl SwitchIntEdgeEffects<State<Self::Value>>,
256-
) {
257-
// FIXME: The dataflow framework only provides the state if we call `apply()`, which makes
258-
// this more inefficient than it has to be.
259-
let mut discr_value = None;
260-
let mut handled = false;
261-
apply_edge_effects.apply(|state, target| {
262-
let discr_value = match discr_value {
263-
Some(value) => value,
264-
None => {
265-
let value = match self.handle_operand(discr, state) {
266-
ValueOrPlace::Value(value) => value,
267-
ValueOrPlace::Place(place) => state.get_idx(place, self.map()),
268-
};
269-
let result = match value {
270-
FlatSet::Top => FlatSet::Top,
271-
FlatSet::Elem(ScalarTy(scalar, _)) => {
272-
let int = scalar.assert_int();
273-
FlatSet::Elem(int.assert_bits(int.size()))
274-
}
275-
FlatSet::Bottom => FlatSet::Bottom,
276-
};
277-
discr_value = Some(result);
278-
result
279-
}
280-
};
281-
282-
let FlatSet::Elem(choice) = discr_value else {
283-
// Do nothing if we don't know which branch will be taken.
284-
return;
285-
};
286-
287-
if target.value.map(|n| n == choice).unwrap_or(!handled) {
288-
// Branch is taken. Has no effect on state.
289-
handled = true;
290-
} else {
291-
// Branch is not taken.
292-
state.mark_unreachable();
293-
}
294-
})
252+
discr: &'mir Operand<'tcx>,
253+
targets: &'mir SwitchTargets,
254+
state: &mut State<Self::Value>,
255+
) -> TerminatorEdge<'mir, 'tcx> {
256+
let value = match self.handle_operand(discr, state) {
257+
ValueOrPlace::Value(value) => value,
258+
ValueOrPlace::Place(place) => state.get_idx(place, self.map()),
259+
};
260+
let FlatSet::Elem(ScalarTy(scalar, _)) = value else {
261+
// Do nothing if we don't know which branch will be taken.
262+
return TerminatorEdge::SwitchInt { discr, targets };
263+
};
264+
265+
let int = scalar.assert_int();
266+
let choice = int.assert_bits(int.size());
267+
TerminatorEdge::Single(targets.target_for_value(choice))
295268
}
296269
}
297270

0 commit comments

Comments
 (0)