fixing wrong instruction selection
This commit is contained in:
parent
823c78bf74
commit
42a713aeae
|
@ -450,7 +450,9 @@ impl Nodes {
|
||||||
return self.idom(from);
|
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]
|
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, from_value, loops);
|
||||||
self.load_loop_var(i, to_value, loops);
|
self.load_loop_var(i, to_value, loops);
|
||||||
if to_value.value() != from_value.value() {
|
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()];
|
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);
|
to_value.set_value_remove(self.new_node(from_value.ty, Kind::Phi, inps), self);
|
||||||
}
|
}
|
||||||
|
@ -624,6 +628,8 @@ impl Nodes {
|
||||||
node.ty.expand(),
|
node.ty.expand(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug_assert!(!matches!(node.ty.expand(), ty::Kind::Struct(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut lookup_meta = None;
|
let mut lookup_meta = None;
|
||||||
|
@ -1036,8 +1042,9 @@ impl Nodes {
|
||||||
if self[lhs].kind == Kind::Stre
|
if self[lhs].kind == Kind::Stre
|
||||||
&& self[rhs].kind == Kind::Stre
|
&& self[rhs].kind == Kind::Stre
|
||||||
&& self[lhs].ty == self[rhs].ty
|
&& 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[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, [
|
let pick_value = self.new_node(self[lhs].ty, Kind::Phi, [
|
||||||
ctrl,
|
ctrl,
|
||||||
|
@ -1154,6 +1161,10 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !unidentifed.is_empty() {
|
||||||
|
break 'eliminate;
|
||||||
|
}
|
||||||
|
|
||||||
debug_assert_matches!(
|
debug_assert_matches!(
|
||||||
self[last_store].kind,
|
self[last_store].kind,
|
||||||
Kind::Stre | Kind::Mem,
|
Kind::Stre | Kind::Mem,
|
||||||
|
@ -1167,10 +1178,6 @@ impl Nodes {
|
||||||
self[first_store]
|
self[first_store]
|
||||||
);
|
);
|
||||||
|
|
||||||
if !unidentifed.is_empty() {
|
|
||||||
break 'eliminate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: when the loads and stores become parallel we will need to get saved
|
// FIXME: when the loads and stores become parallel we will need to get saved
|
||||||
// differently
|
// differently
|
||||||
let mut prev_store = store;
|
let mut prev_store = store;
|
||||||
|
@ -1574,10 +1581,14 @@ impl Nodes {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug_assert!(!var.ptr);
|
||||||
|
|
||||||
let [loops @ .., loob] = loops else { unreachable!() };
|
let [loops @ .., loob] = loops else { unreachable!() };
|
||||||
let node = loob.node;
|
let node = loob.node;
|
||||||
let lvar = &mut loob.scope.vars[index];
|
let lvar = &mut loob.scope.vars[index];
|
||||||
|
|
||||||
|
debug_assert!(!lvar.ptr);
|
||||||
|
|
||||||
self.load_loop_var(index, lvar, loops);
|
self.load_loop_var(index, lvar, loops);
|
||||||
|
|
||||||
if !self[lvar.value()].is_lazy_phi(node) {
|
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 {
|
loop {
|
||||||
if dominator == dominated {
|
if dominator == dominated {
|
||||||
break true;
|
break true;
|
||||||
|
@ -1650,12 +1661,21 @@ impl Nodes {
|
||||||
|
|
||||||
fn is_data_dep(&self, nid: Nid, n: Nid) -> bool {
|
fn is_data_dep(&self, nid: Nid, n: Nid) -> bool {
|
||||||
match self[n].kind {
|
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::Stre => self[n].inputs[3] != nid,
|
||||||
Kind::Load => self[n].inputs[2] != nid,
|
Kind::Load => self[n].inputs[2] != nid,
|
||||||
_ => self[n].inputs[0] != nid || self[n].inputs[1..].contains(&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 {
|
enum CondOptRes {
|
||||||
|
@ -3509,8 +3529,10 @@ impl<'a> Codegen<'a> {
|
||||||
});
|
});
|
||||||
|
|
||||||
for var in self.ci.scope.vars.iter_mut().skip(self.ci.inline_var_base) {
|
for var in self.ci.scope.vars.iter_mut().skip(self.ci.inline_var_base) {
|
||||||
|
if !var.ptr {
|
||||||
var.set_value(VOID, &mut self.ci.nodes);
|
var.set_value(VOID, &mut self.ci.nodes);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for aclass in self.ci.scope.aclasses[..2].iter_mut() {
|
for aclass in self.ci.scope.aclasses[..2].iter_mut() {
|
||||||
aclass.last_store.set(VOID, &mut self.ci.nodes);
|
aclass.last_store.set(VOID, &mut self.ci.nodes);
|
||||||
|
@ -4612,6 +4634,8 @@ mod tests {
|
||||||
if let Err(e) = err {
|
if let Err(e) = err {
|
||||||
writeln!(output, "!!! asm is invalid: {e}").unwrap();
|
writeln!(output, "!!! asm is invalid: {e}").unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
log::info!("================ running {ident} ==============");
|
||||||
|
log::trace!("{output}");
|
||||||
super::hbvm::test_run_vm(&out, output);
|
super::hbvm::test_run_vm(&out, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use {
|
||||||
parser, reg,
|
parser, reg,
|
||||||
son::{debug_assert_matches, write_reloc, Kind, MEM},
|
son::{debug_assert_matches, write_reloc, Kind, MEM},
|
||||||
ty::{self, Loc, Module},
|
ty::{self, Loc, Module},
|
||||||
utils::{Ent, EntVec},
|
utils::{BitSet, Ent, EntVec, Vc},
|
||||||
Offset, Reloc, Size, TypedReloc, Types,
|
Offset, Reloc, Size, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec},
|
alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec},
|
||||||
|
@ -332,6 +332,72 @@ impl Backend for HbvmBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Nodes {
|
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 {
|
fn is_never_used(&self, nid: Nid, tys: &Types) -> bool {
|
||||||
let node = &self[nid];
|
let node = &self[nid];
|
||||||
match node.kind {
|
match node.kind {
|
||||||
|
@ -485,7 +551,7 @@ impl TokenKind {
|
||||||
Self::Band => return Some(andi),
|
Self::Band => return Some(andi),
|
||||||
Self::Bor => return Some(ori),
|
Self::Bor => return Some(ori),
|
||||||
Self::Xor => return Some(xori),
|
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::Shr => basic_op!(srui8, srui16, srui32, srui64),
|
||||||
Self::Shl => basic_op!(slui8, slui16, slui32, slui64),
|
Self::Shl => basic_op!(slui8, slui16, slui32, slui64),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use {
|
||||||
reg::{self, Reg},
|
reg::{self, Reg},
|
||||||
son::{debug_assert_matches, Kind, ARG_START, MEM, VOID},
|
son::{debug_assert_matches, Kind, ARG_START, MEM, VOID},
|
||||||
ty::{self, Arg, Loc},
|
ty::{self, Arg, Loc},
|
||||||
utils::{BitSet, Vc},
|
utils::BitSet,
|
||||||
Offset, PLoc, Reloc, Sig, TypedReloc, Types,
|
Offset, PLoc, Reloc, Sig, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
alloc::{borrow::ToOwned, vec::Vec},
|
alloc::{borrow::ToOwned, vec::Vec},
|
||||||
|
@ -22,9 +22,16 @@ impl HbvmBackend {
|
||||||
tys: &Types,
|
tys: &Types,
|
||||||
files: &[parser::Ast],
|
files: &[parser::Ast],
|
||||||
) -> (usize, bool) {
|
) -> (usize, bool) {
|
||||||
let mut fuc = Function::new(nodes, tys, sig);
|
let fuc = Function::new(nodes, tys, sig);
|
||||||
log::info!("{fuc:?}");
|
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);
|
let mut res = mem::take(&mut self.ralloc_my);
|
||||||
|
|
||||||
Env::new(&fuc, &fuc.func, &mut res).run();
|
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 };
|
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| {
|
res.node_to_reg.iter_mut().filter(|r| **r != 0).for_each(|r| {
|
||||||
|
if *r == u8::MAX {
|
||||||
|
*r = 0
|
||||||
|
} else {
|
||||||
*r += reg_offset - 1;
|
*r += reg_offset - 1;
|
||||||
if fuc.tail && *r >= reg::RET_ADDR {
|
if fuc.tail && *r >= reg::RET_ADDR {
|
||||||
*r += 1;
|
*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() {
|
//for (id, node) in fuc.nodes.iter() {
|
||||||
// if node.kind == Kind::Phi {
|
// if node.kind == Kind::Phi {
|
||||||
|
@ -84,8 +105,6 @@ impl HbvmBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = &fuc.nodes[nid];
|
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 extend = |base: ty::Id, dest: ty::Id, from: Nid, to: Nid| {
|
||||||
let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest));
|
let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest));
|
||||||
debug_assert!(bsize <= 8, "{}", ty::Display::new(tys, files, base));
|
debug_assert!(bsize <= 8, "{}", ty::Display::new(tys, files, base));
|
||||||
|
@ -141,36 +160,35 @@ impl HbvmBackend {
|
||||||
cnd,
|
cnd,
|
||||||
));
|
));
|
||||||
let rel = Reloc::new(self.code.len(), 3, 2);
|
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.jump_relocs.push((node.outputs[0], rel));
|
||||||
self.emit(instrs::jne(atr(cnd), reg::ZERO, 0));
|
self.emit(instrs::jne(atr(cnd), reg::ZERO, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Loop | Kind::Region => {
|
Kind::Loop | Kind::Region => {
|
||||||
let mut emit_moves = |index| {
|
let index = node
|
||||||
|
.inputs
|
||||||
|
.iter()
|
||||||
|
.position(|&n| block.entry == fuc.idom_of(n))
|
||||||
|
.unwrap()
|
||||||
|
+ 1;
|
||||||
|
|
||||||
let mut moves = vec![];
|
let mut moves = vec![];
|
||||||
for &out in node.outputs.iter() {
|
for &out in node.outputs.iter() {
|
||||||
if fuc.nodes[out].is_data_phi() {
|
if fuc.nodes[out].is_data_phi() {
|
||||||
debug_assert_eq!(
|
let src = fuc.nodes[out].inputs[index];
|
||||||
fuc.backrefs[fuc.nodes[out].inputs[index] as usize],
|
if atr(out) != atr(src) {
|
||||||
u16::MAX,
|
moves.push([atr(out), atr(src), 0]);
|
||||||
"{:?}\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,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug_assert_eq!(moves.len(), {
|
||||||
|
moves.sort_unstable();
|
||||||
|
moves.dedup();
|
||||||
|
moves.len()
|
||||||
|
});
|
||||||
|
|
||||||
moves.sort_unstable_by(|[aa, ab, _], [ba, bb, _]| {
|
moves.sort_unstable_by(|[aa, ab, _], [ba, bb, _]| {
|
||||||
if aa == bb && ab == ba {
|
if aa == bb && ab == ba {
|
||||||
core::cmp::Ordering::Equal
|
core::cmp::Ordering::Equal
|
||||||
|
@ -197,40 +215,24 @@ impl HbvmBackend {
|
||||||
self.emit(instrs::swa(dst, src));
|
self.emit(instrs::swa(dst, src));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if (bref != u16::MAX) ^ (node.kind == Kind::Loop) {
|
|
||||||
let index = (node.kind == Kind::Loop) as usize + 1;
|
|
||||||
emit_moves(index);
|
|
||||||
|
|
||||||
|
if fuc.block_of(nid) as usize != i + 1 {
|
||||||
let rel = Reloc::new(self.code.len(), 1, 4);
|
let rel = Reloc::new(self.code.len(), 1, 4);
|
||||||
self.jump_relocs.push((nid, rel));
|
self.jump_relocs.push((nid, rel));
|
||||||
self.emit(instrs::jmp(0));
|
self.emit(instrs::jmp(0));
|
||||||
} else {
|
|
||||||
let index = (node.kind != Kind::Loop) as usize + 1;
|
|
||||||
emit_moves(index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Return => {
|
Kind::Return => {
|
||||||
let &[_, mut ret, ..] = node.inputs.as_slice() else { unreachable!() };
|
let &[_, ret, ..] = node.inputs.as_slice() else { unreachable!() };
|
||||||
match retl {
|
match retl {
|
||||||
None => {}
|
None => {}
|
||||||
Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => {
|
Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => {
|
||||||
self.emit(instrs::cp(r, atr(ret)));
|
self.emit(instrs::cp(r, atr(ret)));
|
||||||
}
|
}
|
||||||
Some(PLoc::Reg(r, size)) | Some(PLoc::WideReg(r, size)) => {
|
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))
|
self.emit(instrs::ld(r, atr(ret), 0, size))
|
||||||
}
|
}
|
||||||
Some(PLoc::Ref(_, 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)];
|
let [src, dst] = [atr(ret), atr(MEM)];
|
||||||
if let Ok(size) = u16::try_from(size) {
|
if let Ok(size) = u16::try_from(size) {
|
||||||
self.emit(instrs::bmc(src, dst, 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::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size),
|
||||||
PLoc::WideReg(rg, size) => (rg, size),
|
PLoc::WideReg(rg, size) => (rg, size),
|
||||||
PLoc::Ref(r, ..) => {
|
PLoc::Ref(r, ..) => {
|
||||||
arg = match fuc.nodes[arg].kind {
|
|
||||||
Kind::Load { .. } => fuc.nodes[arg].inputs[1],
|
|
||||||
_ => arg,
|
|
||||||
};
|
|
||||||
self.emit(instrs::cp(r, atr(arg)));
|
self.emit(instrs::cp(r, atr(arg)));
|
||||||
continue;
|
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));
|
self.emit(instrs::ld(rg, atr(arg), 0, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,6 +358,10 @@ impl HbvmBackend {
|
||||||
!matches!(ret, Some(PLoc::Ref(..))) || allocs.next().is_some()
|
!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 {
|
if func == ty::Func::ECA {
|
||||||
self.emit(instrs::eca());
|
self.emit(instrs::eca());
|
||||||
} else {
|
} else {
|
||||||
|
@ -434,8 +432,9 @@ impl HbvmBackend {
|
||||||
let mut region = node.inputs[2];
|
let mut region = node.inputs[2];
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
let size = u16::try_from(tys.size_of(node.ty)).expect("TODO");
|
let size = u16::try_from(tys.size_of(node.ty)).expect("TODO");
|
||||||
if fuc.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
if matches!(fuc.nodes[region].kind, Kind::BinOp {
|
||||||
&& let Kind::CInt { value } =
|
op: TokenKind::Add | TokenKind::Sub
|
||||||
|
}) && let Kind::CInt { value } =
|
||||||
fuc.nodes[fuc.nodes[region].inputs[2]].kind
|
fuc.nodes[fuc.nodes[region].inputs[2]].kind
|
||||||
&& node.ty.loc(tys) == Loc::Reg
|
&& node.ty.loc(tys) == Loc::Reg
|
||||||
{
|
{
|
||||||
|
@ -448,10 +447,7 @@ impl HbvmBackend {
|
||||||
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
||||||
(reg::STACK_PTR, self.offsets[region as usize] + offset, value)
|
(reg::STACK_PTR, self.offsets[region as usize] + offset, value)
|
||||||
}
|
}
|
||||||
_ => (atr(region), offset, match fuc.nodes[value].kind {
|
_ => (atr(region), offset, value),
|
||||||
Kind::Load { .. } => fuc.nodes[value].inputs[1],
|
|
||||||
_ => value,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match node.ty.loc(tys) {
|
match node.ty.loc(tys) {
|
||||||
|
@ -507,7 +503,7 @@ impl Function<'_> {
|
||||||
self.nodes.values.len()
|
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 { .. }) {
|
if self.nodes[nid].kind.is_cfg() && !matches!(self.nodes[nid].kind, Kind::Call { .. }) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -516,9 +512,22 @@ impl Function<'_> {
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&&n| self.nodes.is_data_dep(nid, n))
|
.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);
|
.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>) {
|
fn phi_inputs_of(&self, nid: Nid, buf: &mut Vec<Nid>) {
|
||||||
match self.nodes[nid].kind {
|
match self.nodes[nid].kind {
|
||||||
Kind::Region => {
|
Kind::Region => {
|
||||||
|
@ -561,14 +570,6 @@ impl Function<'_> {
|
||||||
}
|
}
|
||||||
nid
|
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<'_> {
|
impl core::fmt::Debug for Function<'_> {
|
||||||
|
@ -654,8 +655,11 @@ impl<'a> Function<'a> {
|
||||||
|
|
||||||
if let Kind::BinOp { op } = self.nodes[cond].kind
|
if let Kind::BinOp { op } = self.nodes[cond].kind
|
||||||
&& let Some((_, swapped)) = op.cond_op(node.ty)
|
&& let Some((_, swapped)) = op.cond_op(node.ty)
|
||||||
&& swapped
|
|
||||||
{
|
{
|
||||||
|
if swapped {
|
||||||
|
mem::swap(&mut then, &mut else_);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
mem::swap(&mut then, &mut else_);
|
mem::swap(&mut then, &mut else_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,7 +670,7 @@ impl<'a> Function<'a> {
|
||||||
Kind::Region | Kind::Loop => {
|
Kind::Region | Kind::Loop => {
|
||||||
self.close_block(nid);
|
self.close_block(nid);
|
||||||
self.add_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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
self.emit_node(o);
|
self.emit_node(o);
|
||||||
}
|
}
|
||||||
|
@ -693,14 +697,14 @@ impl<'a> Function<'a> {
|
||||||
self.add_instr(MEM);
|
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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
self.emit_node(o);
|
self.emit_node(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Then | Kind::Else => {
|
Kind::Then | Kind::Else => {
|
||||||
self.add_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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
self.emit_node(o);
|
self.emit_node(o);
|
||||||
}
|
}
|
||||||
|
@ -710,7 +714,7 @@ impl<'a> Function<'a> {
|
||||||
|
|
||||||
self.add_instr(nid);
|
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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
if self.nodes[o].inputs[0] == nid
|
if self.nodes[o].inputs[0] == nid
|
||||||
|| (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region)
|
|| (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region)
|
||||||
|
@ -731,72 +735,6 @@ impl<'a> Function<'a> {
|
||||||
Kind::Assert { .. } => unreachable!(),
|
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> {
|
pub struct Env<'a> {
|
||||||
|
@ -845,26 +783,37 @@ impl<'a> Env<'a> {
|
||||||
self.res.use_buf = use_buf;
|
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);
|
let dom = self.ctx.idom_of(inst);
|
||||||
self.ctx.uses_of(inst, use_buf);
|
self.ctx.uses_of(inst, use_buf);
|
||||||
for uinst in use_buf.drain(..) {
|
for (cursor, uinst) in use_buf.drain(..) {
|
||||||
let cursor = self.ctx.use_block(inst, uinst);
|
|
||||||
self.reverse_cfg_dfs(cursor, dom, |_, n, b| {
|
self.reverse_cfg_dfs(cursor, dom, |_, n, b| {
|
||||||
let mut range = b.range.clone();
|
let mut range = b.range.clone();
|
||||||
|
debug_assert!(range.start < range.end);
|
||||||
range.start =
|
range.start =
|
||||||
range.start.max(self.ctx.instr_of(inst).map_or(0, |n| n + 1) as usize);
|
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(
|
range.end = range.end.min(
|
||||||
self.ctx
|
self.ctx
|
||||||
.instr_of(uinst)
|
.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,
|
.map_or(Nid::MAX, |n| n + 1) as usize,
|
||||||
);
|
);
|
||||||
|
debug_assert!(range.start < range.end);
|
||||||
|
|
||||||
bundle.add(range);
|
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)) {
|
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) {
|
||||||
Some((i, other)) => {
|
Some((i, other)) => {
|
||||||
other.merge(bundle);
|
other.merge(bundle);
|
||||||
|
@ -888,7 +837,14 @@ impl<'a> Env<'a> {
|
||||||
self.res.dfs_buf.push(from);
|
self.res.dfs_buf.push(from);
|
||||||
self.res.dfs_seem.clear(self.ctx.nodes.values.len());
|
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() {
|
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]);
|
each(self, nid, &self.func.blocks[self.ctx.block_of(nid) as usize]);
|
||||||
if nid == until {
|
if nid == until {
|
||||||
continue;
|
continue;
|
||||||
|
@ -896,6 +852,9 @@ impl<'a> Env<'a> {
|
||||||
match self.ctx.nodes[nid].kind {
|
match self.ctx.nodes[nid].kind {
|
||||||
Kind::Then | Kind::Else | Kind::Region | Kind::Loop => {
|
Kind::Then | Kind::Else | Kind::Region | Kind::Loop => {
|
||||||
for &n in self.ctx.nodes[nid].inputs.iter() {
|
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);
|
let d = self.ctx.idom_of(n);
|
||||||
if self.res.dfs_seem.set(d) {
|
if self.res.dfs_seem.set(d) {
|
||||||
self.res.dfs_buf.push(d);
|
self.res.dfs_buf.push(d);
|
||||||
|
@ -913,7 +872,7 @@ impl<'a> Env<'a> {
|
||||||
pub struct Res {
|
pub struct Res {
|
||||||
pub bundles: Vec<Bundle>,
|
pub bundles: Vec<Bundle>,
|
||||||
pub node_to_reg: Vec<Reg>,
|
pub node_to_reg: Vec<Reg>,
|
||||||
use_buf: Vec<Nid>,
|
use_buf: Vec<(Nid, Nid)>,
|
||||||
phi_input_buf: Vec<Nid>,
|
phi_input_buf: Vec<Nid>,
|
||||||
dfs_buf: Vec<Nid>,
|
dfs_buf: Vec<Nid>,
|
||||||
dfs_seem: BitSet,
|
dfs_seem: BitSet,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use {
|
||||||
parser, reg,
|
parser, reg,
|
||||||
son::{debug_assert_matches, Kind, ARG_START, MEM, NEVER, VOID},
|
son::{debug_assert_matches, Kind, ARG_START, MEM, NEVER, VOID},
|
||||||
ty::{self, Arg, Loc},
|
ty::{self, Arg, Loc},
|
||||||
utils::{BitSet, Vc},
|
utils::BitSet,
|
||||||
HashMap, Offset, PLoc, Reloc, Sig, TypedReloc, Types,
|
HashMap, Offset, PLoc, Reloc, Sig, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
alloc::{borrow::ToOwned, vec::Vec},
|
alloc::{borrow::ToOwned, vec::Vec},
|
||||||
|
@ -616,7 +616,7 @@ impl<'a> Function<'a> {
|
||||||
block.push(self.rg(ph));
|
block.push(self.rg(ph));
|
||||||
}
|
}
|
||||||
self.blocks[self.backrefs[nid as usize] as usize].params = block;
|
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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
self.emit_node(o, nid);
|
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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
self.emit_node(o, nid);
|
self.emit_node(o, nid);
|
||||||
}
|
}
|
||||||
|
@ -688,7 +688,7 @@ impl<'a> Function<'a> {
|
||||||
Kind::Then | Kind::Else => {
|
Kind::Then | Kind::Else => {
|
||||||
self.backrefs[nid as usize] = self.add_block(nid);
|
self.backrefs[nid as usize] = self.add_block(nid);
|
||||||
self.bridge(prev, 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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
self.emit_node(o, nid);
|
self.emit_node(o, nid);
|
||||||
}
|
}
|
||||||
|
@ -783,7 +783,7 @@ impl<'a> Function<'a> {
|
||||||
|
|
||||||
self.add_instr(nid, ops);
|
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() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
if self.nodes[o].inputs[0] == nid
|
if self.nodes[o].inputs[0] == nid
|
||||||
|| (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region)
|
|| (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region)
|
||||||
|
@ -853,72 +853,6 @@ impl<'a> Function<'a> {
|
||||||
.preds
|
.preds
|
||||||
.push(regalloc2::Block::new(self.backrefs[pred as usize] as usize));
|
.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<'_> {
|
impl regalloc2::Function for Function<'_> {
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -128d
|
ADDI64 r254, r254, -128d
|
||||||
LI8 r5, 69b
|
LI8 r6, 69b
|
||||||
LI64 r6, 128d
|
LI64 r5, 128d
|
||||||
LI64 r7, 0d
|
LI64 r7, 0d
|
||||||
ADDI64 r4, r254, 0d
|
ADDI64 r4, r254, 0d
|
||||||
2: LD r12, r254, 42a, 1h
|
2: LD r1, r254, 42a, 1h
|
||||||
JLTU r7, r6, :0
|
JLTU r7, r5, :0
|
||||||
ANDI r1, r12, 255d
|
ANDI r1, r1, 255d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: ADDI64 r3, r7, 1d
|
0: ADDI64 r8, r7, 1d
|
||||||
ADD64 r7, r4, r7
|
ADD64 r3, r4, r7
|
||||||
ST r5, r7, 0a, 1h
|
ST r6, r3, 0a, 1h
|
||||||
CP r7, r3
|
CP r7, r8
|
||||||
JMP :2
|
JMP :2
|
||||||
1: ADDI64 r254, r254, 128d
|
1: ADDI64 r254, r254, 128d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
|
|
|
@ -95,8 +95,8 @@ put_filled_rect:
|
||||||
CP r4, r33
|
CP r4, r33
|
||||||
CP r5, r44
|
CP r5, r44
|
||||||
ECA
|
ECA
|
||||||
ADD64 r42, r40, r42
|
|
||||||
SUB64 r41, r41, r40
|
SUB64 r41, r41, r40
|
||||||
|
ADD64 r42, r40, r42
|
||||||
SUB64 r39, r39, r32
|
SUB64 r39, r39, r32
|
||||||
CP r6, r43
|
CP r6, r43
|
||||||
CP r8, r44
|
CP r8, r44
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -32d
|
||||||
LI64 r6, 1d
|
LI64 r7, 1d
|
||||||
LI64 r7, 4d
|
LI64 r6, 4d
|
||||||
LI64 r4, 0d
|
LI64 r4, 0d
|
||||||
ADDI64 r5, r254, 0d
|
ADDI64 r5, r254, 0d
|
||||||
CP r8, r4
|
CP r8, r4
|
||||||
6: JNE r8, r7, :0
|
6: JNE r8, r6, :0
|
||||||
LI64 r7, 2d
|
LI64 r6, 2d
|
||||||
CP r8, r4
|
CP r8, r4
|
||||||
4: LD r1, r254, 0a, 8h
|
4: LD r1, r254, 0a, 8h
|
||||||
JNE r8, r6, :1
|
JNE r8, r7, :1
|
||||||
JMP :2
|
JMP :2
|
||||||
1: MUL64 r10, r8, r7
|
1: MUL64 r11, r8, r6
|
||||||
ADD64 r8, r8, r6
|
ADD64 r8, r8, r7
|
||||||
SUB64 r3, r7, r8
|
SUB64 r9, r6, r8
|
||||||
MUL64 r9, r3, r7
|
MUL64 r9, r9, r6
|
||||||
CP r2, r4
|
CP r2, r4
|
||||||
5: JNE r2, r7, :3
|
5: JNE r2, r6, :3
|
||||||
JMP :4
|
JMP :4
|
||||||
3: ADD64 r1, r2, r6
|
3: ADD64 r10, r2, r7
|
||||||
ADD64 r11, r9, r2
|
ADD64 r12, r9, r2
|
||||||
MULI64 r3, r11, 8d
|
|
||||||
ADD64 r12, r10, r2
|
|
||||||
ADD64 r11, r5, r3
|
|
||||||
MULI64 r12, r12, 8d
|
MULI64 r12, r12, 8d
|
||||||
|
ADD64 r1, r11, r2
|
||||||
ADD64 r12, r5, r12
|
ADD64 r12, r5, r12
|
||||||
BMC r11, r12, 8h
|
MULI64 r1, r1, 8d
|
||||||
BMC r12, r11, 8h
|
ADD64 r1, r5, r1
|
||||||
CP r2, r1
|
BMC r12, r1, 8h
|
||||||
|
BMC r1, r12, 8h
|
||||||
|
CP r2, r10
|
||||||
JMP :5
|
JMP :5
|
||||||
0: ADD64 r11, r8, r6
|
0: ADD64 r12, r8, r7
|
||||||
MULI64 r10, r8, 8d
|
MULI64 r10, r8, 8d
|
||||||
ADD64 r9, r5, r10
|
ADD64 r1, r5, r10
|
||||||
ST r8, r9, 0a, 8h
|
ST r8, r1, 0a, 8h
|
||||||
CP r8, r11
|
CP r8, r12
|
||||||
JMP :6
|
JMP :6
|
||||||
2: ADDI64 r254, r254, 32d
|
2: ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -10240d
|
ADDI64 r254, r254, -10240d
|
||||||
LI64 r6, 1d
|
LI64 r7, 1d
|
||||||
LI8 r7, 64b
|
LI8 r8, 64b
|
||||||
LI64 r8, 1024d
|
LI64 r6, 1024d
|
||||||
LI64 r9, 0d
|
LI64 r9, 0d
|
||||||
ADDI64 r5, r254, 0d
|
ADDI64 r5, r254, 0d
|
||||||
4: JLTU r9, r8, :0
|
4: JLTU r9, r6, :0
|
||||||
LI64 r4, 10d
|
LI64 r6, 10d
|
||||||
CP r7, r6
|
CP r8, r7
|
||||||
3: LD r9, r254, 2048a, 1h
|
3: LD r11, r254, 2048a, 1h
|
||||||
JLTU r7, r4, :1
|
JLTU r8, r6, :1
|
||||||
ANDI r1, r9, 255d
|
ANDI r1, r11, 255d
|
||||||
JMP :2
|
JMP :2
|
||||||
1: ADD64 r12, r7, r6
|
1: ADD64 r2, r8, r7
|
||||||
MULI64 r1, r7, 1024d
|
MULI64 r1, r8, 1024d
|
||||||
ADD64 r7, r5, r1
|
ADD64 r3, r5, r1
|
||||||
BMC r5, r7, 1024h
|
BMC r5, r3, 1024h
|
||||||
CP r7, r12
|
CP r8, r2
|
||||||
JMP :3
|
JMP :3
|
||||||
0: ADD64 r1, r9, r6
|
0: ADD64 r2, r9, r7
|
||||||
ADD64 r10, r5, r9
|
ADD64 r12, r5, r9
|
||||||
ST r7, r10, 0a, 1h
|
ST r8, r12, 0a, 1h
|
||||||
CP r9, r1
|
CP r9, r2
|
||||||
JMP :4
|
JMP :4
|
||||||
2: ADDI64 r254, r254, 10240d
|
2: ADDI64 r254, r254, 10240d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
|
|
Loading…
Reference in a new issue