diff options
| author | Samuel E. Moelius III <sam@moeli.us> | 2022-03-25 21:11:49 -0400 |
|---|---|---|
| committer | Samuel E. Moelius III <sam@moeli.us> | 2022-03-26 08:01:51 -0400 |
| commit | 37ebd47ddb1398c7b0f19aeb888417fbcf2d5992 (patch) | |
| tree | 1f53942b70d5523b4dc8c9c4b2225989c9601e90 /compiler/rustc_middle | |
| parent | ee7413b94cd0f953518ad73f37cac28feb6e8d52 (diff) | |
| download | rust-37ebd47ddb1398c7b0f19aeb888417fbcf2d5992.tar.gz rust-37ebd47ddb1398c7b0f19aeb888417fbcf2d5992.zip | |
Address review comments
* Add lazily computed `switch_sources` data structure * Don't assume a target has only one associated value
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/switch_sources.rs | 82 |
2 files changed, 95 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index a5468b3f4f2..455387901b6 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -45,6 +45,7 @@ use std::{iter, mem, option}; use self::graph_cyclic_cache::GraphIsCyclicCache; use self::predecessors::{PredecessorCache, Predecessors}; pub use self::query::*; +use self::switch_sources::{SwitchSourceCache, SwitchSources}; pub mod coverage; mod generic_graph; @@ -58,6 +59,7 @@ mod predecessors; pub mod pretty; mod query; pub mod spanview; +mod switch_sources; pub mod tcx; pub mod terminator; pub use terminator::*; @@ -284,6 +286,7 @@ pub struct Body<'tcx> { pub is_polymorphic: bool, predecessor_cache: PredecessorCache, + switch_source_cache: SwitchSourceCache, is_cyclic: GraphIsCyclicCache, pub tainted_by_errors: Option<ErrorGuaranteed>, @@ -332,6 +335,7 @@ impl<'tcx> Body<'tcx> { required_consts: Vec::new(), is_polymorphic: false, predecessor_cache: PredecessorCache::new(), + switch_source_cache: SwitchSourceCache::new(), is_cyclic: GraphIsCyclicCache::new(), tainted_by_errors, }; @@ -360,6 +364,7 @@ impl<'tcx> Body<'tcx> { var_debug_info: Vec::new(), is_polymorphic: false, predecessor_cache: PredecessorCache::new(), + switch_source_cache: SwitchSourceCache::new(), is_cyclic: GraphIsCyclicCache::new(), tainted_by_errors: None, }; @@ -380,6 +385,7 @@ impl<'tcx> Body<'tcx> { // FIXME: Use a finer-grained API for this, so only transformations that alter terminators // invalidate the caches. self.predecessor_cache.invalidate(); + self.switch_source_cache.invalidate(); self.is_cyclic.invalidate(); &mut self.basic_blocks } @@ -389,6 +395,7 @@ impl<'tcx> Body<'tcx> { &mut self, ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) { self.predecessor_cache.invalidate(); + self.switch_source_cache.invalidate(); self.is_cyclic.invalidate(); (&mut self.basic_blocks, &mut self.local_decls) } @@ -402,6 +409,7 @@ impl<'tcx> Body<'tcx> { &mut Vec<VarDebugInfo<'tcx>>, ) { self.predecessor_cache.invalidate(); + self.switch_source_cache.invalidate(); self.is_cyclic.invalidate(); (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info) } @@ -530,6 +538,11 @@ impl<'tcx> Body<'tcx> { } #[inline] + pub fn switch_sources(&self) -> &SwitchSources { + self.switch_source_cache.compute(&self.basic_blocks) + } + + #[inline] pub fn dominators(&self) -> Dominators<BasicBlock> { dominators(self) } diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs new file mode 100644 index 00000000000..7f62b4d0dba --- /dev/null +++ b/compiler/rustc_middle/src/mir/switch_sources.rs @@ -0,0 +1,82 @@ +//! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after +//! `Predecessors`/`PredecessorCache`. + +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::OnceCell; +use rustc_index::vec::IndexVec; +use rustc_serialize as serialize; +use smallvec::SmallVec; + +use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind}; + +pub type SwitchSources = IndexVec<BasicBlock, IndexVec<BasicBlock, SmallVec<[Option<u128>; 1]>>>; + +#[derive(Clone, Debug)] +pub(super) struct SwitchSourceCache { + cache: OnceCell<SwitchSources>, +} + +impl SwitchSourceCache { + #[inline] + pub(super) fn new() -> Self { + SwitchSourceCache { cache: OnceCell::new() } + } + + /// Invalidates the switch source cache. + #[inline] + pub(super) fn invalidate(&mut self) { + self.cache = OnceCell::new(); + } + + /// Returns the switch sources for this MIR. + #[inline] + pub(super) fn compute( + &self, + basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>, + ) -> &SwitchSources { + self.cache.get_or_init(|| { + let mut switch_sources = IndexVec::from_elem( + IndexVec::from_elem(SmallVec::new(), basic_blocks), + basic_blocks, + ); + for (bb, data) in basic_blocks.iter_enumerated() { + if let Some(Terminator { + kind: TerminatorKind::SwitchInt { targets, .. }, .. + }) = &data.terminator + { + for (value, target) in targets.iter() { + switch_sources[target][bb].push(Some(value)); + } + switch_sources[targets.otherwise()][bb].push(None); + } + } + + switch_sources + }) + } +} + +impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache { + #[inline] + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_unit() + } +} + +impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache { + #[inline] + fn decode(_: &mut D) -> Self { + Self::new() + } +} + +impl<CTX> HashStable<CTX> for SwitchSourceCache { + #[inline] + fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) { + // do nothing + } +} + +TrivialTypeFoldableAndLiftImpls! { + SwitchSourceCache, +} |
