]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/switch_sources.rs
Auto merge of #96002 - nnethercote:speed-up-Vec-clear-2, r=m-ou-se
[rust.git] / compiler / rustc_middle / src / mir / switch_sources.rs
1 //! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after
2 //! `Predecessors`/`PredecessorCache`.
3
4 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5 use rustc_data_structures::sync::OnceCell;
6 use rustc_index::vec::IndexVec;
7 use rustc_serialize as serialize;
8 use smallvec::SmallVec;
9
10 use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
11
12 pub type SwitchSources = IndexVec<BasicBlock, IndexVec<BasicBlock, SmallVec<[Option<u128>; 1]>>>;
13
14 #[derive(Clone, Debug)]
15 pub(super) struct SwitchSourceCache {
16     cache: OnceCell<SwitchSources>,
17 }
18
19 impl SwitchSourceCache {
20     #[inline]
21     pub(super) fn new() -> Self {
22         SwitchSourceCache { cache: OnceCell::new() }
23     }
24
25     /// Invalidates the switch source cache.
26     #[inline]
27     pub(super) fn invalidate(&mut self) {
28         self.cache = OnceCell::new();
29     }
30
31     /// Returns the switch sources for this MIR.
32     #[inline]
33     pub(super) fn compute(
34         &self,
35         basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
36     ) -> &SwitchSources {
37         self.cache.get_or_init(|| {
38             let mut switch_sources = IndexVec::from_elem(
39                 IndexVec::from_elem(SmallVec::new(), basic_blocks),
40                 basic_blocks,
41             );
42             for (bb, data) in basic_blocks.iter_enumerated() {
43                 if let Some(Terminator {
44                     kind: TerminatorKind::SwitchInt { targets, .. }, ..
45                 }) = &data.terminator
46                 {
47                     for (value, target) in targets.iter() {
48                         switch_sources[target][bb].push(Some(value));
49                     }
50                     switch_sources[targets.otherwise()][bb].push(None);
51                 }
52             }
53
54             switch_sources
55         })
56     }
57 }
58
59 impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache {
60     #[inline]
61     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
62         s.emit_unit()
63     }
64 }
65
66 impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache {
67     #[inline]
68     fn decode(_: &mut D) -> Self {
69         Self::new()
70     }
71 }
72
73 impl<CTX> HashStable<CTX> for SwitchSourceCache {
74     #[inline]
75     fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
76         // do nothing
77     }
78 }
79
80 TrivialTypeFoldableAndLiftImpls! {
81     SwitchSourceCache,
82 }