Skip to content

Commit 7149bbc

Browse files
committed
Eliminate duplication of RPO calculation for mir
add `postorder_cache` to mir Body add `ReversePostorderCache` struct correct struct name and comments
1 parent c95346b commit 7149bbc

File tree

4 files changed

+96
-7
lines changed

4 files changed

+96
-7
lines changed

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 0 additions & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 86 additions & 4 deletions
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)