Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 12 additions & 20 deletions compiler/rustc_mir_dataflow/src/framework/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,28 +195,20 @@ where
debug_assert_eq!(target.block, self.pos.block);

let block_data = &self.body[target.block];
#[rustfmt::skip]
let next_effect = if A::Direction::IS_FORWARD {
self.pos.curr_effect_index.map_or_else(
|| Effect::Early.at_index(0),
EffectIndex::next_in_forward_order,
)
} else {
self.pos.curr_effect_index.map_or_else(
|| Effect::Early.at_index(block_data.statements.len()),
EffectIndex::next_in_backward_order,
)
};

let next_effect = self.pos.curr_effect_index.map_or_else(
|| A::Direction::first_index(block_data),
|idx| A::Direction::next_index(idx),
);
let target_effect_index = effect.at_index(target.statement_index);

A::Direction::apply_effects_in_range(
&self.results.analysis,
&mut self.state,
target.block,
block_data,
next_effect..=target_effect_index,
);
let mut idx = next_effect;
loop {
self.results.analysis.apply_effect(&mut self.state, target.block, block_data, idx);
if idx == target_effect_index {
break;
}
idx = A::Direction::next_index(idx);
}

self.pos =
CursorPosition { block: target.block, curr_effect_index: Some(target_effect_index) };
Expand Down
205 changes: 31 additions & 174 deletions compiler/rustc_mir_dataflow/src/framework/direction.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::ops::RangeInclusive;

use rustc_middle::bug;
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};

