1
Fork 0

Simplify Postorder customization.

`Postorder` has a `C: Customization<'tcx>` parameter, that gives it
flexibility about how it computes successors. But in practice, there are
only two `impls` of `Customization`, and one is for the unit type.

This commit simplifies things by removing the generic parameter and
replacing it with an `Option`.
This commit is contained in:
Nicholas Nethercote 2025-02-19 14:08:52 +11:00
parent 5986ff05d8
commit cae9ebbe1e
3 changed files with 15 additions and 36 deletions

View file

@ -79,7 +79,7 @@ impl<'tcx> BasicBlocks<'tcx> {
#[inline] #[inline]
pub fn reverse_postorder(&self) -> &[BasicBlock] { pub fn reverse_postorder(&self) -> &[BasicBlock] {
self.cache.reverse_postorder.get_or_init(|| { self.cache.reverse_postorder.get_or_init(|| {
let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, ()).collect(); let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, None).collect();
rpo.reverse(); rpo.reverse();
rpo rpo
}) })

View file

@ -104,23 +104,21 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
/// ``` /// ```
/// ///
/// A Postorder traversal of this graph is `D B C A` or `D C B A` /// A Postorder traversal of this graph is `D B C A` or `D C B A`
pub struct Postorder<'a, 'tcx, C> { pub struct Postorder<'a, 'tcx> {
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>, basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
visited: DenseBitSet<BasicBlock>, visited: DenseBitSet<BasicBlock>,
visit_stack: Vec<(BasicBlock, Successors<'a>)>, visit_stack: Vec<(BasicBlock, Successors<'a>)>,
root_is_start_block: bool, root_is_start_block: bool,
extra: C, /// A non-empty `extra` allows for a precise calculation of the successors.
extra: Option<(TyCtxt<'tcx>, Instance<'tcx>)>,
} }
impl<'a, 'tcx, C> Postorder<'a, 'tcx, C> impl<'a, 'tcx> Postorder<'a, 'tcx> {
where
C: Customization<'tcx>,
{
pub fn new( pub fn new(
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>, basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
root: BasicBlock, root: BasicBlock,
extra: C, extra: Option<(TyCtxt<'tcx>, Instance<'tcx>)>,
) -> Postorder<'a, 'tcx, C> { ) -> Postorder<'a, 'tcx> {
let mut po = Postorder { let mut po = Postorder {
basic_blocks, basic_blocks,
visited: DenseBitSet::new_empty(basic_blocks.len()), visited: DenseBitSet::new_empty(basic_blocks.len()),
@ -140,7 +138,11 @@ where
return; return;
} }
let data = &self.basic_blocks[bb]; let data = &self.basic_blocks[bb];
let successors = C::successors(data, self.extra); let successors = if let Some(extra) = self.extra {
data.mono_successors(extra.0, extra.1)
} else {
data.terminator().successors()
};
self.visit_stack.push((bb, successors)); self.visit_stack.push((bb, successors));
} }
@ -198,10 +200,7 @@ where
} }
} }
impl<'tcx, C> Iterator for Postorder<'_, 'tcx, C> impl<'tcx> Iterator for Postorder<'_, 'tcx> {
where
C: Customization<'tcx>,
{
type Item = BasicBlock; type Item = BasicBlock;
fn next(&mut self) -> Option<BasicBlock> { fn next(&mut self) -> Option<BasicBlock> {
@ -241,32 +240,12 @@ pub fn postorder<'a, 'tcx>(
reverse_postorder(body).rev() reverse_postorder(body).rev()
} }
/// Lets us plug in some additional logic and data into a Postorder traversal. Or not.
pub trait Customization<'tcx>: Copy {
fn successors<'a>(_: &'a BasicBlockData<'tcx>, _: Self) -> Successors<'a>;
}
impl<'tcx> Customization<'tcx> for () {
fn successors<'a>(data: &'a BasicBlockData<'tcx>, _: ()) -> Successors<'a> {
data.terminator().successors()
}
}
impl<'tcx> Customization<'tcx> for (TyCtxt<'tcx>, Instance<'tcx>) {
fn successors<'a>(
data: &'a BasicBlockData<'tcx>,
(tcx, instance): (TyCtxt<'tcx>, Instance<'tcx>),
) -> Successors<'a> {
data.mono_successors(tcx, instance)
}
}
pub fn mono_reachable_reverse_postorder<'a, 'tcx>( pub fn mono_reachable_reverse_postorder<'a, 'tcx>(
body: &'a Body<'tcx>, body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>, instance: Instance<'tcx>,
) -> Vec<BasicBlock> { ) -> Vec<BasicBlock> {
let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, (tcx, instance)); let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, Some((tcx, instance)));
let mut items = Vec::with_capacity(body.basic_blocks.len()); let mut items = Vec::with_capacity(body.basic_blocks.len());
while let Some(block) = iter.next() { while let Some(block) = iter.next() {
items.push(block); items.push(block);

View file

@ -30,7 +30,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -
locals.len() locals.len()
]; ];
traversal::Postorder::new(&mir.basic_blocks, location.block, ()) traversal::Postorder::new(&mir.basic_blocks, location.block, None)
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()
.rev() .rev()