Skip to content

Commit 3233fb1

Browse files
Extend dataflow framework to support arbitrary lattices
1 parent 9e45e90 commit 3233fb1

File tree

11 files changed

+738
-514
lines changed

11 files changed

+738
-514
lines changed

Diff for: compiler/rustc_mir/src/dataflow/framework/cursor.rs

+19-15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::borrow::Borrow;
44
use std::cmp::Ordering;
55

66
use rustc_index::bit_set::BitSet;
7+
use rustc_index::vec::Idx;
78
use rustc_middle::mir::{self, BasicBlock, Location};
89

910
use super::{Analysis, Direction, Effect, EffectIndex, Results};
@@ -26,7 +27,7 @@ where
2627
{
2728
body: &'mir mir::Body<'tcx>,
2829
results: R,
29-
state: BitSet<A::Idx>,
30+
state: A::Domain,
3031

3132
pos: CursorPosition,
3233

@@ -46,17 +47,16 @@ where
4647
{
4748
/// Returns a new cursor that can inspect `results`.
4849
pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self {
49-
let bits_per_block = results.borrow().entry_set_for_block(mir::START_BLOCK).domain_size();
50-
50+
let bottom_value = results.borrow().analysis.bottom_value(body);
5151
ResultsCursor {
5252
body,
5353
results,
5454

55-
// Initialize to an empty `BitSet` and set `state_needs_reset` to tell the cursor that
55+
// Initialize to the `bottom_value` and set `state_needs_reset` to tell the cursor that
5656
// it needs to reset to block entry before the first seek. The cursor position is
5757
// immaterial.
5858
state_needs_reset: true,
59-
state: BitSet::new_empty(bits_per_block),
59+
state: bottom_value,
6060
pos: CursorPosition::block_entry(mir::START_BLOCK),
6161

6262
#[cfg(debug_assertions)]
@@ -79,17 +79,10 @@ where
7979
}
8080

8181
/// Returns the dataflow state at the current location.
82-
pub fn get(&self) -> &BitSet<A::Idx> {
82+
pub fn get(&self) -> &A::Domain {
8383
&self.state
8484
}
8585

86-
/// Returns `true` if the dataflow state at the current location contains the given element.
87-
///
88-
/// Shorthand for `self.get().contains(elem)`
89-
pub fn contains(&self, elem: A::Idx) -> bool {
90-
self.state.contains(elem)
91-
}
92-
9386
/// Resets the cursor to hold the entry set for the given basic block.
9487
///
9588
/// For forward dataflow analyses, this is the dataflow state prior to the first statement.
@@ -99,7 +92,7 @@ where
9992
#[cfg(debug_assertions)]
10093
assert!(self.reachable_blocks.contains(block));
10194

102-
self.state.overwrite(&self.results.borrow().entry_set_for_block(block));
95+
self.state.clone_from(&self.results.borrow().entry_set_for_block(block));
10396
self.pos = CursorPosition::block_entry(block);
10497
self.state_needs_reset = false;
10598
}
@@ -207,12 +200,23 @@ where
207200
///
208201
/// This can be used, e.g., to apply the call return effect directly to the cursor without
209202
/// creating an extra copy of the dataflow state.
210-
pub fn apply_custom_effect(&mut self, f: impl FnOnce(&A, &mut BitSet<A::Idx>)) {
203+
pub fn apply_custom_effect(&mut self, f: impl FnOnce(&A, &mut A::Domain)) {
211204
f(&self.results.borrow().analysis, &mut self.state);
212205
self.state_needs_reset = true;
213206
}
214207
}
215208

209+
impl<'mir, 'tcx, A, R, T> ResultsCursor<'mir, 'tcx, A, R>
210+
where
211+
A: Analysis<'tcx, Domain = BitSet<T>>,
212+
T: Idx,
213+
R: Borrow<Results<'tcx, A>>,
214+
{
215+
pub fn contains(&self, elem: T) -> bool {
216+
self.get().contains(elem)
217+
}
218+
}
219+
216220
#[derive(Clone, Copy, Debug)]
217221
struct CursorPosition {
218222
block: BasicBlock,

Diff for: compiler/rustc_mir/src/dataflow/framework/direction.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub trait Direction {
1818
/// `effects.start()` must precede or equal `effects.end()` in this direction.
1919
fn apply_effects_in_range<A>(
2020
analysis: &A,
21-
state: &mut BitSet<A::Idx>,
21+
state: &mut A::Domain,
2222
block: BasicBlock,
2323
block_data: &mir::BasicBlockData<'tcx>,
2424
effects: RangeInclusive<EffectIndex>,
@@ -27,7 +27,7 @@ pub trait Direction {
2727

2828
fn apply_effects_in_block<A>(
2929
analysis: &A,
30-
state: &mut BitSet<A::Idx>,
30+
state: &mut A::Domain,
3131
block: BasicBlock,
3232
block_data: &mir::BasicBlockData<'tcx>,
3333
) where
@@ -55,9 +55,9 @@ pub trait Direction {
5555
tcx: TyCtxt<'tcx>,
5656
body: &mir::Body<'tcx>,
5757
dead_unwinds: Option<&BitSet<BasicBlock>>,
58-
exit_state: &mut BitSet<A::Idx>,
58+
exit_state: &mut A::Domain,
5959
block: (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
60-
propagate: impl FnMut(BasicBlock, &BitSet<A::Idx>),
60+
propagate: impl FnMut(BasicBlock, &A::Domain),
6161
) where
6262
A: Analysis<'tcx>;
6363
}
@@ -72,7 +72,7 @@ impl Direction for Backward {
7272

7373
fn apply_effects_in_block<A>(
7474
analysis: &A,
75-
state: &mut BitSet<A::Idx>,
75+
state: &mut A::Domain,
7676
block: BasicBlock,
7777
block_data: &mir::BasicBlockData<'tcx>,
7878
) where
@@ -112,7 +112,7 @@ impl Direction for Backward {
112112

113113
fn apply_effects_in_range<A>(
114114
analysis: &A,
115-
state: &mut BitSet<A::Idx>,
115+
state: &mut A::Domain,
116116
block: BasicBlock,
117117
block_data: &mir::BasicBlockData<'tcx>,
118118
effects: RangeInclusive<EffectIndex>,
@@ -224,9 +224,9 @@ impl Direction for Backward {
224224
_tcx: TyCtxt<'tcx>,
225225
body: &mir::Body<'tcx>,
226226
dead_unwinds: Option<&BitSet<BasicBlock>>,
227-
exit_state: &mut BitSet<A::Idx>,
227+
exit_state: &mut A::Domain,
228228
(bb, _bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
229-
mut propagate: impl FnMut(BasicBlock, &BitSet<A::Idx>),
229+
mut propagate: impl FnMut(BasicBlock, &A::Domain),
230230
) where
231231
A: Analysis<'tcx>,
232232
{
@@ -281,7 +281,7 @@ impl Direction for Forward {
281281

282282
fn apply_effects_in_block<A>(
283283
analysis: &A,
284-
state: &mut BitSet<A::Idx>,
284+
state: &mut A::Domain,
285285
block: BasicBlock,
286286
block_data: &mir::BasicBlockData<'tcx>,
287287
) where
@@ -321,7 +321,7 @@ impl Direction for Forward {
321321

322322
fn apply_effects_in_range<A>(
323323
analysis: &A,
324-
state: &mut BitSet<A::Idx>,
324+
state: &mut A::Domain,
325325
block: BasicBlock,
326326
block_data: &mir::BasicBlockData<'tcx>,
327327
effects: RangeInclusive<EffectIndex>,
@@ -428,9 +428,9 @@ impl Direction for Forward {
428428
tcx: TyCtxt<'tcx>,
429429
body: &mir::Body<'tcx>,
430430
dead_unwinds: Option<&BitSet<BasicBlock>>,
431-
exit_state: &mut BitSet<A::Idx>,
431+
exit_state: &mut A::Domain,
432432
(bb, bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
433-
mut propagate: impl FnMut(BasicBlock, &BitSet<A::Idx>),
433+
mut propagate: impl FnMut(BasicBlock, &A::Domain),
434434
) where
435435
A: Analysis<'tcx>,
436436
{
@@ -499,7 +499,7 @@ impl Direction for Forward {
499499
// MIR building adds discriminants to the `values` array in the same order as they
500500
// are yielded by `AdtDef::discriminants`. We rely on this to match each
501501
// discriminant in `values` to its corresponding variant in linear time.
502-
let mut tmp = BitSet::new_empty(exit_state.domain_size());
502+
let mut tmp = analysis.bottom_value(body);
503503
let mut discriminants = enum_def.discriminants(tcx);
504504
for (value, target) in values.iter().zip(targets.iter().copied()) {
505505
let (variant_idx, _) =
@@ -508,7 +508,7 @@ impl Direction for Forward {
508508
from that of `SwitchInt::values`",
509509
);
510510

511-
tmp.overwrite(exit_state);
511+
tmp.clone_from(exit_state);
512512
analysis.apply_discriminant_switch_effect(
513513
&mut tmp,
514514
bb,

0 commit comments

Comments
 (0)