Skip to content

Commit eabf390

Browse files
committed
Auto merge of rust-lang#146697 - cjgillot:invalidate-patch, r=lcnr
Avoid invalidating CFG caches from MirPatch::apply. Small effort to reduce invalidating CFG caches.
2 parents 6f34f4e + ce677c7 commit eabf390

File tree

1 file changed

+21
-15
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+21
-15
lines changed

compiler/rustc_mir_transform/src/patch.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use rustc_index::{Idx, IndexVec};
1+
use rustc_data_structures::fx::FxHashMap;
2+
use rustc_index::Idx;
23
use rustc_middle::mir::*;
34
use rustc_middle::ty::Ty;
45
use rustc_span::Span;
@@ -9,7 +10,7 @@ use tracing::debug;
910
/// and replacement of terminators, and then apply the queued changes all at
1011
/// once with `apply`. This is useful for MIR transformation passes.
1112
pub(crate) struct MirPatch<'tcx> {
12-
term_patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
13+
term_patch_map: FxHashMap<BasicBlock, TerminatorKind<'tcx>>,
1314
new_blocks: Vec<BasicBlockData<'tcx>>,
1415
new_statements: Vec<(Location, StatementKind<'tcx>)>,
1516
new_locals: Vec<LocalDecl<'tcx>>,
@@ -22,17 +23,21 @@ pub(crate) struct MirPatch<'tcx> {
2223
terminate_block: Option<(BasicBlock, UnwindTerminateReason)>,
2324
body_span: Span,
2425
next_local: usize,
26+
/// The number of blocks at the start of the transformation. New blocks
27+
/// get appended at the end.
28+
next_block: usize,
2529
}
2630

2731
impl<'tcx> MirPatch<'tcx> {
2832
/// Creates a new, empty patch.
2933
pub(crate) fn new(body: &Body<'tcx>) -> Self {
3034
let mut result = MirPatch {
31-
term_patch_map: IndexVec::from_elem(None, &body.basic_blocks),
35+
term_patch_map: Default::default(),
3236
new_blocks: vec![],
3337
new_statements: vec![],
3438
new_locals: vec![],
3539
next_local: body.local_decls.len(),
40+
next_block: body.basic_blocks.len(),
3641
resume_block: None,
3742
unreachable_cleanup_block: None,
3843
unreachable_no_cleanup_block: None,
@@ -141,7 +146,7 @@ impl<'tcx> MirPatch<'tcx> {
141146

142147
/// Has a replacement of this block's terminator been queued in this patch?
143148
pub(crate) fn is_term_patched(&self, bb: BasicBlock) -> bool {
144-
self.term_patch_map[bb].is_some()
149+
self.term_patch_map.contains_key(&bb)
145150
}
146151

147152
/// Universal getter for block data, either it is in 'old' blocks or in patched ones
@@ -194,18 +199,17 @@ impl<'tcx> MirPatch<'tcx> {
194199

195200
/// Queues the addition of a new basic block.
196201
pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
197-
let block = self.term_patch_map.next_index();
202+
let block = BasicBlock::from_usize(self.next_block + self.new_blocks.len());
198203
debug!("MirPatch: new_block: {:?}: {:?}", block, data);
199204
self.new_blocks.push(data);
200-
self.term_patch_map.push(None);
201205
block
202206
}
203207

204208
/// Queues the replacement of a block's terminator.
205209
pub(crate) fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
206-
assert!(self.term_patch_map[block].is_none());
210+
assert!(!self.term_patch_map.contains_key(&block));
207211
debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
208-
self.term_patch_map[block] = Some(new);
212+
self.term_patch_map.insert(block, new);
209213
}
210214

211215
/// Queues the insertion of a statement at a given location. The statement
@@ -244,18 +248,20 @@ impl<'tcx> MirPatch<'tcx> {
244248
self.new_blocks.len(),
245249
body.basic_blocks.len()
246250
);
251+
debug_assert_eq!(self.next_block, body.basic_blocks.len());
247252
let bbs = if self.term_patch_map.is_empty() && self.new_blocks.is_empty() {
248253
body.basic_blocks.as_mut_preserves_cfg()
249254
} else {
250255
body.basic_blocks.as_mut()
251256
};
252257
bbs.extend(self.new_blocks);
253258
body.local_decls.extend(self.new_locals);
254-
for (src, patch) in self.term_patch_map.into_iter_enumerated() {
255-
if let Some(patch) = patch {
256-
debug!("MirPatch: patching block {:?}", src);
257-
bbs[src].terminator_mut().kind = patch;
258-
}
259+
260+
// The order in which we patch terminators does not change the result.
261+
#[allow(rustc::potential_query_instability)]
262+
for (src, patch) in self.term_patch_map {
263+
debug!("MirPatch: patching block {:?}", src);
264+
bbs[src].terminator_mut().kind = patch;
259265
}
260266

261267
let mut new_statements = self.new_statements;
@@ -273,8 +279,8 @@ impl<'tcx> MirPatch<'tcx> {
273279
}
274280
debug!("MirPatch: adding statement {:?} at loc {:?}+{}", stmt, loc, delta);
275281
loc.statement_index += delta;
276-
let source_info = Self::source_info_for_index(&body[loc.block], loc);
277-
body[loc.block]
282+
let source_info = Self::source_info_for_index(&bbs[loc.block], loc);
283+
bbs[loc.block]
278284
.statements
279285
.insert(loc.statement_index, Statement::new(source_info, stmt));
280286
delta += 1;

0 commit comments

Comments
 (0)