]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/switch_sources.rs
Auto merge of #106827 - alexcrichton:update-llvm-to-15.0.7, r=cuviper
[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::fx::FxHashMap;
5 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
6 use rustc_data_structures::sync::OnceCell;
7 use rustc_index::vec::IndexVec;
8 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
9 use smallvec::SmallVec;
10
11 use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
12
13 pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
14
15 #[derive(Clone, Debug)]
16 pub(super) struct SwitchSourceCache {
17     cache: OnceCell<SwitchSources>,
18 }
19
20 impl SwitchSourceCache {
21     #[inline]
22     pub(super) fn new() -> Self {
23         SwitchSourceCache { cache: OnceCell::new() }
24     }
25
26     /// Invalidates the switch source cache.
27     #[inline]
28     pub(super) fn invalidate(&mut self) {
29         self.cache = OnceCell::new();
30     }
31
32     /// Returns the switch sources for this MIR.
33     #[inline]
34     pub(super) fn compute(
35         &self,
36         basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
37     ) -> &SwitchSources {
38         self.cache.get_or_init(|| {
39             let mut switch_sources: SwitchSources = FxHashMap::default();
40             for (bb, data) in basic_blocks.iter_enumerated() {
41                 if let Some(Terminator {
42                     kind: TerminatorKind::SwitchInt { targets, .. }, ..
43                 }) = &data.terminator
44                 {
45                     for (value, target) in targets.iter() {
46                         switch_sources.entry((target, bb)).or_default().push(Some(value));
47                     }
48                     switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
49                 }
50             }
51
52             switch_sources
53         })
54     }
55 }
56
57 impl<S: Encoder> Encodable<S> for SwitchSourceCache {
58     #[inline]
59     fn encode(&self, _s: &mut S) {}
60 }
61
62 impl<D: Decoder> Decodable<D> for SwitchSourceCache {
63     #[inline]
64     fn decode(_: &mut D) -> Self {
65         Self::new()
66     }
67 }
68
69 impl<CTX> HashStable<CTX> for SwitchSourceCache {
70     #[inline]
71     fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
72         // do nothing
73     }
74 }
75
76 TrivialTypeTraversalAndLiftImpls! {
77     SwitchSourceCache,
78 }