Eliminate call stack recursion in VirtRegs::find (#584)
* Eliminate call stack recursion in VirtRegs::find
This commit is contained in:
@@ -291,21 +291,23 @@ impl UFEntry {
|
|||||||
impl VirtRegs {
|
impl VirtRegs {
|
||||||
/// Find the leader value and rank of the set containing `v`.
|
/// Find the leader value and rank of the set containing `v`.
|
||||||
/// Compress the path if needed.
|
/// 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]) {
|
match UFEntry::decode(self.union_find[val]) {
|
||||||
UFEntry::Rank(rank) => (val, rank),
|
UFEntry::Rank(rank) => break (val, rank),
|
||||||
UFEntry::Link(parent) => {
|
UFEntry::Link(parent) => {
|
||||||
// TODO: This recursion would be more efficient as an iteration that pushes
|
val_stack.push(val);
|
||||||
// elements onto a SmallVector.
|
val = parent;
|
||||||
let found = self.find(parent);
|
}
|
||||||
// Compress the path if needed.
|
}
|
||||||
if found.0 != parent {
|
};
|
||||||
|
// Compress the path
|
||||||
|
while let Some(val) = val_stack.pop() {
|
||||||
self.union_find[val] = UFEntry::encode_link(found.0);
|
self.union_find[val] = UFEntry::encode_link(found.0);
|
||||||
}
|
}
|
||||||
found
|
found
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Union the two sets containing `a` and `b`.
|
/// Union the two sets containing `a` and `b`.
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user