fixing wrong instruction selection
This commit is contained in:
parent
823c78bf74
commit
42a713aeae
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<'_> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue