diff --git a/lang/src/son.rs b/lang/src/son.rs index 627361b5..6697eb30 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -314,6 +314,7 @@ impl Nodes { ); for &block in &*cfg_nodes { + debug_assert!(block != VOID); seen.clear(self.values.len()); let mut outputs = mem::take(&mut self[block].outputs); self.reschedule_block(block, &mut outputs, buf, seen); @@ -719,7 +720,6 @@ impl Nodes { self.bind(from, to); } - bind_buf.clear(); self[VOID].outputs = self[VOID].outputs.iter().filter(|&&n| self[n].kind.is_at_start()).copied().collect(); @@ -736,8 +736,8 @@ impl Nodes { self[shed].outputs.push(n); } + bind_buf.clear(); scratch.clear(); - visited.clear(self.values.len()); self.schedule_inside_blocks(bind_buf, scratch, visited); } diff --git a/lang/src/son/hbvm/regalloc.rs b/lang/src/son/hbvm/regalloc.rs index 1aa395f7..2fe62f06 100644 --- a/lang/src/son/hbvm/regalloc.rs +++ b/lang/src/son/hbvm/regalloc.rs @@ -1,9 +1,12 @@ use { crate::{ - parser, + parser, quad_sort, son::{ debug_assert_matches, - hbvm::{reg, reg::Reg, HbvmBackend, Nid, Nodes, PLoc}, + hbvm::{ + reg::{self, Reg}, + HbvmBackend, Nid, Nodes, PLoc, + }, Kind, ARG_START, MEM, VOID, }, ty::{self, Arg, Loc}, @@ -11,7 +14,7 @@ use { Sig, Types, }, alloc::{borrow::ToOwned, vec::Vec}, - core::{mem, ops::Range}, + core::{mem, ops::Range, u8, usize}, hbbytecode::{self as instrs}, }; @@ -167,32 +170,65 @@ impl HbvmBackend { moves.len() }); - moves.sort_unstable_by(|[aa, ab, _], [ba, bb, _]| { - if aa == bb && ab == ba { - core::cmp::Ordering::Equal - } else if aa == bb { - core::cmp::Ordering::Greater - } else { - core::cmp::Ordering::Less - } - }); + let mut graph = [u8::MAX; 256]; + for &[d, s, _] in moves.iter() { + graph[d as usize] = s; + } - moves.dedup_by(|[aa, ab, _], [ba, bb, kind]| { - if aa == bb && ab == ba { - *kind = 1; - true - } else { - false - } - }); + // [3, 2, 0] - for [dst, src, kind] in moves { - if kind == 0 { - self.emit(instrs::cp(dst, src)); - } else { - self.emit(instrs::swa(dst, src)); + // cp 0, 1 = 3 + // cp 1, 2 = 2 + // cp 2, 0 = 1 + // + // swp a, b + // swp b, c + + // cp a, b + // cp b, c + // cp c, d + // cp d, a + // + // swp a, b + // swp b, c + // swp c, d + + 'o: for &mut [d, s, ref mut depth] in moves.iter_mut() { + let mut c = s; + loop { + if c == d { + break; + } + + c = graph[c as usize]; + *depth += 1; + + if c == u8::MAX { + continue 'o; + } + } + + // cut the cycle + graph[c as usize] = u8::MAX; + // mark cycyle + *depth = u8::MAX; + } + + quad_sort(&mut moves, |a, b| a[2].cmp(&b[2]).reverse()); + + for [mut d, mut s, depth] in moves { + if depth == u8::MAX { + while graph[s as usize] != u8::MAX { + self.emit(instrs::swa(d, s)); + d = s; + mem::swap(&mut graph[s as usize], &mut s); + } + graph[s as usize] = s; + } else if graph[s as usize] != s { + self.emit(instrs::cp(d, s)); } } + is_next_block = res.backrefs[nid as usize] as usize == i + 1; } Kind::Return { .. } => { diff --git a/lang/tests/son_tests_fb_driver.txt b/lang/tests/son_tests_fb_driver.txt index 76ff70fb..c26958b8 100644 --- a/lang/tests/son_tests_fb_driver.txt +++ b/lang/tests/son_tests_fb_driver.txt @@ -14,9 +14,9 @@ main: CP r35, r0 LI64 r36, 30d LI64 r37, 100d - CP r34, r35 - CP r33, r35 CP r32, r35 + CP r33, r35 + CP r34, r35 5: JLTU r34, r36, :0 ADDI64 r32, r32, 1d CP r2, r35 diff --git a/lang/tests/son_tests_generic_types.txt b/lang/tests/son_tests_generic_types.txt index 0801485f..6ff4f3b9 100644 --- a/lang/tests/son_tests_generic_types.txt +++ b/lang/tests/son_tests_generic_types.txt @@ -172,8 +172,8 @@ push: ADDI64 r33, r32, 1d LD r32, r32, 0a, 1h ST r32, r34, 0a, 1h - CP r34, r36 CP r32, r33 + CP r34, r36 JMP :7 0: LD r32, r38, 0a, 8h LD r33, r38, 8a, 8h @@ -228,8 +228,8 @@ push: ADDI64 r33, r32, 8d LD r32, r32, 0a, 8h ST r32, r34, 0a, 8h - CP r34, r36 CP r32, r33 + CP r34, r36 JMP :7 0: LD r32, r38, 8a, 8h MULI64 r33, r32, 8d diff --git a/lang/tests/son_tests_loops.txt b/lang/tests/son_tests_loops.txt index de4541c5..eaf226dd 100644 --- a/lang/tests/son_tests_loops.txt +++ b/lang/tests/son_tests_loops.txt @@ -2,8 +2,8 @@ fib: CP r13, r2 LI64 r17, 1d CP r15, r0 - CP r16, r17 CP r14, r15 + CP r16, r17 2: JNE r13, r15, :0 CP r1, r14 JMP :1 diff --git a/lang/tests/son_tests_struct_patterns.txt b/lang/tests/son_tests_struct_patterns.txt index 55d641d3..6e8ec9cd 100644 --- a/lang/tests/son_tests_struct_patterns.txt +++ b/lang/tests/son_tests_struct_patterns.txt @@ -23,8 +23,8 @@ fib_iter: CP r13, r2 LI64 r17, 1d CP r15, r0 - CP r16, r17 CP r14, r15 + CP r16, r17 2: JNE r13, r15, :0 CP r1, r14 JMP :1