Expand All @@ -10,6 +8,13 @@ pub trait Direction {
const IS_FORWARD: bool;
const IS_BACKWARD: bool = !Self::IS_FORWARD;

/// Returns the first statement index for this direction. (0 when going forward and
/// `statements.len()` when going backward.)
fn first_index(block_data: &mir::BasicBlockData<'_>) -> EffectIndex;

/// Returns the next index for this direction.
fn next_index(idx: EffectIndex) -> EffectIndex;

/// Called by `iterate_to_fixpoint` during initial analysis computation.
fn apply_effects_in_block<'mir, 'tcx, A>(
analysis: &A,
Expand All @@ -21,19 +26,6 @@ pub trait Direction {
) where
A: Analysis<'tcx>;

/// Called by `ResultsCursor` to recompute the domain value for a location
/// in a basic block. Applies all effects between the given `EffectIndex`s.
///
/// `effects.start()` must precede or equal `effects.end()` in this direction.
fn apply_effects_in_range<'tcx, A>(
analysis: &A,
state: &mut A::Domain,
block: BasicBlock,
block_data: &mir::BasicBlockData<'tcx>,
effects: RangeInclusive<EffectIndex>,
) where
A: Analysis<'tcx>;

/// Called by `ResultsVisitor` to recompute the analysis domain values for
/// all locations in a basic block (starting from `entry_state` and to
/// visit them with `vis`.
Expand All @@ -53,6 +45,18 @@ pub struct Backward;
impl Direction for Backward {
const IS_FORWARD: bool = false;

fn first_index(block_data: &mir::BasicBlockData<'_>) -> EffectIndex {
Effect::Early.at_index(block_data.statements.len())
}

/// Returns the next index for this direction.
fn next_index(idx: EffectIndex) -> EffectIndex {
match idx.effect {
Effect::Early => Effect::Primary.at_index(idx.statement_index),
Effect::Primary => Effect::Early.at_index(idx.statement_index - 1),
}
}

fn apply_effects_in_block<'mir, 'tcx, A>(
analysis: &A,
body: &mir::Body<'tcx>,
Expand Down Expand Up @@ -128,83 +132,6 @@ impl Direction for Backward {
}
}

fn apply_effects_in_range<'tcx, A>(
analysis: &A,
state: &mut A::Domain,
block: BasicBlock,
block_data: &mir::BasicBlockData<'tcx>,
effects: RangeInclusive<EffectIndex>,
) where
A: Analysis<'tcx>,
{
let (from, to) = (*effects.start(), *effects.end());
let terminator_index = block_data.statements.len();

assert!(from.statement_index <= terminator_index);
assert!(!to.precedes_in_backward_order(from));

// Handle the statement (or terminator) at `from`.

let next_effect = match from.effect {
// If we need to apply the terminator effect in all or in part, do so now.
_ if from.statement_index == terminator_index => {
let location = Location { block, statement_index: from.statement_index };
let terminator = block_data.terminator();

if from.effect == Effect::Early {
analysis.apply_early_terminator_effect(state, terminator, location);
if to == Effect::Early.at_index(terminator_index) {
return;
}
}

analysis.apply_primary_terminator_effect(state, terminator, location);
if to == Effect::Primary.at_index(terminator_index) {
return;
}

// If `from.statement_index` is `0`, we will have hit one of the earlier comparisons
// with `to`.
from.statement_index - 1
}

Effect::Primary => {
let location = Location { block, statement_index: from.statement_index };
let statement = &block_data.statements[from.statement_index];

analysis.apply_primary_statement_effect(state, statement, location);
if to == Effect::Primary.at_index(from.statement_index) {
return;
}

from.statement_index - 1
}

Effect::Early => from.statement_index,
};

// Handle all statements between `first_unapplied_idx` and `to.statement_index`.

for statement_index in (to.statement_index..next_effect).rev().map(|i| i + 1) {
let location = Location { block, statement_index };
let statement = &block_data.statements[statement_index];
analysis.apply_early_statement_effect(state, statement, location);
analysis.apply_primary_statement_effect(state, statement, location);
}

// Handle the statement at `to`.

let location = Location { block, statement_index: to.statement_index };
let statement = &block_data.statements[to.statement_index];
analysis.apply_early_statement_effect(state, statement, location);

if to.effect == Effect::Early {
return;
}

analysis.apply_primary_statement_effect(state, statement, location);
}

fn visit_results_in_block<'mir, 'tcx, A>(
analysis: &A,
state: &mut A::Domain,
Expand All @@ -214,8 +141,6 @@ impl Direction for Backward {
) where
A: Analysis<'tcx>,
{
vis.visit_block_end(state);

let loc = Location { block, statement_index: block_data.statements.len() };
let term = block_data.terminator();
analysis.apply_early_terminator_effect(state, term, loc);
Expand All @@ -230,8 +155,6 @@ impl Direction for Backward {
analysis.apply_primary_statement_effect(state, stmt, loc);
vis.visit_after_primary_statement_effect(analysis, state, stmt, loc);
}

vis.visit_block_start(state);
}
}

Expand All @@ -241,6 +164,18 @@ pub struct Forward;
impl Direction for Forward {
const IS_FORWARD: bool = true;

fn first_index(_block_data: &mir::BasicBlockData<'_>) -> EffectIndex {
Effect::Early.at_index(0)
}

/// Returns the next index for this direction.
fn next_index(idx: EffectIndex) -> EffectIndex {
match idx.effect {
Effect::Early => Effect::Primary.at_index(idx.statement_index),
Effect::Primary => Effect::Early.at_index(idx.statement_index + 1),
}
}

fn apply_effects_in_block<'mir, 'tcx, A>(
analysis: &A,
body: &mir::Body<'tcx>,
Expand Down Expand Up @@ -310,80 +245,6 @@ impl Direction for Forward {
}
}

fn apply_effects_in_range<'tcx, A>(
analysis: &A,
state: &mut A::Domain,
block: BasicBlock,
block_data: &mir::BasicBlockData<'tcx>,
effects: RangeInclusive<EffectIndex>,
) where
A: Analysis<'tcx>,
{
let (from, to) = (*effects.start(), *effects.end());
let terminator_index = block_data.statements.len();

assert!(to.statement_index <= terminator_index);
assert!(!to.precedes_in_forward_order(from));

// If we have applied the before affect of the statement or terminator at `from` but not its
// after effect, do so now and start the loop below from the next statement.

let first_unapplied_index = match from.effect {
Effect::Early => from.statement_index,

Effect::Primary if from.statement_index == terminator_index => {
debug_assert_eq!(from, to);

let location = Location { block, statement_index: terminator_index };
let terminator = block_data.terminator();
analysis.apply_primary_terminator_effect(state, terminator, location);
return;
}

Effect::Primary => {
let location = Location { block, statement_index: from.statement_index };
let statement = &block_data.statements[from.statement_index];
analysis.apply_primary_statement_effect(state, statement, location);

// If we only needed to apply the after effect of the statement at `idx`, we are
// done.
if from == to {
return;
}

from.statement_index + 1
}
};

// Handle all statements between `from` and `to` whose effects must be applied in full.

for statement_index in first_unapplied_index..to.statement_index {
let location = Location { block, statement_index };
let statement = &block_data.statements[statement_index];
analysis.apply_early_statement_effect(state, statement, location);
analysis.apply_primary_statement_effect(state, statement, location);
}

// Handle the statement or terminator at `to`.

let location = Location { block, statement_index: to.statement_index };
if to.statement_index == terminator_index {
let terminator = block_data.terminator();
analysis.apply_early_terminator_effect(state, terminator, location);

if to.effect == Effect::Primary {
analysis.apply_primary_terminator_effect(state, terminator, location);
}
} else {
let statement = &block_data.statements[to.statement_index];
analysis.apply_early_statement_effect(state, statement, location);

if to.effect == Effect::Primary {
analysis.apply_primary_statement_effect(state, statement, location);
}
}
}

fn visit_results_in_block<'mir, 'tcx, A>(
analysis: &A,
state: &mut A::Domain,
Expand All @@ -393,8 +254,6 @@ impl Direction for Forward {
) where
A: Analysis<'tcx>,
{
vis.visit_block_start(state);

for (statement_index, stmt) in block_data.statements.iter().enumerate() {
let loc = Location { block, statement_index };
analysis.apply_early_statement_effect(state, stmt, loc);
Expand All @@ -409,7 +268,5 @@ impl Direction for Forward {
vis.visit_after_early_terminator_effect(analysis, state, term, loc);
analysis.apply_primary_terminator_effect(state, term, loc);
vis.visit_after_primary_terminator_effect(analysis, state, term, loc);

vis.visit_block_end(state);
}
}
16 changes: 2 additions & 14 deletions compiler/rustc_mir_dataflow/src/framework/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ struct StateDiffCollector<D> {
after: Vec<String>,
}

impl<D> StateDiffCollector<D> {
impl<D: Clone> StateDiffCollector<D> {
fn run<'tcx, A>(
body: &Body<'tcx>,
block: BasicBlock,
Expand All @@ -645,7 +645,7 @@ impl<D> StateDiffCollector<D> {
D: DebugWithContext<A>,
{
let mut collector = StateDiffCollector {
prev_state: results.analysis.bottom_value(body),
prev_state: results.entry_states[block].clone(),
after: vec![],
before: (style == OutputStyle::BeforeAndAfter).then_some(vec![]),
};
Expand All @@ -660,18 +660,6 @@ where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
{
fn visit_block_start(&mut self, state: &A::Domain) {
if A::Direction::IS_FORWARD {
self.prev_state.clone_from(state);
}
}

fn visit_block_end(&mut self, state: &A::Domain) {
if A::Direction::IS_BACKWARD {
self.prev_state.clone_from(state);
}
}

fn visit_after_early_statement_effect(
&mut self,
analysis: &A,
Expand Down
Loading
Loading