fixing wrong instruction selection

This commit is contained in:
Jakub Doka 2024-11-10 09:17:43 +01:00
parent 823c78bf74
commit 42a713aeae
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
8 changed files with 286 additions and 303 deletions

View file

@ -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);
}
}

View file

@ -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,

View file

@ -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<Nid>) {
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<Nid>) {
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<Nid>) {
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<Bundle>,
pub node_to_reg: Vec<Reg>,
use_buf: Vec<Nid>,
use_buf: Vec<(Nid, Nid)>,
phi_input_buf: Vec<Nid>,
dfs_buf: Vec<Nid>,
dfs_seem: BitSet,

View file

@ -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<'_> {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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