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:
parent
5986ff05d8
commit
cae9ebbe1e
3 changed files with 15 additions and 36 deletions
|
@ -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
|
||||||
})
|
})
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue