Skip to content

Commit cb39073

Browse files
committed
Auto merge of #96838 - tmiasko:lazy-switch-sources, r=oli-obk
Optimize switch sources representation and usage * Avoid constructing switch sources unless necessary - switch sources are used by backward analysis with a custom switch int edge effects, but are otherwise unnecessarily computed. * Use sparse representation of switch sources to avoid quadratic space overhead.
2 parents 88860d5 + 2be012a commit cb39073

File tree

3 files changed

+11
-10
lines changed

3 files changed

+11
-10
lines changed

compiler/rustc_middle/src/mir/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,8 @@ impl<'tcx> Body<'tcx> {
580580
self.predecessor_cache.compute(&self.basic_blocks)
581581
}
582582

583+
/// `body.switch_sources()[&(target, switch)]` returns a list of switch
584+
/// values that lead to a `target` block from a `switch` block.
583585
#[inline]
584586
pub fn switch_sources(&self) -> &SwitchSources {
585587
self.switch_source_cache.compute(&self.basic_blocks)

compiler/rustc_middle/src/mir/switch_sources.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
//! `Predecessors`/`PredecessorCache`.
33
44
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5+
use rustc_data_structures::stable_map::FxHashMap;
56
use rustc_data_structures::sync::OnceCell;
67
use rustc_index::vec::IndexVec;
78
use rustc_serialize as serialize;
89
use smallvec::SmallVec;
910

1011
use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
1112

12-
pub type SwitchSources = IndexVec<BasicBlock, IndexVec<BasicBlock, SmallVec<[Option<u128>; 1]>>>;
13+
pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
1314

1415
#[derive(Clone, Debug)]
1516
pub(super) struct SwitchSourceCache {
@@ -35,19 +36,16 @@ impl SwitchSourceCache {
3536
basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
3637
) -> &SwitchSources {
3738
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-
);
39+
let mut switch_sources: SwitchSources = FxHashMap::default();
4240
for (bb, data) in basic_blocks.iter_enumerated() {
4341
if let Some(Terminator {
4442
kind: TerminatorKind::SwitchInt { targets, .. }, ..
4543
}) = &data.terminator
4644
{
4745
for (value, target) in targets.iter() {
48-
switch_sources[target][bb].push(Some(value));
46+
switch_sources.entry((target, bb)).or_default().push(Some(value));
4947
}
50-
switch_sources[targets.otherwise()][bb].push(None);
48+
switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
5149
}
5250
}
5351

compiler/rustc_mir_dataflow/src/framework/direction.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,9 @@ impl Direction for Backward {
269269

270270
mir::TerminatorKind::SwitchInt { targets: _, ref discr, switch_ty: _ } => {
271271
let mut applier = BackwardSwitchIntEdgeEffectsApplier {
272+
body,
272273
pred,
273274
exit_state,
274-
values: &body.switch_sources()[bb][pred],
275275
bb,
276276
propagate: &mut propagate,
277277
effects_applied: false,
@@ -305,9 +305,9 @@ impl Direction for Backward {
305305
}
306306

307307
struct BackwardSwitchIntEdgeEffectsApplier<'a, D, F> {
308+
body: &'a mir::Body<'a>,
308309
pred: BasicBlock,
309310
exit_state: &'a mut D,
310-
values: &'a [Option<u128>],
311311
bb: BasicBlock,
312312
propagate: &'a mut F,
313313

@@ -322,7 +322,8 @@ where
322322
fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) {
323323
assert!(!self.effects_applied);
324324

325-
let targets = self.values.iter().map(|&value| SwitchIntTarget { value, target: self.bb });
325+
let values = &self.body.switch_sources()[&(self.bb, self.pred)];
326+
let targets = values.iter().map(|&value| SwitchIntTarget { value, target: self.bb });
326327

327328
let mut tmp = None;
328329
for target in targets {

0 commit comments

Comments
 (0)