Skip to content

Commit 5fb1b8a

Browse files
committed
Auto merge of #142540 - cjgillot:renumber-cfg, r=<try>
Pre-compute MIR CFG caches for borrowck and other analyses I was puzzled that #142390 introduces additional computations of CFG traversals: borrowck computes them, right? It turns out that borrowck clones the MIR body, so doesn't share its cache with other analyses. This PR: - forces the computation of all caches in `mir_promoted` query; - modifies region renumbering to avoid dropping that cache.
2 parents 915e535 + 184e17c commit 5fb1b8a

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

compiler/rustc_borrowck/src/renumber.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ pub(crate) fn renumber_mir<'tcx>(
2121
let mut renumberer = RegionRenumberer { infcx };
2222

2323
for body in promoted.iter_mut() {
24-
renumberer.visit_body(body);
24+
renumberer.visit_body_preserves_cfg(body);
2525
}
2626

27-
renumberer.visit_body(body);
27+
renumberer.visit_body_preserves_cfg(body);
2828
}
2929

3030
// The fields are used only for debugging output in `sccs_info`.

compiler/rustc_middle/src/mir/basic_blocks.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::sync::OnceLock;
1+
use std::sync::{Arc, OnceLock};
22

33
use rustc_data_structures::graph;
44
use rustc_data_structures::graph::dominators::{Dominators, dominators};
@@ -14,7 +14,8 @@ use crate::mir::{BasicBlock, BasicBlockData, START_BLOCK};
1414
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
1515
pub struct BasicBlocks<'tcx> {
1616
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
17-
cache: Cache,
17+
/// Use an `Arc` so we can share the cache when we clone the MIR body, as borrowck does.
18+
cache: Arc<Cache>,
1819
}
1920

2021
// Typically 95%+ of basic blocks have 4 or fewer predecessors.
@@ -38,9 +39,10 @@ struct Cache {
3839
impl<'tcx> BasicBlocks<'tcx> {
3940
#[inline]
4041
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
41-
BasicBlocks { basic_blocks, cache: Cache::default() }
42+
BasicBlocks { basic_blocks, cache: Arc::new(Cache::default()) }
4243
}
4344

45+
#[inline]
4446
pub fn dominators(&self) -> &Dominators<BasicBlock> {
4547
self.cache.dominators.get_or_init(|| dominators(self))
4648
}
@@ -104,7 +106,14 @@ impl<'tcx> BasicBlocks<'tcx> {
104106
/// All other methods that allow you to mutate the basic blocks also call this method
105107
/// themselves, thereby avoiding any risk of accidentally cache invalidation.
106108
pub fn invalidate_cfg_cache(&mut self) {
107-
self.cache = Cache::default();
109+
if let Some(cache) = Arc::get_mut(&mut self.cache) {
110+
// If we only have a single reference to this cache, clear it.
111+
*cache = Cache::default();
112+
} else {
113+
// If we have several references to this cache, overwrite the pointer itself so other
114+
// users can continue to use their (valid) cache.
115+
self.cache = Arc::new(Cache::default());
116+
}
108117
}
109118
}
110119

0 commit comments

Comments
 (0)