Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 9ba0ca9

Browse files
committed
Deduplicate Postorder logic
1 parent 04f2f63 commit 9ba0ca9

File tree

2 files changed

+39
-64
lines changed

2 files changed

+39
-64
lines changed

compiler/rustc_middle/src/mir/basic_blocks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl<'tcx> BasicBlocks<'tcx> {
7171
#[inline]
7272
pub fn reverse_postorder(&self) -> &[BasicBlock] {
7373
self.cache.reverse_postorder.get_or_init(|| {
74-
let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK).collect();
74+
let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, ()).collect();
7575
rpo.reverse();
7676
rpo
7777
})

compiler/rustc_middle/src/mir/traversal.rs

Lines changed: 38 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -104,36 +104,46 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
104104
/// ```
105105
///
106106
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
107-
pub struct Postorder<'a, 'tcx> {
107+
pub struct Postorder<'a, 'tcx, C> {
108108
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
109109
visited: BitSet<BasicBlock>,
110110
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
111111
root_is_start_block: bool,
112+
extra: C,
112113
}
113114

114-
impl<'a, 'tcx> Postorder<'a, 'tcx> {
115+
impl<'a, 'tcx, C> Postorder<'a, 'tcx, C>
116+
where
117+
C: Customization<'tcx>,
118+
{
115119
pub fn new(
116120
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
117121
root: BasicBlock,
118-
) -> Postorder<'a, 'tcx> {
122+
extra: C,
123+
) -> Postorder<'a, 'tcx, C> {
119124
let mut po = Postorder {
120125
basic_blocks,
121126
visited: BitSet::new_empty(basic_blocks.len()),
122127
visit_stack: Vec::new(),
123128
root_is_start_block: root == START_BLOCK,
129+
extra,
124130
};
125131

126-
let data = &po.basic_blocks[root];
127-
128-
if let Some(ref term) = data.terminator {
129-
po.visited.insert(root);
130-
po.visit_stack.push((root, term.successors()));
131-
po.traverse_successor();
132-
}
132+
po.visit(root);
133+
po.traverse_successor();
133134

134135
po
135136
}
136137

138+
fn visit(&mut self, bb: BasicBlock) {
139+
if !self.visited.insert(bb) {
140+
return;
141+
}
142+
let data = &self.basic_blocks[bb];
143+
let successors = C::successors(data, self.extra);
144+
self.visit_stack.push((bb, successors));
145+
}
146+
137147
fn traverse_successor(&mut self) {
138148
// This is quite a complex loop due to 1. the borrow checker not liking it much
139149
// and 2. what exactly is going on is not clear
@@ -183,16 +193,15 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
183193
// since we've already visited `E`, that child isn't added to the stack. The last
184194
// two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A]
185195
while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) {
186-
if self.visited.insert(bb) {
187-
if let Some(term) = &self.basic_blocks[bb].terminator {
188-
self.visit_stack.push((bb, term.successors()));
189-
}
190-
}
196+
self.visit(bb);
191197
}
192198
}
193199
}
194200

195-
impl<'tcx> Iterator for Postorder<'_, 'tcx> {
201+
impl<'tcx, C> Iterator for Postorder<'_, 'tcx, C>
202+
where
203+
C: Customization<'tcx>,
204+
{
196205
type Item = BasicBlock;
197206

198207
fn next(&mut self) -> Option<BasicBlock> {
@@ -232,57 +241,23 @@ pub fn postorder<'a, 'tcx>(
232241
reverse_postorder(body).rev()
233242
}
234243

235-
struct MonoReachablePostorder<'a, 'tcx> {
236-
basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
237-
visited: BitSet<BasicBlock>,
238-
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
239-
tcx: TyCtxt<'tcx>,
240-
instance: Instance<'tcx>,
244+
/// Lets us plug in some additional logic and data into a Postorder traversal. Or not.
245+
pub trait Customization<'tcx>: Copy {
246+
fn successors<'a>(_: &'a BasicBlockData<'tcx>, _: Self) -> Successors<'a>;
241247
}
242248

243-
impl<'a, 'tcx> MonoReachablePostorder<'a, 'tcx> {
244-
fn new(
245-
body: &'a Body<'tcx>,
246-
tcx: TyCtxt<'tcx>,
247-
instance: Instance<'tcx>,
248-
) -> MonoReachablePostorder<'a, 'tcx> {
249-
let basic_blocks = &body.basic_blocks;
250-
let mut po = MonoReachablePostorder {
251-
basic_blocks,
252-
visited: BitSet::new_empty(basic_blocks.len()),
253-
visit_stack: Vec::new(),
254-
tcx,
255-
instance,
256-
};
257-
258-
po.visit(START_BLOCK);
259-
po.traverse_successor();
260-
po
261-
}
262-
263-
fn visit(&mut self, bb: BasicBlock) {
264-
if !self.visited.insert(bb) {
265-
return;
266-
}
267-
let data = &self.basic_blocks[bb];
268-
let successors = data.mono_successors(self.tcx, self.instance);
269-
self.visit_stack.push((bb, successors));
270-
}
271-
272-
fn traverse_successor(&mut self) {
273-
while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) {
274-
self.visit(bb);
275-
}
249+
impl<'tcx> Customization<'tcx> for () {
250+
fn successors<'a>(data: &'a BasicBlockData<'tcx>, _: ()) -> Successors<'a> {
251+
data.terminator().successors()
276252
}
277253
}
278254

279-
impl<'tcx> Iterator for MonoReachablePostorder<'_, 'tcx> {
280-
type Item = BasicBlock;
281-
282-
fn next(&mut self) -> Option<BasicBlock> {
283-
let (bb, _) = self.visit_stack.pop()?;
284-
self.traverse_successor();
285-
Some(bb)
255+
impl<'tcx> Customization<'tcx> for (TyCtxt<'tcx>, Instance<'tcx>) {
256+
fn successors<'a>(
257+
data: &'a BasicBlockData<'tcx>,
258+
(tcx, instance): (TyCtxt<'tcx>, Instance<'tcx>),
259+
) -> Successors<'a> {
260+
data.mono_successors(tcx, instance)
286261
}
287262
}
288263

@@ -291,7 +266,7 @@ pub fn mono_reachable_reverse_postorder<'a, 'tcx>(
291266
tcx: TyCtxt<'tcx>,
292267
instance: Instance<'tcx>,
293268
) -> Vec<BasicBlock> {
294-
let mut iter = MonoReachablePostorder::new(body, tcx, instance);
269+
let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, (tcx, instance));
295270
let mut items = Vec::with_capacity(body.basic_blocks.len());
296271
while let Some(block) = iter.next() {
297272
items.push(block);

0 commit comments

Comments
 (0)