Skip to content

Commit 9a98c63

Browse files
committed
Auto merge of #96500 - SparrowLii:rpo, r=tmiasko
Reduce duplication of RPO calculation of mir Computing the RPO of mir is not a low-cost thing, but it is duplicate in many places. In particular the `iterate_to_fixpoint` method which is called multiple times when computing the data flow. This PR reduces the number of times the RPO is recalculated as much as possible, which should save some compile time.
2 parents 0c8e520 + 7149bbc commit 9a98c63

File tree

4 files changed

+96
-7
lines changed

4 files changed

+96
-7
lines changed

compiler/rustc_codegen_ssa/src/mir/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
244244
fx.debug_introduce_locals(&mut bx);
245245

246246
// Codegen the body of each block using reverse postorder
247-
// FIXME(eddyb) reuse RPO iterator between `analysis` and this.
248247
for (bb, _) in traversal::reverse_postorder(&mir) {
249248
fx.codegen_block(bb);
250249
}

compiler/rustc_const_eval/src/transform/promote_consts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! move analysis runs after promotion on broken MIR.
1414
1515
use rustc_hir as hir;
16-
use rustc_middle::mir::traversal::ReversePostorder;
16+
use rustc_middle::mir::traversal::ReversePostorderIter;
1717
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
1818
use rustc_middle::mir::*;
1919
use rustc_middle::ty::cast::CastTy;
@@ -170,7 +170,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
170170

