From d4add5d52a87e0a1d45505a302d28a577bbe05c2 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 27 Nov 2017 15:08:11 +0100 Subject: [PATCH] Refactoring: pull bitvector initialization out from other parts of dataflow. This is meant to ease development of multi-stage dataflow analyses where the output from one analysis is used to initialize the state for the next; in such a context, you cannot start with `bottom_value` for all the bits. --- src/librustc_mir/dataflow/impls/borrows.rs | 4 ++-- src/librustc_mir/dataflow/impls/mod.rs | 12 +++++------ .../dataflow/impls/storage_liveness.rs | 2 +- src/librustc_mir/dataflow/mod.rs | 21 ++++++++----------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 25bc702764a3..eeb7f32c25c2 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -22,7 +22,7 @@ use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::{IndexVec}; -use dataflow::{BitDenotation, BlockSets, DataflowOperator}; +use dataflow::{BitDenotation, BlockSets, InitialFlow}; pub use dataflow::indexes::BorrowIndex; use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::ToRegionVid; @@ -339,7 +339,7 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for Borrows<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = no Rvalue::Refs are active by default diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 033d2a3212f8..106a88e703c7 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -23,7 +23,7 @@ use util::elaborate_drops::DropFlagState; use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex}; use super::move_paths::{LookupResult, InitKind}; -use super::{BitDenotation, BlockSets, DataflowOperator}; +use super::{BitDenotation, BlockSets, InitialFlow}; use super::drop_flag_effects_for_function_entry; use super::drop_flag_effects_for_location; @@ -702,35 +702,35 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedLvals<'a, 'gcx, 'tcx> { // propagating, or you start at all-ones and then use Intersect as // your merge when propagating. -impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for MaybeInitializedLvals<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = uninitialized } } -impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for MaybeUninitializedLvals<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = initialized (start_block_effect counters this at outset) } } -impl<'a, 'gcx, 'tcx> DataflowOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { true // bottom = initialized (start_block_effect counters this at outset) } } -impl<'a, 'gcx, 'tcx> DataflowOperator for MovingOutStatements<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for MovingOutStatements<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = no loans in scope by default } } -impl<'a, 'gcx, 'tcx> DataflowOperator for EverInitializedLvals<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedLvals<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = no initialized variables by default diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 9e5a71683781..dea61542ac4e 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> { } } -impl<'a, 'tcx> DataflowOperator for MaybeStorageLive<'a, 'tcx> { +impl<'a, 'tcx> InitialFlow for MaybeStorageLive<'a, 'tcx> { #[inline] fn bottom_value() -> bool { false // bottom = dead diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 8624cbbf50ab..fe152b46c1d5 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -127,7 +127,7 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, bd: BD, p: P) -> DataflowResults - where BD: BitDenotation, + where BD: BitDenotation + InitialFlow, P: Fn(&BD, BD::Idx) -> DebugFormatted { let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option { @@ -176,7 +176,6 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation }; while propcx.changed { propcx.changed = false; - propcx.reset(&mut temp); propcx.walk_cfg(&mut temp); } } @@ -212,13 +211,6 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation { - fn reset(&mut self, bits: &mut IdxSet) { - let e = if BD::bottom_value() {!0} else {0}; - for b in bits.words_mut() { - *b = e; - } - } - fn walk_cfg(&mut self, in_out: &mut IdxSet) { let mir = self.builder.mir; for (bb_idx, bb_data) in mir.basic_blocks().iter().enumerate() { @@ -554,12 +546,17 @@ impl AllSets { } /// Parameterization for the precise form of data flow that is used. -pub trait DataflowOperator: BitwiseOperator { +/// `InitialFlow` handles initializing the bitvectors before any +/// code is inspected by the analysis. Analyses that need more nuanced +/// initialization (e.g. they need to consult the results of some other +/// dataflow analysis to set up the initial bitvectors) should not +/// implement this. +pub trait InitialFlow { /// Specifies the initial value for each bit in the `on_entry` set fn bottom_value() -> bool; } -pub trait BitDenotation: DataflowOperator { +pub trait BitDenotation: BitwiseOperator { /// Specifies what index type is used to access the bitvector. type Idx: Idx; @@ -642,7 +639,7 @@ impl<'a, 'gcx, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation pub fn new(_tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, dead_unwinds: &'a IdxSet, - denotation: D) -> Self { + denotation: D) -> Self where D: InitialFlow { let bits_per_block = denotation.bits_per_block(); let usize_bits = mem::size_of::() * 8; let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;