From 42a713aeaef11ca86d96083915191fbe456c47e5 Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Sun, 10 Nov 2024 09:17:43 +0100 Subject: [PATCH] fixing wrong instruction selection --- lang/src/son.rs | 42 ++- lang/src/son/hbvm.rs | 70 +++- lang/src/son/hbvm/my_regalloc.rs | 301 ++++++++---------- lang/src/son/hbvm/their_regalloc.rs | 76 +---- lang/tests/son_tests_idk.txt | 18 +- lang/tests/son_tests_inlining_issues.txt | 2 +- lang/tests/son_tests_string_flip.txt | 44 +-- .../tests/son_tests_tests_ptr_to_ptr_copy.txt | 36 +-- 8 files changed, 286 insertions(+), 303 deletions(-) diff --git a/lang/src/son.rs b/lang/src/son.rs index 04927448..2076cc82 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -450,7 +450,9 @@ impl Nodes { return self.idom(from); } - let index = self[from].inputs.iter().position(|&n| n == target).unwrap(); + let index = self[from].inputs.iter().position(|&n| n == target).unwrap_or_else(|| { + panic!("from {from} {:?} target {target} {:?}", self[from], self[target]) + }); self[self[from].inputs[0]].inputs[index - 1] } @@ -493,6 +495,8 @@ impl Nodes { self.load_loop_var(i, from_value, loops); self.load_loop_var(i, to_value, loops); if to_value.value() != from_value.value() { + debug_assert!(!to_value.ptr); + debug_assert!(!from_value.ptr); let inps = [ctrl.get(), from_value.value(), to_value.value()]; to_value.set_value_remove(self.new_node(from_value.ty, Kind::Phi, inps), self); } @@ -624,6 +628,8 @@ impl Nodes { node.ty.expand(), ); } + + debug_assert!(!matches!(node.ty.expand(), ty::Kind::Struct(_))); } let mut lookup_meta = None; @@ -1036,8 +1042,9 @@ impl Nodes { if self[lhs].kind == Kind::Stre && self[rhs].kind == Kind::Stre && self[lhs].ty == self[rhs].ty + && !matches!(self[lhs].ty.expand(), ty::Kind::Struct(_)) && self[lhs].inputs[2] == self[rhs].inputs[2] - && self[lhs].inputs.get(3) == self[rhs].inputs.get(3) + && self[lhs].inputs[3] == self[rhs].inputs[3] { let pick_value = self.new_node(self[lhs].ty, Kind::Phi, [ ctrl, @@ -1154,6 +1161,10 @@ impl Nodes { } } + if !unidentifed.is_empty() { + break 'eliminate; + } + debug_assert_matches!( self[last_store].kind, Kind::Stre | Kind::Mem, @@ -1167,10 +1178,6 @@ impl Nodes { self[first_store] ); - if !unidentifed.is_empty() { - break 'eliminate; - } - // FIXME: when the loads and stores become parallel we will need to get saved // differently let mut prev_store = store; @@ -1574,10 +1581,14 @@ impl Nodes { return; } + debug_assert!(!var.ptr); + let [loops @ .., loob] = loops else { unreachable!() }; let node = loob.node; let lvar = &mut loob.scope.vars[index]; + debug_assert!(!lvar.ptr); + self.load_loop_var(index, lvar, loops); if !self[lvar.value()].is_lazy_phi(node) { @@ -1634,7 +1645,7 @@ impl Nodes { } } - fn dominates(&mut self, dominator: Nid, mut dominated: Nid) -> bool { + fn dominates(&self, dominator: Nid, mut dominated: Nid) -> bool { loop { if dominator == dominated { break true; @@ -1650,12 +1661,21 @@ impl Nodes { fn is_data_dep(&self, nid: Nid, n: Nid) -> bool { match self[n].kind { - _ if self.is_cfg(n) && !matches!(self[n].kind, Kind::Call { .. }) => false, + Kind::Return => self[n].inputs[1] == nid, + _ if self.is_cfg(n) && !matches!(self[n].kind, Kind::Call { .. } | Kind::If) => false, Kind::Stre => self[n].inputs[3] != nid, Kind::Load => self[n].inputs[2] != nid, _ => self[n].inputs[0] != nid || self[n].inputs[1..].contains(&nid), } } + + fn this_or_delegates<'a>(&'a self, source: Nid, target: &'a Nid) -> (Nid, &'a [Nid]) { + if self[*target].lock_rc == 0 { + (source, core::slice::from_ref(target)) + } else { + (*target, self[*target].outputs.as_slice()) + } + } } enum CondOptRes { @@ -3509,7 +3529,9 @@ impl<'a> Codegen<'a> { }); for var in self.ci.scope.vars.iter_mut().skip(self.ci.inline_var_base) { - var.set_value(VOID, &mut self.ci.nodes); + if !var.ptr { + var.set_value(VOID, &mut self.ci.nodes); + } } for aclass in self.ci.scope.aclasses[..2].iter_mut() { @@ -4612,6 +4634,8 @@ mod tests { if let Err(e) = err { writeln!(output, "!!! asm is invalid: {e}").unwrap(); } else { + log::info!("================ running {ident} =============="); + log::trace!("{output}"); super::hbvm::test_run_vm(&out, output); } } diff --git a/lang/src/son/hbvm.rs b/lang/src/son/hbvm.rs index 12e910a4..1c06b937 100644 --- a/lang/src/son/hbvm.rs +++ b/lang/src/son/hbvm.rs @@ -5,7 +5,7 @@ use { parser, reg, son::{debug_assert_matches, write_reloc, Kind, MEM}, ty::{self, Loc, Module}, - utils::{Ent, EntVec}, + utils::{BitSet, Ent, EntVec, Vc}, Offset, Reloc, Size, TypedReloc, Types, }, alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec}, @@ -332,6 +332,72 @@ impl Backend for HbvmBackend { } impl Nodes { + fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) { + // NOTE: this code is horible + let from = Some(&from); + let mut buf = Vec::with_capacity(outputs.len()); + let mut seen = BitSet::default(); + seen.clear(self.values.len()); + + for &o in outputs.iter() { + if !self.is_cfg(o) { + continue; + } + + seen.set(o); + + let mut cursor = buf.len(); + buf.push(o); + while let Some(&n) = buf.get(cursor) { + for &i in &self[n].inputs[1..] { + if from == self[i].inputs.first() + && self[i] + .outputs + .iter() + .all(|&o| self[o].inputs.first() != from || seen.get(o)) + && seen.set(i) + { + for &o in outputs.iter().filter(|&&n| n == i) { + buf.push(o); + } + } + } + cursor += 1; + } + } + + for &o in outputs.iter() { + if !seen.set(o) { + continue; + } + let mut cursor = buf.len(); + for &o in outputs.iter().filter(|&&n| n == o) { + buf.push(o); + } + while let Some(&n) = buf.get(cursor) { + for &i in &self[n].inputs[1..] { + if from == self[i].inputs.first() + && self[i] + .outputs + .iter() + .all(|&o| self[o].inputs.first() != from || seen.get(o)) + && seen.set(i) + { + for &o in outputs.iter().filter(|&&n| n == i) { + buf.push(o); + } + } + } + cursor += 1; + } + } + + if outputs.len() != buf.len() { + panic!("{:?} {:?}", outputs, buf); + } + outputs.copy_from_slice(&buf); + } + fn is_never_used(&self, nid: Nid, tys: &Types) -> bool { let node = &self[nid]; match node.kind { @@ -485,7 +551,7 @@ impl TokenKind { Self::Band => return Some(andi), Self::Bor => return Some(ori), Self::Xor => return Some(xori), - Self::Shr if signed => basic_op!(srui8, srui16, srui32, srui64), + Self::Shr if signed => basic_op!(srsi8, srsi16, srsi32, srsi64), Self::Shr => basic_op!(srui8, srui16, srui32, srui64), Self::Shl => basic_op!(slui8, slui16, slui32, slui64), _ => return None, diff --git a/lang/src/son/hbvm/my_regalloc.rs b/lang/src/son/hbvm/my_regalloc.rs index aa926c9d..8dd96384 100644 --- a/lang/src/son/hbvm/my_regalloc.rs +++ b/lang/src/son/hbvm/my_regalloc.rs @@ -6,7 +6,7 @@ use { reg::{self, Reg}, son::{debug_assert_matches, Kind, ARG_START, MEM, VOID}, ty::{self, Arg, Loc}, - utils::{BitSet, Vc}, + utils::BitSet, Offset, PLoc, Reloc, Sig, TypedReloc, Types, }, alloc::{borrow::ToOwned, vec::Vec}, @@ -22,9 +22,16 @@ impl HbvmBackend { tys: &Types, files: &[parser::Ast], ) -> (usize, bool) { - let mut fuc = Function::new(nodes, tys, sig); + let fuc = Function::new(nodes, tys, sig); log::info!("{fuc:?}"); + let strip_load = |value| match fuc.nodes[value].kind { + Kind::Load { .. } if fuc.nodes[value].ty.loc(tys) == Loc::Stack => { + fuc.nodes[value].inputs[1] + } + _ => value, + }; + let mut res = mem::take(&mut self.ralloc_my); Env::new(&fuc, &fuc.func, &mut res).run(); @@ -39,13 +46,27 @@ impl HbvmBackend { let reg_offset = if fuc.tail { reg::RET + 12 } else { reg::RET_ADDR + 1 }; res.node_to_reg.iter_mut().filter(|r| **r != 0).for_each(|r| { - *r += reg_offset - 1; - if fuc.tail && *r >= reg::RET_ADDR { - *r += 1; + if *r == u8::MAX { + *r = 0 + } else { + *r += reg_offset - 1; + if fuc.tail && *r >= reg::RET_ADDR { + *r += 1; + } } }); - let atr = |allc: Nid| res.node_to_reg[allc as usize]; + let atr = |allc: Nid| { + let allc = strip_load(allc); + debug_assert_eq!( + fuc.nodes[allc].lock_rc, + 0, + "{:?} {}", + fuc.nodes[allc], + ty::Display::new(tys, files, fuc.nodes[allc].ty) + ); + res.node_to_reg[allc as usize] + }; //for (id, node) in fuc.nodes.iter() { // if node.kind == Kind::Phi { @@ -84,8 +105,6 @@ impl HbvmBackend { } let node = &fuc.nodes[nid]; - let bref = mem::replace(&mut fuc.backrefs[nid as usize], u16::MAX); - let extend = |base: ty::Id, dest: ty::Id, from: Nid, to: Nid| { let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest)); debug_assert!(bsize <= 8, "{}", ty::Display::new(tys, files, base)); @@ -141,96 +160,79 @@ impl HbvmBackend { cnd, )); let rel = Reloc::new(self.code.len(), 3, 2); + debug_assert_eq!(fuc.nodes[node.outputs[0]].kind, Kind::Then); self.jump_relocs.push((node.outputs[0], rel)); self.emit(instrs::jne(atr(cnd), reg::ZERO, 0)); } } Kind::Loop | Kind::Region => { - let mut emit_moves = |index| { - let mut moves = vec![]; - for &out in node.outputs.iter() { - if fuc.nodes[out].is_data_phi() { - debug_assert_eq!( - fuc.backrefs[fuc.nodes[out].inputs[index] as usize], - u16::MAX, - "{:?}\n{:?}", - node, - fuc.nodes[fuc.nodes[out].inputs[index]] - ); - if atr(out) != atr(fuc.nodes[out].inputs[index]) { - if atr(out) == 34 && atr(fuc.nodes[out].inputs[index]) == 32 - { - std::dbg!(&node, out, &fuc.nodes[out]); - } - moves.push([ - atr(out), - atr(fuc.nodes[out].inputs[index]), - 0, - ]); - } + let index = node + .inputs + .iter() + .position(|&n| block.entry == fuc.idom_of(n)) + .unwrap() + + 1; + + let mut moves = vec![]; + for &out in node.outputs.iter() { + if fuc.nodes[out].is_data_phi() { + let src = fuc.nodes[out].inputs[index]; + if atr(out) != atr(src) { + moves.push([atr(out), atr(src), 0]); } } + } - 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 - } - }); + debug_assert_eq!(moves.len(), { + moves.sort_unstable(); + moves.dedup(); + moves.len() + }); - moves.dedup_by(|[aa, ab, _], [ba, bb, kind]| { - if aa == bb && ab == ba { - *kind = 1; - true - } else { - false - } - }); - - for [dst, src, kind] in moves { - if kind == 0 { - self.emit(instrs::cp(dst, src)); - } else { - self.emit(instrs::swa(dst, src)); - } + 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 } - }; + }); - if (bref != u16::MAX) ^ (node.kind == Kind::Loop) { - let index = (node.kind == Kind::Loop) as usize + 1; - emit_moves(index); + moves.dedup_by(|[aa, ab, _], [ba, bb, kind]| { + if aa == bb && ab == ba { + *kind = 1; + true + } else { + false + } + }); + for [dst, src, kind] in moves { + if kind == 0 { + self.emit(instrs::cp(dst, src)); + } else { + self.emit(instrs::swa(dst, src)); + } + } + + if fuc.block_of(nid) as usize != i + 1 { let rel = Reloc::new(self.code.len(), 1, 4); self.jump_relocs.push((nid, rel)); self.emit(instrs::jmp(0)); - } else { - let index = (node.kind != Kind::Loop) as usize + 1; - emit_moves(index); } } Kind::Return => { - let &[_, mut ret, ..] = node.inputs.as_slice() else { unreachable!() }; + let &[_, ret, ..] = node.inputs.as_slice() else { unreachable!() }; match retl { None => {} Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => { self.emit(instrs::cp(r, atr(ret))); } Some(PLoc::Reg(r, size)) | Some(PLoc::WideReg(r, size)) => { - ret = match fuc.nodes[ret].kind { - Kind::Load { .. } => fuc.nodes[ret].inputs[1], - _ => ret, - }; self.emit(instrs::ld(r, atr(ret), 0, size)) } Some(PLoc::Ref(_, size)) => { - ret = match fuc.nodes[ret].kind { - Kind::Load { .. } => fuc.nodes[ret].inputs[1], - _ => ret, - }; - let [src, dst] = [atr(ret), atr(MEM)]; if let Ok(size) = u16::try_from(size) { self.emit(instrs::bmc(src, dst, size)); @@ -340,10 +342,6 @@ impl HbvmBackend { PLoc::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size), PLoc::WideReg(rg, size) => (rg, size), PLoc::Ref(r, ..) => { - arg = match fuc.nodes[arg].kind { - Kind::Load { .. } => fuc.nodes[arg].inputs[1], - _ => arg, - }; self.emit(instrs::cp(r, atr(arg))); continue; } @@ -353,10 +351,6 @@ impl HbvmBackend { } }; - arg = match fuc.nodes[arg].kind { - Kind::Load { .. } => fuc.nodes[arg].inputs[1], - _ => arg, - }; self.emit(instrs::ld(rg, atr(arg), 0, size)); } @@ -364,6 +358,10 @@ impl HbvmBackend { !matches!(ret, Some(PLoc::Ref(..))) || allocs.next().is_some() ); + if let Some(PLoc::Ref(r, ..)) = ret { + self.emit(instrs::cp(r, atr(*node.inputs.last().unwrap()))) + } + if func == ty::Func::ECA { self.emit(instrs::eca()); } else { @@ -434,9 +432,10 @@ impl HbvmBackend { let mut region = node.inputs[2]; let mut offset = 0; let size = u16::try_from(tys.size_of(node.ty)).expect("TODO"); - if fuc.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add }) - && let Kind::CInt { value } = - fuc.nodes[fuc.nodes[region].inputs[2]].kind + if matches!(fuc.nodes[region].kind, Kind::BinOp { + op: TokenKind::Add | TokenKind::Sub + }) && let Kind::CInt { value } = + fuc.nodes[fuc.nodes[region].inputs[2]].kind && node.ty.loc(tys) == Loc::Reg { region = fuc.nodes[region].inputs[1]; @@ -448,10 +447,7 @@ impl HbvmBackend { Kind::Stck if node.ty.loc(tys) == Loc::Reg => { (reg::STACK_PTR, self.offsets[region as usize] + offset, value) } - _ => (atr(region), offset, match fuc.nodes[value].kind { - Kind::Load { .. } => fuc.nodes[value].inputs[1], - _ => value, - }), + _ => (atr(region), offset, value), }; match node.ty.loc(tys) { @@ -507,7 +503,7 @@ impl Function<'_> { self.nodes.values.len() } - fn uses_of(&self, nid: Nid, buf: &mut Vec) { + fn uses_of(&self, nid: Nid, buf: &mut Vec<(Nid, Nid)>) { if self.nodes[nid].kind.is_cfg() && !matches!(self.nodes[nid].kind, Kind::Call { .. }) { return; } @@ -516,9 +512,22 @@ impl Function<'_> { .outputs .iter() .filter(|&&n| self.nodes.is_data_dep(nid, n)) + .map(|n| self.nodes.this_or_delegates(nid, n)) + .flat_map(|(p, ls)| ls.iter().map(move |l| (p, l))) + .filter(|&(o, &n)| self.nodes.is_data_dep(o, n)) + .map(|(p, &n)| (self.use_block(p, n), n)) + .inspect(|&(_, n)| debug_assert_eq!(self.nodes[n].lock_rc, 0)) .collect_into(buf); } + fn use_block(&self, inst: Nid, uinst: Nid) -> Nid { + let mut block = self.nodes.use_block(inst, uinst); + while !self.nodes[block].kind.starts_basic_block() { + block = self.nodes.idom(block); + } + block + } + fn phi_inputs_of(&self, nid: Nid, buf: &mut Vec) { match self.nodes[nid].kind { Kind::Region => { @@ -561,14 +570,6 @@ impl Function<'_> { } nid } - - fn use_block(&self, inst: Nid, uinst: Nid) -> Nid { - let mut block = self.nodes.use_block(inst, uinst); - while !self.nodes[block].kind.starts_basic_block() { - block = self.nodes.idom(block); - } - block - } } impl core::fmt::Debug for Function<'_> { @@ -654,8 +655,11 @@ impl<'a> Function<'a> { if let Kind::BinOp { op } = self.nodes[cond].kind && let Some((_, swapped)) = op.cond_op(node.ty) - && swapped { + if swapped { + mem::swap(&mut then, &mut else_); + } + } else { mem::swap(&mut then, &mut else_); } @@ -666,7 +670,7 @@ impl<'a> Function<'a> { Kind::Region | Kind::Loop => { self.close_block(nid); self.add_block(nid); - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { self.emit_node(o); } @@ -693,14 +697,14 @@ impl<'a> Function<'a> { self.add_instr(MEM); } - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { self.emit_node(o); } } Kind::Then | Kind::Else => { self.add_block(nid); - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { self.emit_node(o); } @@ -710,7 +714,7 @@ impl<'a> Function<'a> { self.add_instr(nid); - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { if self.nodes[o].inputs[0] == nid || (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region) @@ -731,72 +735,6 @@ impl<'a> Function<'a> { Kind::Assert { .. } => unreachable!(), } } - - fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) { - let from = Some(&from); - let mut buf = Vec::with_capacity(outputs.len()); - let mut seen = BitSet::default(); - seen.clear(self.nodes.values.len()); - - for &o in outputs.iter() { - if !self.nodes.is_cfg(o) { - continue; - } - - seen.set(o); - - let mut cursor = buf.len(); - buf.push(o); - while let Some(&n) = buf.get(cursor) { - for &i in &self.nodes[n].inputs[1..] { - if from == self.nodes[i].inputs.first() - && self.nodes[i] - .outputs - .iter() - .all(|&o| self.nodes[o].inputs.first() != from || seen.get(o)) - && seen.set(i) - { - buf.push(i); - } - } - cursor += 1; - } - } - - for &o in outputs.iter() { - if !seen.set(o) { - continue; - } - let mut cursor = buf.len(); - buf.push(o); - while let Some(&n) = buf.get(cursor) { - for &i in &self.nodes[n].inputs[1..] { - if from == self.nodes[i].inputs.first() - && self.nodes[i] - .outputs - .iter() - .all(|&o| self.nodes[o].inputs.first() != from || seen.get(o)) - && seen.set(i) - { - buf.push(i); - } - } - cursor += 1; - } - } - - debug_assert!( - outputs.len() == buf.len() || outputs.len() == buf.len() + 1, - "{:?} {:?}", - outputs, - buf - ); - - if buf.len() + 1 == outputs.len() { - outputs.remove(outputs.len() - 1); - } - outputs.copy_from_slice(&buf); - } } pub struct Env<'a> { @@ -845,26 +783,37 @@ impl<'a> Env<'a> { self.res.use_buf = use_buf; } - fn append_bundle(&mut self, inst: Nid, bundle: &mut Bundle, use_buf: &mut Vec) { + fn append_bundle(&mut self, inst: Nid, bundle: &mut Bundle, use_buf: &mut Vec<(Nid, Nid)>) { let dom = self.ctx.idom_of(inst); self.ctx.uses_of(inst, use_buf); - for uinst in use_buf.drain(..) { - let cursor = self.ctx.use_block(inst, uinst); + for (cursor, uinst) in use_buf.drain(..) { self.reverse_cfg_dfs(cursor, dom, |_, n, b| { let mut range = b.range.clone(); + debug_assert!(range.start < range.end); range.start = range.start.max(self.ctx.instr_of(inst).map_or(0, |n| n + 1) as usize); + debug_assert!(range.start < range.end, "{:?}", range); range.end = range.end.min( self.ctx .instr_of(uinst) - .filter(|_| self.ctx.nodes.loop_depth(dom) == self.ctx.nodes.loop_depth(n)) + .filter(|_| { + n == cursor + && self.ctx.nodes.loop_depth(dom) + == self.ctx.nodes.loop_depth(cursor) + }) .map_or(Nid::MAX, |n| n + 1) as usize, ); + debug_assert!(range.start < range.end); bundle.add(range); }); } + if !bundle.taken.contains(&true) { + self.res.node_to_reg[inst as usize] = u8::MAX; + return; + } + match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) { Some((i, other)) => { other.merge(bundle); @@ -888,7 +837,14 @@ impl<'a> Env<'a> { self.res.dfs_buf.push(from); self.res.dfs_seem.clear(self.ctx.nodes.values.len()); + debug_assert!(self.ctx.nodes.dominates(until, from)); + while let Some(nid) = self.res.dfs_buf.pop() { + debug_assert!( + self.ctx.nodes.dominates(until, nid), + "{until} {:?}", + self.ctx.nodes[until] + ); each(self, nid, &self.func.blocks[self.ctx.block_of(nid) as usize]); if nid == until { continue; @@ -896,6 +852,9 @@ impl<'a> Env<'a> { match self.ctx.nodes[nid].kind { Kind::Then | Kind::Else | Kind::Region | Kind::Loop => { for &n in self.ctx.nodes[nid].inputs.iter() { + if self.ctx.nodes[n].kind == Kind::Loops { + continue; + } let d = self.ctx.idom_of(n); if self.res.dfs_seem.set(d) { self.res.dfs_buf.push(d); @@ -913,7 +872,7 @@ impl<'a> Env<'a> { pub struct Res { pub bundles: Vec, pub node_to_reg: Vec, - use_buf: Vec, + use_buf: Vec<(Nid, Nid)>, phi_input_buf: Vec, dfs_buf: Vec, dfs_seem: BitSet, diff --git a/lang/src/son/hbvm/their_regalloc.rs b/lang/src/son/hbvm/their_regalloc.rs index 83210395..b98e8934 100644 --- a/lang/src/son/hbvm/their_regalloc.rs +++ b/lang/src/son/hbvm/their_regalloc.rs @@ -5,7 +5,7 @@ use { parser, reg, son::{debug_assert_matches, Kind, ARG_START, MEM, NEVER, VOID}, ty::{self, Arg, Loc}, - utils::{BitSet, Vc}, + utils::BitSet, HashMap, Offset, PLoc, Reloc, Sig, TypedReloc, Types, }, alloc::{borrow::ToOwned, vec::Vec}, @@ -616,7 +616,7 @@ impl<'a> Function<'a> { block.push(self.rg(ph)); } self.blocks[self.backrefs[nid as usize] as usize].params = block; - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { self.emit_node(o, nid); } @@ -680,7 +680,7 @@ impl<'a> Function<'a> { )]); } - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { self.emit_node(o, nid); } @@ -688,7 +688,7 @@ impl<'a> Function<'a> { Kind::Then | Kind::Else => { self.backrefs[nid as usize] = self.add_block(nid); self.bridge(prev, nid); - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { self.emit_node(o, nid); } @@ -783,7 +783,7 @@ impl<'a> Function<'a> { self.add_instr(nid, ops); - self.reschedule_block(nid, &mut node.outputs); + self.nodes.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { if self.nodes[o].inputs[0] == nid || (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region) @@ -853,72 +853,6 @@ impl<'a> Function<'a> { .preds .push(regalloc2::Block::new(self.backrefs[pred as usize] as usize)); } - - fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) { - // NOTE: this code is horible - let from = Some(&from); - let mut buf = Vec::with_capacity(outputs.len()); - let mut seen = BitSet::default(); - seen.clear(self.nodes.values.len()); - - for &o in outputs.iter() { - if !self.nodes.is_cfg(o) { - continue; - } - - seen.set(o); - - let mut cursor = buf.len(); - buf.push(o); - while let Some(&n) = buf.get(cursor) { - for &i in &self.nodes[n].inputs[1..] { - if from == self.nodes[i].inputs.first() - && self.nodes[i] - .outputs - .iter() - .all(|&o| self.nodes[o].inputs.first() != from || seen.get(o)) - && seen.set(i) - { - for &o in outputs.iter().filter(|&&n| n == i) { - buf.push(o); - } - } - } - cursor += 1; - } - } - - for &o in outputs.iter() { - if !seen.set(o) { - continue; - } - let mut cursor = buf.len(); - for &o in outputs.iter().filter(|&&n| n == o) { - buf.push(o); - } - while let Some(&n) = buf.get(cursor) { - for &i in &self.nodes[n].inputs[1..] { - if from == self.nodes[i].inputs.first() - && self.nodes[i] - .outputs - .iter() - .all(|&o| self.nodes[o].inputs.first() != from || seen.get(o)) - && seen.set(i) - { - for &o in outputs.iter().filter(|&&n| n == i) { - buf.push(o); - } - } - } - cursor += 1; - } - } - - if outputs.len() != buf.len() { - panic!("{:?} {:?}", outputs, buf); - } - outputs.copy_from_slice(&buf); - } } impl regalloc2::Function for Function<'_> { diff --git a/lang/tests/son_tests_idk.txt b/lang/tests/son_tests_idk.txt index b48669b1..542ebd2f 100644 --- a/lang/tests/son_tests_idk.txt +++ b/lang/tests/son_tests_idk.txt @@ -1,17 +1,17 @@ main: ADDI64 r254, r254, -128d - LI8 r5, 69b - LI64 r6, 128d + LI8 r6, 69b + LI64 r5, 128d LI64 r7, 0d ADDI64 r4, r254, 0d - 2: LD r12, r254, 42a, 1h - JLTU r7, r6, :0 - ANDI r1, r12, 255d + 2: LD r1, r254, 42a, 1h + JLTU r7, r5, :0 + ANDI r1, r1, 255d JMP :1 - 0: ADDI64 r3, r7, 1d - ADD64 r7, r4, r7 - ST r5, r7, 0a, 1h - CP r7, r3 + 0: ADDI64 r8, r7, 1d + ADD64 r3, r4, r7 + ST r6, r3, 0a, 1h + CP r7, r8 JMP :2 1: ADDI64 r254, r254, 128d JALA r0, r31, 0a diff --git a/lang/tests/son_tests_inlining_issues.txt b/lang/tests/son_tests_inlining_issues.txt index c4608ce9..896a6f59 100644 --- a/lang/tests/son_tests_inlining_issues.txt +++ b/lang/tests/son_tests_inlining_issues.txt @@ -95,8 +95,8 @@ put_filled_rect: CP r4, r33 CP r5, r44 ECA - ADD64 r42, r40, r42 SUB64 r41, r41, r40 + ADD64 r42, r40, r42 SUB64 r39, r39, r32 CP r6, r43 CP r8, r44 diff --git a/lang/tests/son_tests_string_flip.txt b/lang/tests/son_tests_string_flip.txt index 49787bdd..2bea0391 100644 --- a/lang/tests/son_tests_string_flip.txt +++ b/lang/tests/son_tests_string_flip.txt @@ -1,39 +1,39 @@ main: ADDI64 r254, r254, -32d - LI64 r6, 1d - LI64 r7, 4d + LI64 r7, 1d + LI64 r6, 4d LI64 r4, 0d ADDI64 r5, r254, 0d CP r8, r4 - 6: JNE r8, r7, :0 - LI64 r7, 2d + 6: JNE r8, r6, :0 + LI64 r6, 2d CP r8, r4 4: LD r1, r254, 0a, 8h - JNE r8, r6, :1 + JNE r8, r7, :1 JMP :2 - 1: MUL64 r10, r8, r7 - ADD64 r8, r8, r6 - SUB64 r3, r7, r8 - MUL64 r9, r3, r7 + 1: MUL64 r11, r8, r6 + ADD64 r8, r8, r7 + SUB64 r9, r6, r8 + MUL64 r9, r9, r6 CP r2, r4 - 5: JNE r2, r7, :3 + 5: JNE r2, r6, :3 JMP :4 - 3: ADD64 r1, r2, r6 - ADD64 r11, r9, r2 - MULI64 r3, r11, 8d - ADD64 r12, r10, r2 - ADD64 r11, r5, r3 + 3: ADD64 r10, r2, r7 + ADD64 r12, r9, r2 MULI64 r12, r12, 8d + ADD64 r1, r11, r2 ADD64 r12, r5, r12 - BMC r11, r12, 8h - BMC r12, r11, 8h - CP r2, r1 + MULI64 r1, r1, 8d + ADD64 r1, r5, r1 + BMC r12, r1, 8h + BMC r1, r12, 8h + CP r2, r10 JMP :5 - 0: ADD64 r11, r8, r6 + 0: ADD64 r12, r8, r7 MULI64 r10, r8, 8d - ADD64 r9, r5, r10 - ST r8, r9, 0a, 8h - CP r8, r11 + ADD64 r1, r5, r10 + ST r8, r1, 0a, 8h + CP r8, r12 JMP :6 2: ADDI64 r254, r254, 32d JALA r0, r31, 0a diff --git a/lang/tests/son_tests_tests_ptr_to_ptr_copy.txt b/lang/tests/son_tests_tests_ptr_to_ptr_copy.txt index 7c29a58e..6a10f2f6 100644 --- a/lang/tests/son_tests_tests_ptr_to_ptr_copy.txt +++ b/lang/tests/son_tests_tests_ptr_to_ptr_copy.txt @@ -1,27 +1,27 @@ main: ADDI64 r254, r254, -10240d - LI64 r6, 1d - LI8 r7, 64b - LI64 r8, 1024d + LI64 r7, 1d + LI8 r8, 64b + LI64 r6, 1024d LI64 r9, 0d ADDI64 r5, r254, 0d - 4: JLTU r9, r8, :0 - LI64 r4, 10d - CP r7, r6 - 3: LD r9, r254, 2048a, 1h - JLTU r7, r4, :1 - ANDI r1, r9, 255d + 4: JLTU r9, r6, :0 + LI64 r6, 10d + CP r8, r7 + 3: LD r11, r254, 2048a, 1h + JLTU r8, r6, :1 + ANDI r1, r11, 255d JMP :2 - 1: ADD64 r12, r7, r6 - MULI64 r1, r7, 1024d - ADD64 r7, r5, r1 - BMC r5, r7, 1024h - CP r7, r12 + 1: ADD64 r2, r8, r7 + MULI64 r1, r8, 1024d + ADD64 r3, r5, r1 + BMC r5, r3, 1024h + CP r8, r2 JMP :3 - 0: ADD64 r1, r9, r6 - ADD64 r10, r5, r9 - ST r7, r10, 0a, 1h - CP r9, r1 + 0: ADD64 r2, r9, r7 + ADD64 r12, r5, r9 + ST r8, r12, 0a, 1h + CP r9, r2 JMP :4 2: ADDI64 r254, r254, 10240d JALA r0, r31, 0a