From 6f198ee159a66ade81b06f5f035ba0af8d1d3f23 Mon Sep 17 00:00:00 2001 From: Makro Date: Fri, 31 Jul 2026 04:42:55 +0000 Subject: [PATCH] perf: Avoid a heap allocation per basic block in MoveData's location maps --- .../rustc_mir_dataflow/src/move_paths/mod.rs | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 7f8872b3e3493..cb1a6f4f32494 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -189,21 +189,38 @@ pub trait HasMoveData<'tcx> { #[derive(Debug)] pub struct LocationMap { - /// Location-indexed (BasicBlock for outer index, index within BB - /// for inner index) map. - pub(crate) map: IndexVec>, + /// All per-location entries live in the single flat `data` vector. + /// `block_starts[bb]` gives the index in `data` where block `bb`'s entries + /// start; each block has one entry per statement plus one for its terminator. + data: Vec, + block_starts: IndexVec, +} + +impl LocationMap { + #[inline] + fn offset(&self, loc: Location) -> usize { + let offset = self.block_starts[loc.block] + loc.statement_index; + // A block's entries end where the next block's begin, or at the end of + // `data` for the last block. + debug_assert!( + offset + < self.block_starts.raw.get(loc.block.as_usize() + 1).copied().unwrap_or(self.data.len()), + "{loc:?} is out of range for its block", + ); + offset + } } impl Index for LocationMap { type Output = T; fn index(&self, index: Location) -> &Self::Output { - &self.map[index.block][index.statement_index] + &self.data[self.offset(index)] } } impl IndexMut for LocationMap { fn index_mut(&mut self, index: Location) -> &mut Self::Output { - &mut self.map[index.block][index.statement_index] + &mut self.data[self.offset(index)] } } @@ -212,13 +229,13 @@ where T: Default + Clone, { fn new(body: &Body<'_>) -> Self { - LocationMap { - map: body - .basic_blocks - .iter() - .map(|block| vec![T::default(); block.statements.len() + 1]) - .collect(), + let mut block_starts = IndexVec::with_capacity(body.basic_blocks.len()); + let mut total = 0; + for block in body.basic_blocks.iter() { + block_starts.push(total); + total += block.statements.len() + 1; } + LocationMap { data: vec![T::default(); total], block_starts } } }