diff options
| author | Laurențiu Nicola <lnicola@dend.ro> | 2024-10-17 10:04:49 +0300 |
|---|---|---|
| committer | Laurențiu Nicola <lnicola@dend.ro> | 2024-10-17 10:04:49 +0300 |
| commit | 1b7cd2bed6efac6ecbe78e9006a9f60878d4a450 (patch) | |
| tree | ddd444e2cdf64d53dc4d522ca38f1a5e631623a2 /compiler/rustc_mir_dataflow/src/framework | |
| parent | aff69ccfb2b7da9374dd47f13e626a980ce8338a (diff) | |
| parent | dd5127615ad626741a1116d022cf784637ac05df (diff) | |
| download | rust-1b7cd2bed6efac6ecbe78e9006a9f60878d4a450.tar.gz rust-1b7cd2bed6efac6ecbe78e9006a9f60878d4a450.zip | |
Merge from rust-lang/rust
Diffstat (limited to 'compiler/rustc_mir_dataflow/src/framework')
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/framework/cursor.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/framework/direction.rs | 66 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/framework/engine.rs | 89 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/framework/mod.rs | 265 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/framework/tests.rs | 12 |
5 files changed, 54 insertions, 389 deletions
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index 7cfaef22689..5ebb343f4e1 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -7,7 +7,6 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::{self, BasicBlock, Location}; use super::{Analysis, Direction, Effect, EffectIndex, Results}; -use crate::framework::BitSetExt; /// Allows random access inspection of the results of a dataflow analysis. /// @@ -221,16 +220,6 @@ where } } -impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> -where - A: crate::GenKillAnalysis<'tcx>, - A::Domain: BitSetExt<A::Idx>, -{ - pub fn contains(&self, elem: A::Idx) -> bool { - self.get().contains(elem) - } -} - #[derive(Clone, Copy, Debug)] struct CursorPosition { block: BasicBlock, diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 88a9a78f8ad..3e01f0512c4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::{ }; use super::visitor::{ResultsVisitable, ResultsVisitor}; -use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget}; +use super::{Analysis, Effect, EffectIndex, SwitchIntTarget}; pub trait Direction { const IS_FORWARD: bool; @@ -29,19 +29,10 @@ pub trait Direction { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>, ) -> TerminatorEdges<'mir, 'tcx> where A: Analysis<'tcx>; - fn gen_kill_statement_effects_in_block<'tcx, A>( - analysis: &mut A, - trans: &mut GenKillSet<A::Idx>, - block: BasicBlock, - block_data: &mir::BasicBlockData<'tcx>, - ) where - A: GenKillAnalysis<'tcx>; - fn visit_results_in_block<'mir, 'tcx, D, R>( state: &mut D, block: BasicBlock, @@ -73,7 +64,6 @@ impl Direction for Backward { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>, ) -> TerminatorEdges<'mir, 'tcx> where A: Analysis<'tcx>, @@ -82,31 +72,12 @@ impl Direction for Backward { let location = Location { block, statement_index: block_data.statements.len() }; analysis.apply_before_terminator_effect(state, terminator, location); let edges = analysis.apply_terminator_effect(state, terminator, location); - if let Some(statement_effect) = statement_effect { - statement_effect(block, state) - } else { - for (statement_index, statement) in block_data.statements.iter().enumerate().rev() { - let location = Location { block, statement_index }; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); - } - } - edges - } - - fn gen_kill_statement_effects_in_block<'tcx, A>( - analysis: &mut A, - trans: &mut GenKillSet<A::Idx>, - block: BasicBlock, - block_data: &mir::BasicBlockData<'tcx>, - ) where - A: GenKillAnalysis<'tcx>, - { for (statement_index, statement) in block_data.statements.iter().enumerate().rev() { let location = Location { block, statement_index }; - analysis.before_statement_effect(trans, statement, location); - analysis.statement_effect(trans, statement, location); + analysis.apply_before_statement_effect(state, statement, location); + analysis.apply_statement_effect(state, statement, location); } + edges } fn apply_effects_in_range<'tcx, A>( @@ -330,42 +301,21 @@ impl Direction for Forward { state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>, ) -> TerminatorEdges<'mir, 'tcx> where A: Analysis<'tcx>, { - if let Some(statement_effect) = statement_effect { - statement_effect(block, state) - } else { - for (statement_index, statement) in block_data.statements.iter().enumerate() { - let location = Location { block, statement_index }; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); - } + for (statement_index, statement) in block_data.statements.iter().enumerate() { + let location = Location { block, statement_index }; + analysis.apply_before_statement_effect(state, statement, location); + analysis.apply_statement_effect(state, statement, location); } - let terminator = block_data.terminator(); let location = Location { block, statement_index: block_data.statements.len() }; analysis.apply_before_terminator_effect(state, terminator, location); analysis.apply_terminator_effect(state, terminator, location) } - fn gen_kill_statement_effects_in_block<'tcx, A>( - analysis: &mut A, - trans: &mut GenKillSet<A::Idx>, - block: BasicBlock, - block_data: &mir::BasicBlockData<'tcx>, - ) where - A: GenKillAnalysis<'tcx>, - { - for (statement_index, statement) in block_data.statements.iter().enumerate() { - let location = Location { block, statement_index }; - analysis.before_statement_effect(trans, statement, location); - analysis.statement_effect(trans, statement, location); - } - } - fn apply_effects_in_range<'tcx, A>( analysis: &mut A, state: &mut A::Domain, diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 9d50e57d668..cbd1083d037 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use rustc_data_structures::work_queue::WorkQueue; use rustc_hir::def_id::DefId; -use rustc_index::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::mir::{self, BasicBlock, create_dump_file, dump_enabled, traversal}; use rustc_middle::ty::TyCtxt; @@ -16,15 +16,13 @@ use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::DebugWithContext; use super::{ - Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, GenKillSet, JoinSemiLattice, - ResultsCursor, ResultsVisitor, graphviz, visit_results, + Analysis, Direction, JoinSemiLattice, ResultsCursor, ResultsVisitor, graphviz, visit_results, }; use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; -use crate::framework::BitSetExt; -type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>; +type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>; /// A dataflow analysis that has converged to fixpoint. #[derive(Clone)] @@ -82,53 +80,6 @@ where entry_sets: IndexVec<BasicBlock, A::Domain>, pass_name: Option<&'static str>, analysis: A, - - /// Cached, cumulative transfer functions for each block. - // - // FIXME(ecstaticmorse): This boxed `Fn` trait object is invoked inside a tight loop for - // gen/kill problems on cyclic CFGs. This is not ideal, but it doesn't seem to degrade - // performance in practice. I've tried a few ways to avoid this, but they have downsides. See - // the message for the commit that added this FIXME for more information. - apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, -} - -impl<'mir, 'tcx, A, D, T> Engine<'mir, 'tcx, A> -where - A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, - D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>, - T: Idx, -{ - /// Creates a new `Engine` to solve a gen-kill dataflow problem. - pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, mut analysis: A) -> Self { - // If there are no back-edges in the control-flow graph, we only ever need to apply the - // transfer function for each block exactly once (assuming that we process blocks in RPO). - // - // In this case, there's no need to compute the block transfer functions ahead of time. - if !body.basic_blocks.is_cfg_cyclic() { - return Self::new(tcx, body, analysis, None); - } - - // Otherwise, compute and store the cumulative transfer function for each block. - - let identity = GenKillSet::identity(analysis.domain_size(body)); - let mut trans_for_block = IndexVec::from_elem(identity, &body.basic_blocks); - - for (block, block_data) in body.basic_blocks.iter_enumerated() { - let trans = &mut trans_for_block[block]; - A::Direction::gen_kill_statement_effects_in_block( - &mut analysis, - trans, - block, - block_data, - ); - } - - let apply_trans = Box::new(move |bb: BasicBlock, state: &mut A::Domain| { - trans_for_block[bb].apply(state); - }); - - Self::new(tcx, body, analysis, Some(apply_trans as Box<_>)) - } } impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A> @@ -138,19 +89,7 @@ where { /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer /// function. - /// - /// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for - /// better performance. - pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self { - Self::new(tcx, body, analysis, None) - } - - fn new( - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - analysis: A, - apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, - ) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self { let mut entry_sets = IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len()); analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); @@ -160,7 +99,7 @@ where bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); } - Engine { analysis, tcx, body, pass_name: None, entry_sets, apply_statement_trans_for_block } + Engine { analysis, tcx, body, pass_name: None, entry_sets } } /// Adds an identifier to the graphviz output for this particular run of a dataflow analysis. @@ -177,14 +116,7 @@ where where A::Domain: DebugWithContext<A>, { - let Engine { - mut analysis, - body, - mut entry_sets, - tcx, - apply_statement_trans_for_block, - pass_name, - } = self; + let Engine { mut analysis, body, mut entry_sets, tcx, pass_name } = self; let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len()); @@ -213,13 +145,8 @@ where state.clone_from(&entry_sets[bb]); // Apply the block transfer function, using the cached one if it exists. - let edges = A::Direction::apply_effects_in_block( - &mut analysis, - &mut state, - bb, - bb_data, - apply_statement_trans_for_block.as_deref(), - ); + let edges = + A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data); A::Direction::join_state_into_successors_of( &mut analysis, diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index d0472e35fe0..959f1ea5340 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -1,9 +1,11 @@ //! A framework that can express both [gen-kill] and generic dataflow problems. //! -//! To use this framework, implement either the [`Analysis`] or the -//! [`GenKillAnalysis`] trait. If your transfer function can be expressed with only gen/kill -//! operations, prefer `GenKillAnalysis` since it will run faster while iterating to fixpoint. The -//! `impls` module contains several examples of gen/kill dataflow analyses. +//! To use this framework, implement the [`Analysis`] trait. There used to be a `GenKillAnalysis` +//! alternative trait for gen-kill analyses that would pre-compute the transfer function for each +//! block. It was intended as an optimization, but it ended up not being any faster than +//! `Analysis`. +//! +//! The `impls` module contains several examples of dataflow analyses. //! //! Create an `Engine` for your analysis using the `into_engine` method on the `Analysis` trait, //! then call `iterate_to_fixpoint`. From there, you can use a `ResultsCursor` to inspect the @@ -87,11 +89,26 @@ impl<T: Idx> BitSetExt<T> for ChunkedBitSet<T> { } } -/// Defines the domain of a dataflow problem. +/// A dataflow problem with an arbitrarily complex transfer function. +/// +/// This trait specifies the lattice on which this analysis operates (the domain), its +/// initial value at the entry point of each basic block, and various operations. +/// +/// # Convergence +/// +/// When implementing this trait it's possible to choose a transfer function such that the analysis +/// does not reach fixpoint. To guarantee convergence, your transfer functions must maintain the +/// following invariant: +/// +/// > If the dataflow state **before** some point in the program changes to be greater +/// than the prior state **before** that point, the dataflow state **after** that point must +/// also change to be greater than the prior state **after** that point. /// -/// This trait specifies the lattice on which this analysis operates (the domain) as well as its -/// initial value at the entry point of each basic block. -pub trait AnalysisDomain<'tcx> { +/// This invariant guarantees that the dataflow state at a given point in the program increases +/// monotonically until fixpoint is reached. Note that this monotonicity requirement only applies +/// to the same point in the program at different points in time. The dataflow state at a given +/// point in the program may or may not be greater than the state at any preceding point. +pub trait Analysis<'tcx> { /// The type that holds the dataflow state at any given point in the program. type Domain: Clone + JoinSemiLattice; @@ -116,25 +133,7 @@ pub trait AnalysisDomain<'tcx> { // block where control flow could exit the MIR body (e.g., those terminated with `return` or // `resume`). It's not obvious how to handle `yield` points in coroutines, however. fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain); -} -/// A dataflow problem with an arbitrarily complex transfer function. -/// -/// # Convergence -/// -/// When implementing this trait directly (not via [`GenKillAnalysis`]), it's possible to choose a -/// transfer function such that the analysis does not reach fixpoint. To guarantee convergence, -/// your transfer functions must maintain the following invariant: -/// -/// > If the dataflow state **before** some point in the program changes to be greater -/// than the prior state **before** that point, the dataflow state **after** that point must -/// also change to be greater than the prior state **after** that point. -/// -/// This invariant guarantees that the dataflow state at a given point in the program increases -/// monotonically until fixpoint is reached. Note that this monotonicity requirement only applies -/// to the same point in the program at different points in time. The dataflow state at a given -/// point in the program may or may not be greater than the state at any preceding point. -pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// Updates the current dataflow state with the effect of evaluating a statement. fn apply_statement_effect( &mut self, @@ -165,10 +164,12 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// initialized here. fn apply_terminator_effect<'mir>( &mut self, - state: &mut Self::Domain, + _state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, - location: Location, - ) -> TerminatorEdges<'mir, 'tcx>; + _location: Location, + ) -> TerminatorEdges<'mir, 'tcx> { + terminator.edges() + } /// Updates the current dataflow state with an effect that occurs immediately *before* the /// given terminator. @@ -193,10 +194,11 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// edges. fn apply_call_return_effect( &mut self, - state: &mut Self::Domain, - block: BasicBlock, - return_places: CallReturnPlaces<'_, 'tcx>, - ); + _state: &mut Self::Domain, + _block: BasicBlock, + _return_places: CallReturnPlaces<'_, 'tcx>, + ) { + } /// Updates the current dataflow state with the effect of taking a particular branch in a /// `SwitchInt` terminator. @@ -223,9 +225,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// Creates an `Engine` to find the fixpoint for this dataflow problem. /// - /// You shouldn't need to override this outside this module, since the combination of the - /// default impl and the one for all `A: GenKillAnalysis` will do the right thing. - /// Its purpose is to enable method chaining like so: + /// You shouldn't need to override this. Its purpose is to enable method chaining like so: /// /// ```ignore (cross-crate-imports) /// let results = MyAnalysis::new(tcx, body) @@ -242,164 +242,11 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { where Self: Sized, { - Engine::new_generic(tcx, body, self) - } -} - -/// A gen/kill dataflow problem. -/// -/// Each method in this trait has a corresponding one in `Analysis`. However, the first two methods -/// here only allow modification of the dataflow state via "gen" and "kill" operations. By defining -/// transfer functions for each statement in this way, the transfer function for an entire basic -/// block can be computed efficiently. The remaining methods match up with `Analysis` exactly. -/// -/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis` via a blanket -/// impl below. -pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { - type Idx: Idx; - - fn domain_size(&self, body: &mir::Body<'tcx>) -> usize; - - /// See `Analysis::apply_statement_effect`. Note how the second arg differs. - fn statement_effect( - &mut self, - trans: &mut impl GenKill<Self::Idx>, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - /// See `Analysis::apply_before_statement_effect`. Note how the second arg - /// differs. - fn before_statement_effect( - &mut self, - _trans: &mut impl GenKill<Self::Idx>, - _statement: &mir::Statement<'tcx>, - _location: Location, - ) { - } - - /// See `Analysis::apply_terminator_effect`. - fn terminator_effect<'mir>( - &mut self, - trans: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, - location: Location, - ) -> TerminatorEdges<'mir, 'tcx>; - - /// See `Analysis::apply_before_terminator_effect`. - fn before_terminator_effect( - &mut self, - _trans: &mut Self::Domain, - _terminator: &mir::Terminator<'tcx>, - _location: Location, - ) { - } - - /* Edge-specific effects */ - - /// See `Analysis::apply_call_return_effect`. - fn call_return_effect( - &mut self, - trans: &mut Self::Domain, - block: BasicBlock, - return_places: CallReturnPlaces<'_, 'tcx>, - ); - - /// See `Analysis::apply_switch_int_edge_effects`. - fn switch_int_edge_effects<G: GenKill<Self::Idx>>( - &mut self, - _block: BasicBlock, - _discr: &mir::Operand<'tcx>, - _edge_effects: &mut impl SwitchIntEdgeEffects<G>, - ) { - } -} - -// Blanket impl: any impl of `GenKillAnalysis` automatically impls `Analysis`. -impl<'tcx, A> Analysis<'tcx> for A -where - A: GenKillAnalysis<'tcx>, - A::Domain: GenKill<A::Idx> + BitSetExt<A::Idx>, -{ - fn apply_statement_effect( - &mut self, - state: &mut A::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ) { - self.statement_effect(state, statement, location); - } - - fn apply_before_statement_effect( - &mut self, - state: &mut A::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ) { - self.before_statement_effect(state, statement, location); - } - - fn apply_terminator_effect<'mir>( - &mut self, - state: &mut A::Domain, - terminator: &'mir mir::Terminator<'tcx>, - location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { - self.terminator_effect(state, terminator, location) - } - - fn apply_before_terminator_effect( - &mut self, - state: &mut A::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ) { - self.before_terminator_effect(state, terminator, location); - } - - /* Edge-specific effects */ - - fn apply_call_return_effect( - &mut self, - state: &mut A::Domain, - block: BasicBlock, - return_places: CallReturnPlaces<'_, 'tcx>, - ) { - self.call_return_effect(state, block, return_places); - } - - fn apply_switch_int_edge_effects( - &mut self, - block: BasicBlock, - discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects<A::Domain>, - ) { - self.switch_int_edge_effects(block, discr, edge_effects); - } - - /* Extension methods */ - #[inline] - fn into_engine<'mir>( - self, - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - ) -> Engine<'mir, 'tcx, Self> - where - Self: Sized, - { - Engine::new_gen_kill(tcx, body, self) + Engine::new(tcx, body, self) } } /// The legal operations for a transfer function in a gen/kill problem. -/// -/// This abstraction exists because there are two different contexts in which we call the methods in -/// `GenKillAnalysis`. Sometimes we need to store a single transfer function that can be efficiently -/// applied multiple times, such as when computing the cumulative transfer function for each block. -/// These cases require a `GenKillSet`, which in turn requires two `BitSet`s of storage. Oftentimes, -/// however, we only need to apply an effect once. In *these* cases, it is more efficient to pass the -/// `BitSet` representing the state vector directly into the `*_effect` methods as opposed to -/// building up a `GenKillSet` and then throwing it away. pub trait GenKill<T> { /// Inserts `elem` into the state vector. fn gen_(&mut self, elem: T); @@ -422,44 +269,6 @@ pub trait GenKill<T> { } } -/// Stores a transfer function for a gen/kill problem. -/// -/// Calling `gen_`/`kill` on a `GenKillSet` will "build up" a transfer function so that it can be -/// applied multiple times efficiently. When there are multiple calls to `gen_` and/or `kill` for -/// the same element, the most recent one takes precedence. -#[derive(Clone)] -pub struct GenKillSet<T> { - gen_: HybridBitSet<T>, - kill: HybridBitSet<T>, -} - -impl<T: Idx> GenKillSet<T> { - /// Creates a new transfer function that will leave the dataflow state unchanged. - pub fn identity(universe: usize) -> Self { - GenKillSet { - gen_: HybridBitSet::new_empty(universe), - kill: HybridBitSet::new_empty(universe), - } - } - - pub fn apply(&self, state: &mut impl BitSetExt<T>) { - state.union(&self.gen_); - state.subtract(&self.kill); - } -} - -impl<T: Idx> GenKill<T> for GenKillSet<T> { - fn gen_(&mut self, elem: T) { - self.gen_.insert(elem); - self.kill.remove(elem); - } - - fn kill(&mut self, elem: T) { - self.kill.insert(elem); - self.gen_.remove(elem); - } -} - impl<T: Idx> GenKill<T> for BitSet<T> { fn gen_(&mut self, elem: T) { self.insert(elem); diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 1861f4cffc7..14fb6dfb50c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -154,7 +154,7 @@ impl<D: Direction> MockAnalysis<'_, D> { } } -impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { +impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { type Domain = BitSet<usize>; type Direction = D; @@ -167,9 +167,7 @@ impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) { unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint"); } -} -impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { fn apply_statement_effect( &mut self, state: &mut Self::Domain, @@ -210,14 +208,6 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { let idx = self.effect(Effect::Before.at_index(location.statement_index)); assert!(state.insert(idx)); } - - fn apply_call_return_effect( - &mut self, - _state: &mut Self::Domain, - _block: BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
