Skip to content

Commit e5dfa99

Browse files
committed
ZJIT: Remove Option<T> from UnionFind
We can have it fixpoint at nodes pointing to themselves instead. This also saves space.
1 parent a8f3c34 commit e5dfa99

1 file changed

Lines changed: 39 additions & 19 deletions

File tree

zjit/src/hir.rs

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ impl From<InsnId> for usize {
3636
}
3737
}
3838

39+
impl From<usize> for InsnId {
40+
fn from(val: usize) -> Self {
41+
InsnId(val)
42+
}
43+
}
44+
3945
impl std::fmt::Display for InsnId {
4046
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4147
write!(f, "v{}", self.0)
@@ -2273,28 +2279,28 @@ impl<'a> FunctionGraphvizPrinter<'a> {
22732279
/// in missing optimizations.
22742280
#[derive(Debug)]
22752281
struct UnionFind<T: Copy + Into<usize>> {
2276-
forwarded: Vec<Option<T>>,
2282+
forwarded: Vec<T>,
22772283
}
22782284

2279-
impl<T: Copy + Into<usize> + PartialEq> UnionFind<T> {
2285+
impl<T: Copy + Into<usize> + PartialEq + std::convert::From<usize>> UnionFind<T> {
22802286
fn new() -> UnionFind<T> {
22812287
UnionFind { forwarded: vec![] }
22822288
}
22832289

22842290
/// Private. Return the internal representation of the forwarding pointer for a given element.
2285-
fn at(&self, idx: T) -> Option<T> {
2286-
self.forwarded.get(idx.into()).copied().flatten()
2291+
fn at(&self, idx: T) -> T {
2292+
self.forwarded.get(idx.into()).unwrap_or(&idx).to_owned()
22872293
}
22882294

22892295
/// Private. Set the internal representation of the forwarding pointer for the given element
22902296
/// `idx`. Extend the internal vector if necessary.
22912297
fn set(&mut self, idx: T, value: T) {
22922298
if idx.into() >= self.forwarded.len() {
2293-
self.forwarded.resize(idx.into()+1, None);
2294-
}
2295-
if idx != value {
2296-
self.forwarded[idx.into()] = Some(value);
2299+
for i in self.forwarded.len()..=idx.into() {
2300+
self.forwarded.push(i.into());
2301+
}
22972302
}
2303+
self.forwarded[idx.into()] = value;
22982304
}
22992305

23002306
/// Find the set representative for `insn`. Perform path compression at the same time to speed
@@ -2321,21 +2327,18 @@ impl<T: Copy + Into<usize> + PartialEq> UnionFind<T> {
23212327
fn find_const(&self, insn: T) -> T {
23222328
let mut result = insn;
23232329
loop {
2324-
match self.at(result) {
2325-
None => return result,
2326-
Some(insn) => {
2327-
assert!(result != insn, "cycle detected");
2328-
result = insn;
2329-
}
2330-
}
2330+
let found = self.at(result);
2331+
if found == result { return found; }
2332+
result = found;
23312333
}
23322334
}
23332335

23342336
/// Union the two sets containing `insn` and `target` such that every element in `insn`s set is
23352337
/// now part of `target`'s. Neither argument must be the representative in its set.
23362338
pub fn make_equal_to(&mut self, insn: T, target: T) {
2337-
let found = self.find(insn);
2338-
self.set(found, target);
2339+
let insn = self.find(insn);
2340+
let target = self.find(target);
2341+
self.set(insn, target);
23392342
}
23402343
}
23412344

@@ -8906,6 +8909,12 @@ mod union_find_tests {
89068909
assert_eq!(uf.find(3usize), 4);
89078910
}
89088911

8912+
#[test]
8913+
fn test_find_with_unknown_element_returns_self() {
8914+
let mut uf = UnionFind::new();
8915+
assert_eq!(uf.find(10usize), 10);
8916+
}
8917+
89098918
#[test]
89108919
fn test_find_halts_with_identity_make_equal_to() {
89118920
let mut uf = UnionFind::<usize>::new();
@@ -8927,9 +8936,20 @@ mod union_find_tests {
89278936
let mut uf = UnionFind::new();
89288937
uf.make_equal_to(3, 4);
89298938
uf.make_equal_to(4, 5);
8930-
assert_eq!(uf.at(3usize), Some(4));
8939+
assert_eq!(uf.at(3usize), 4);
89318940
assert_eq!(uf.find(3usize), 5);
8932-
assert_eq!(uf.at(3usize), Some(5));
8941+
assert_eq!(uf.at(3usize), 5);
8942+
}
8943+
8944+
#[test]
8945+
fn test_make_equal_to_does_not_create_cycles() {
8946+
let mut uf = UnionFind::new();
8947+
uf.make_equal_to(3, 4);
8948+
uf.make_equal_to(4, 5);
8949+
uf.make_equal_to(5, 3);
8950+
assert_eq!(uf.find(3usize), 5);
8951+
assert_eq!(uf.find(4usize), 5);
8952+
assert_eq!(uf.find(5usize), 5);
89338953
}
89348954
}
89358955

0 commit comments

Comments
 (0)