Skip to content

Commit a5fa99e

Browse files
committed
Auto merge of #106975 - tmiasko:basic-blocks-cache, r=cjgillot
Refactor basic blocks control flow caches No functional changes.
2 parents 5e37043 + a6235a2 commit a5fa99e

File tree

6 files changed

+74
-296
lines changed

6 files changed

+74
-296
lines changed

compiler/rustc_middle/src/mir/basic_blocks.rs

+74-24
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,44 @@
1-
use crate::mir::graph_cyclic_cache::GraphIsCyclicCache;
2-
use crate::mir::predecessors::{PredecessorCache, Predecessors};
3-
use crate::mir::switch_sources::{SwitchSourceCache, SwitchSources};
4-
use crate::mir::traversal::PostorderCache;
5-
use crate::mir::{BasicBlock, BasicBlockData, Successors, START_BLOCK};
1+
use crate::mir::traversal::Postorder;
2+
use crate::mir::{BasicBlock, BasicBlockData, Successors, Terminator, TerminatorKind, START_BLOCK};
63

4+
use rustc_data_structures::fx::FxHashMap;
75
use rustc_data_structures::graph;
86
use rustc_data_structures::graph::dominators::{dominators, Dominators};
7+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
8+
use rustc_data_structures::sync::OnceCell;
99
use rustc_index::vec::IndexVec;
10+
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
11+
use smallvec::SmallVec;
1012

1113
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
1214
pub struct BasicBlocks<'tcx> {
1315
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
14-
predecessor_cache: PredecessorCache,
15-
switch_source_cache: SwitchSourceCache,
16-
is_cyclic: GraphIsCyclicCache,
17-
postorder_cache: PostorderCache,
16+
cache: Cache,
17+
}
18+
19+
// Typically 95%+ of basic blocks have 4 or fewer predecessors.
20+
pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
21+
22+
pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
23+
24+
#[derive(Clone, Default, Debug)]
25+
struct Cache {
26+
predecessors: OnceCell<Predecessors>,
27+
switch_sources: OnceCell<SwitchSources>,
28+
is_cyclic: OnceCell<bool>,
29+
postorder: OnceCell<Vec<BasicBlock>>,
1830
}
1931

2032
impl<'tcx> BasicBlocks<'tcx> {
2133
#[inline]
2234
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
23-
BasicBlocks {
24-
basic_blocks,
25-
predecessor_cache: PredecessorCache::new(),
26-
switch_source_cache: SwitchSourceCache::new(),
27-
is_cyclic: GraphIsCyclicCache::new(),
28-
postorder_cache: PostorderCache::new(),
29-
}
35+
BasicBlocks { basic_blocks, cache: Cache::default() }
3036
}
3137

3238
/// Returns true if control-flow graph contains a cycle reachable from the `START_BLOCK`.
3339
#[inline]
3440
pub fn is_cfg_cyclic(&self) -> bool {
35-
self.is_cyclic.is_cyclic(self)
41+
*self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
3642
}
3743

3844
#[inline]
@@ -43,20 +49,46 @@ impl<'tcx> BasicBlocks<'tcx> {
4349
/// Returns predecessors for each basic block.
4450
#[inline]
4551
pub fn predecessors(&self) -> &Predecessors {
46-
self.predecessor_cache.compute(&self.basic_blocks)
52+
self.cache.predecessors.get_or_init(|| {
53+
let mut preds = IndexVec::from_elem(SmallVec::new(), &self.basic_blocks);
54+
for (bb, data) in self.basic_blocks.iter_enumerated() {
55+
if let Some(term) = &data.terminator {
56+
for succ in term.successors() {
57+
preds[succ].push(bb);
58+
}
59+
}
60+
}
61+
preds
62+
})
4763
}
4864

4965
/// Returns basic blocks in a postorder.
5066
#[inline]
5167
pub fn postorder(&self) -> &[BasicBlock] {
52-
self.postorder_cache.compute(&self.basic_blocks)
68+
self.cache.postorder.get_or_init(|| {
69+
Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect()
70+
})
5371
}
5472

5573
/// `switch_sources()[&(target, switch)]` returns a list of switch
5674
/// values that lead to a `target` block from a `switch` block.
5775
#[inline]
5876
pub fn switch_sources(&self) -> &SwitchSources {
59-
self.switch_source_cache.compute(&self.basic_blocks)
77+
self.cache.switch_sources.get_or_init(|| {
78+
let mut switch_sources: SwitchSources = FxHashMap::default();
79+
for (bb, data) in self.basic_blocks.iter_enumerated() {
80+
if let Some(Terminator {
81+
kind: TerminatorKind::SwitchInt { targets, .. }, ..
82+
}) = &data.terminator
83+
{
84+
for (value, target) in targets.iter() {
85+
switch_sources.entry((target, bb)).or_default().push(Some(value));
86+
}
87+
switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
88+
}
89+
}
90+
switch_sources
91+
})
6092
}
6193

6294
/// Returns mutable reference to basic blocks. Invalidates CFG cache.
@@ -88,10 +120,7 @@ impl<'tcx> BasicBlocks<'tcx> {
88120
/// All other methods that allow you to mutate the basic blocks also call this method
89121
/// themselves, thereby avoiding any risk of accidentally cache invalidation.
90122
pub fn invalidate_cfg_cache(&mut self) {
91-
self.predecessor_cache.invalidate();
92-
self.switch_source_cache.invalidate();
93-
self.is_cyclic.invalidate();
94-
self.postorder_cache.invalidate();
123+
self.cache = Cache::default();
95124
}
96125
}
97126

@@ -145,3 +174,24 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> {
145174
self.predecessors()[node].iter().copied()
146175
}
147176
}
177+
178+
TrivialTypeTraversalAndLiftImpls! {
179+
Cache,
180+
}
181+
182+
impl<S: Encoder> Encodable<S> for Cache {
183+
#[inline]
184+
fn encode(&self, _s: &mut S) {}
185+
}
186+
187+
impl<D: Decoder> Decodable<D> for Cache {
188+
#[inline]
189+
fn decode(_: &mut D) -> Self {
190+
Default::default()
191+
}
192+
}
193+
194+
impl<CTX> HashStable<CTX> for Cache {
195+
#[inline]
196+
fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {}
197+
}

compiler/rustc_middle/src/mir/graph_cyclic_cache.rs

-63
This file was deleted.

compiler/rustc_middle/src/mir/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,15 @@ mod basic_blocks;
4747
pub mod coverage;
4848
mod generic_graph;
4949
pub mod generic_graphviz;
50-
mod graph_cyclic_cache;
5150
pub mod graphviz;
5251
pub mod interpret;
5352
pub mod mono;
5453
pub mod patch;
55-
mod predecessors;
5654
pub mod pretty;
5755
mod query;
5856
pub mod spanview;
5957
mod syntax;
6058
pub use syntax::*;
61-
mod switch_sources;
6259
pub mod tcx;
6360
pub mod terminator;
6461
pub use terminator::*;

compiler/rustc_middle/src/mir/predecessors.rs

-78
This file was deleted.

compiler/rustc_middle/src/mir/switch_sources.rs

-78
This file was deleted.

0 commit comments

Comments
 (0)