171171
pub fn collect_temps_and_candidates<'tcx>(
172172
ccx: &ConstCx<'_, 'tcx>,
173-
rpo: &mut ReversePostorder<'_, 'tcx>,
173+
rpo: &mut ReversePostorderIter<'_, 'tcx>,
174174
) -> (IndexVec<Local, TempState>, Vec<Candidate>) {
175175
let mut collector = Collector {
176176
temps: IndexVec::from_elem(TempState::Undefined, &ccx.body.local_decls),

compiler/rustc_middle/src/mir/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ pub mod spanview;
6262
mod switch_sources;
6363
pub mod tcx;
6464
pub mod terminator;
65+
use crate::mir::traversal::PostorderCache;
6566
pub use terminator::*;
67+
6668
pub mod traversal;
6769
mod type_foldable;
6870
pub mod visit;
@@ -323,6 +325,7 @@ pub struct Body<'tcx> {
323325
predecessor_cache: PredecessorCache,
324326
switch_source_cache: SwitchSourceCache,
325327
is_cyclic: GraphIsCyclicCache,
328+
postorder_cache: PostorderCache,
326329

327330
pub tainted_by_errors: Option<ErrorGuaranteed>,
328331
}
@@ -372,6 +375,7 @@ impl<'tcx> Body<'tcx> {
372375
predecessor_cache: PredecessorCache::new(),
373376
switch_source_cache: SwitchSourceCache::new(),
374377
is_cyclic: GraphIsCyclicCache::new(),
378+
postorder_cache: PostorderCache::new(),
375379
tainted_by_errors,
376380
};
377381
body.is_polymorphic = body.has_param_types_or_consts();
@@ -401,6 +405,7 @@ impl<'tcx> Body<'tcx> {
401405
predecessor_cache: PredecessorCache::new(),
402406
switch_source_cache: SwitchSourceCache::new(),
403407
is_cyclic: GraphIsCyclicCache::new(),
408+
postorder_cache: PostorderCache::new(),
404409
tainted_by_errors: None,
405410
};
406411
body.is_polymorphic = body.has_param_types_or_consts();
@@ -422,6 +427,7 @@ impl<'tcx> Body<'tcx> {
422427
self.predecessor_cache.invalidate();
423428
self.switch_source_cache.invalidate();
424429
self.is_cyclic.invalidate();
430+
self.postorder_cache.invalidate();
425431
&mut self.basic_blocks
426432
}
427433

@@ -432,6 +438,7 @@ impl<'tcx> Body<'tcx> {
432438
self.predecessor_cache.invalidate();
433439
self.switch_source_cache.invalidate();
434440
self.is_cyclic.invalidate();
441+
self.postorder_cache.invalidate();
435442
(&mut self.basic_blocks, &mut self.local_decls)
436443
}
437444

@@ -446,6 +453,7 @@ impl<'tcx> Body<'tcx> {
446453
self.predecessor_cache.invalidate();
447454
self.switch_source_cache.invalidate();
448455
self.is_cyclic.invalidate();
456+
self.postorder_cache.invalidate();
449457
(&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
450458
}
451459

compiler/rustc_middle/src/mir/traversal.rs

+86-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
2+
use rustc_data_structures::sync::OnceCell;
13
use rustc_index::bit_set::BitSet;
4+
use rustc_serialize as serialize;
25

36
use super::*;
47

@@ -268,10 +271,6 @@ impl<'a, 'tcx> ReversePostorder<'a, 'tcx> {
268271
}
269272
}
270273

271-
pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorder<'a, 'tcx> {
272-
ReversePostorder::new(body, START_BLOCK)
273-
}
274-
275274
impl<'a, 'tcx> Iterator for ReversePostorder<'a, 'tcx> {
276275
type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
277276

@@ -307,3 +306,86 @@ pub fn reachable_as_bitset<'tcx>(body: &Body<'tcx>) -> BitSet<BasicBlock> {
307306
(&mut iter).for_each(drop);
308307
iter.visited
309308
}
309+
310+
#[derive(Clone)]
311+
pub struct ReversePostorderIter<'a, 'tcx> {
312+
body: &'a Body<'tcx>,
313+
blocks: &'a Vec<BasicBlock>,
314+
idx: usize,
315+
}
316+
317+
impl<'a, 'tcx> Iterator for ReversePostorderIter<'a, 'tcx> {
318+
type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
319+
320+
fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> {
321+
if self.idx == 0 {
322+
return None;
323+
}
324+
self.idx -= 1;
325+
326+
self.blocks.get(self.idx).map(|&bb| (bb, &self.body[bb]))
327+
}
328+
329+
fn size_hint(&self) -> (usize, Option<usize>) {
330+
(self.idx, Some(self.idx))
331+
}
332+
}
333+
334+
impl<'a, 'tcx> ExactSizeIterator for ReversePostorderIter<'a, 'tcx> {}
335+
336+
pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter<'a, 'tcx> {
337+
let blocks = body.postorder_cache.compute(body);
338+
339+
let len = blocks.len();
340+
341+
ReversePostorderIter { body, blocks, idx: len }
342+
}
343+
344+
#[derive(Clone, Debug)]
345+
pub(super) struct PostorderCache {
346+
cache: OnceCell<Vec<BasicBlock>>,
347+
}
348+
349+
impl PostorderCache {
350+
#[inline]
351+
pub(super) fn new() -> Self {
352+
PostorderCache { cache: OnceCell::new() }
353+
}
354+
355+
/// Invalidates the postorder cache.
356+
#[inline]
357+
pub(super) fn invalidate(&mut self) {
358+
self.cache = OnceCell::new();
359+
}
360+
361+
/// Returns the &Vec<BasicBlocks> represents the postorder graph for this MIR.
362+
#[inline]
363+
pub(super) fn compute(&self, body: &Body<'_>) -> &Vec<BasicBlock> {
364+
self.cache.get_or_init(|| Postorder::new(body, START_BLOCK).map(|(bb, _)| bb).collect())
365+
}
366+
}
367+
368+
impl<S: serialize::Encoder> serialize::Encodable<S> for PostorderCache {
369+
#[inline]
370+
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
371+
s.emit_unit()
372+
}
373+
}
374+
375+
impl<D: serialize::Decoder> serialize::Decodable<D> for PostorderCache {
376+
#[inline]
377+
fn decode(_: &mut D) -> Self {
378+
Self::new()
379+
}
380+
}
381+
382+
impl<CTX> HashStable<CTX> for PostorderCache {
383+
#[inline]
384+
fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
385+
// do nothing
386+
}
387+
}
388+
389+
TrivialTypeFoldableAndLiftImpls! {
390+
PostorderCache,
391+
}

0 commit comments

Comments
 (0)