Eliminate call stack recursion in VirtRegs::find (#584)

* Eliminate call stack recursion in VirtRegs::find
This commit is contained in:
oooooba
2018-11-15 05:58:50 +09:00
committed by Dan Gohman
parent 5baeed06bb
commit 155fd4c72a

View File

@@ -291,21 +291,23 @@ impl UFEntry {
impl VirtRegs {
/// Find the leader value and rank of the set containing `v`.
/// Compress the path if needed.
fn find(&mut self, val: Value) -> (Value, u32) {
fn find(&mut self, mut val: Value) -> (Value, u32) {
let mut val_stack = vec![];
let found = loop {
match UFEntry::decode(self.union_find[val]) {
UFEntry::Rank(rank) => (val, rank),
UFEntry::Rank(rank) => break (val, rank),
UFEntry::Link(parent) => {
// TODO: This recursion would be more efficient as an iteration that pushes
// elements onto a SmallVector.
let found = self.find(parent);
// Compress the path if needed.
if found.0 != parent {
val_stack.push(val);
val = parent;
}
}
};
// Compress the path
while let Some(val) = val_stack.pop() {
self.union_find[val] = UFEntry::encode_link(found.0);
}
found
}
}
}
/// Union the two sets containing `a` and `b`.
///