forked from AbleOS/holey-bytes
fixing function destinations
This commit is contained in:
parent
d01e31b203
commit
981c17ff19
|
@ -646,6 +646,41 @@ main := fn(): uint {
|
|||
|
||||
### Purely Testing Examples
|
||||
|
||||
#### different_function_destinations
|
||||
```hb
|
||||
Stru := struct {a: uint, b: uint}
|
||||
new_stru := fn(): Stru return .(0, 0)
|
||||
|
||||
glob_stru := Stru.(1, 1)
|
||||
|
||||
main := fn(): uint {
|
||||
glob_stru = new_stru()
|
||||
if glob_stru.a != 0 return 300
|
||||
glob_stru = .(1, 1)
|
||||
glob_stru = @inline(new_stru)
|
||||
if glob_stru.a != 0 return 200
|
||||
|
||||
glob_stru = .(1, 1)
|
||||
strus := [Stru].(glob_stru, glob_stru, glob_stru)
|
||||
i := 0
|
||||
loop if i == 3 break else {
|
||||
strus[i] = new_stru()
|
||||
i += 1
|
||||
}
|
||||
if strus[2].a != 0 return 100
|
||||
|
||||
strus = [Stru].(glob_stru, glob_stru, glob_stru)
|
||||
i = 0
|
||||
loop if i == 3 break else {
|
||||
strus[i] = @inline(new_stru)
|
||||
i += 1
|
||||
}
|
||||
if strus[2].a != 0 return 10
|
||||
|
||||
return 0
|
||||
}
|
||||
```
|
||||
|
||||
#### triggering_store_in_divergent_branch
|
||||
```hb
|
||||
opaque := fn(): uint {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![feature(
|
||||
iter_array_chunks,
|
||||
assert_matches,
|
||||
let_chains,
|
||||
if_let_guard,
|
||||
|
|
129
lang/src/son.rs
129
lang/src/son.rs
|
@ -125,52 +125,34 @@ impl Default for Nodes {
|
|||
|
||||
impl Nodes {
|
||||
fn loop_depth(&self, target: Nid) -> LoopDepth {
|
||||
if self[target].loop_depth.get() != 0 {
|
||||
return self[target].loop_depth.get();
|
||||
}
|
||||
|
||||
self[target].loop_depth.set(match self[target].kind {
|
||||
Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::Return | Kind::If => {
|
||||
let dpth = self.loop_depth(self[target].inputs[0]);
|
||||
Kind::Region | Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::If => {
|
||||
if self[target].loop_depth.get() != 0 {
|
||||
return self[target].loop_depth.get();
|
||||
}
|
||||
dpth
|
||||
}
|
||||
Kind::Region => {
|
||||
let l = self.loop_depth(self[target].inputs[0]);
|
||||
let r = self.loop_depth(self[target].inputs[1]);
|
||||
debug_assert_eq!(l, r);
|
||||
l
|
||||
self.loop_depth(self[target].inputs[0])
|
||||
}
|
||||
Kind::Loop => {
|
||||
let depth = Self::loop_depth(self, self[target].inputs[0]) + 1;
|
||||
if self[target].loop_depth.get() == self.loop_depth(self[target].inputs[0]) + 1 {
|
||||
return self[target].loop_depth.get();
|
||||
}
|
||||
let depth = self.loop_depth(self[target].inputs[0]) + 1;
|
||||
self[target].loop_depth.set(depth);
|
||||
let mut cursor = self[target].inputs[1];
|
||||
while cursor != target {
|
||||
self[cursor].loop_depth.set(depth);
|
||||
let next = if self[cursor].kind == Kind::Region {
|
||||
self.loop_depth(self[cursor].inputs[0]);
|
||||
self[cursor].inputs[1]
|
||||
} else {
|
||||
self.idom(cursor)
|
||||
};
|
||||
debug_assert_ne!(next, VOID);
|
||||
let next = self.idom(cursor);
|
||||
debug_assert_ne!(next, 0);
|
||||
if matches!(self[cursor].kind, Kind::Then | Kind::Else) {
|
||||
let other = *self[next]
|
||||
.outputs
|
||||
.iter()
|
||||
.find(|&&n| self[n].kind != self[cursor].kind)
|
||||
.unwrap();
|
||||
if self[other].loop_depth.get() == 0 {
|
||||
debug_assert_eq!(self[next].kind, Kind::If);
|
||||
let other = self[next].outputs[(self[next].outputs[0] == cursor) as usize];
|
||||
self[other].loop_depth.set(depth - 1);
|
||||
}
|
||||
}
|
||||
cursor = next;
|
||||
}
|
||||
depth
|
||||
}
|
||||
Kind::Start | Kind::End | Kind::Die => 1,
|
||||
Kind::Start | Kind::End | Kind::Die | Kind::Return => 1,
|
||||
u => unreachable!("{u:?}"),
|
||||
});
|
||||
|
||||
|
@ -194,23 +176,24 @@ impl Nodes {
|
|||
self[target].depth.get()
|
||||
}
|
||||
|
||||
fn fix_loops(&mut self) {
|
||||
'o: for l in self[LOOPS].outputs.clone() {
|
||||
let mut cursor = self[l].inputs[1];
|
||||
let depth = self.loop_depth(cursor);
|
||||
while cursor != l {
|
||||
if self[cursor].kind == Kind::If
|
||||
&& self[cursor].outputs.iter().any(|&b| self.loop_depth(b) < depth)
|
||||
{
|
||||
continue 'o;
|
||||
fn fix_loops(&mut self, stack: &mut Vec<Nid>, seen: &mut BitSet) {
|
||||
debug_assert!(stack.is_empty());
|
||||
|
||||
stack.push(NEVER);
|
||||
|
||||
while let Some(node) = stack.pop() {
|
||||
if seen.set(node) && self.is_cfg(node) {
|
||||
stack.extend(self[node].inputs.iter());
|
||||
}
|
||||
cursor = self.idom(cursor);
|
||||
}
|
||||
|
||||
for l in self[LOOPS].outputs.clone() {
|
||||
if !seen.get(l) {
|
||||
self[l].outputs.push(NEVER);
|
||||
self[NEVER].inputs.push(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push_up_impl(&mut self, node: Nid, visited: &mut BitSet) {
|
||||
if !visited.set(node) {
|
||||
|
@ -599,7 +582,8 @@ impl Nodes {
|
|||
}
|
||||
|
||||
fn gcm(&mut self, rpo: &mut Vec<Nid>, visited: &mut BitSet) {
|
||||
self.fix_loops();
|
||||
visited.clear(self.values.len());
|
||||
self.fix_loops(rpo, visited);
|
||||
visited.clear(self.values.len());
|
||||
self.push_up(rpo, visited);
|
||||
visited.clear(self.values.len());
|
||||
|
@ -947,6 +931,10 @@ impl Nodes {
|
|||
}
|
||||
}
|
||||
K::If => {
|
||||
if self[target].inputs[0] == NEVER {
|
||||
return Some(NEVER);
|
||||
}
|
||||
|
||||
if self[target].ty == ty::Id::VOID {
|
||||
match self.try_opt_cond(target) {
|
||||
CondOptRes::Unknown => {}
|
||||
|
@ -962,6 +950,10 @@ impl Nodes {
|
|||
}
|
||||
}
|
||||
K::Then => {
|
||||
if self[target].inputs[0] == NEVER {
|
||||
return Some(NEVER);
|
||||
}
|
||||
|
||||
if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
|
||||
return Some(NEVER);
|
||||
} else if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
|
||||
|
@ -969,6 +961,10 @@ impl Nodes {
|
|||
}
|
||||
}
|
||||
K::Else => {
|
||||
if self[target].inputs[0] == NEVER {
|
||||
return Some(NEVER);
|
||||
}
|
||||
|
||||
if self[self[target].inputs[0]].ty == ty::Id::RIGHT_UNREACHABLE {
|
||||
return Some(NEVER);
|
||||
} else if self[self[target].inputs[0]].ty == ty::Id::LEFT_UNREACHABLE {
|
||||
|
@ -1354,6 +1350,7 @@ impl Nodes {
|
|||
return Some(self[target].inputs[0]);
|
||||
}
|
||||
}
|
||||
_ if self.is_cfg(target) && self.idom(target) == NEVER => panic!(),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -1665,6 +1662,40 @@ impl Nodes {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_loop_depth_integrity(&self, disp: ty::Display) {
|
||||
if !cfg!(debug_assertions) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut failed = false;
|
||||
for &loob in self[LOOPS].outputs.iter() {
|
||||
let mut stack = vec![self[loob].inputs[1]];
|
||||
let mut seen = BitSet::default();
|
||||
seen.set(loob);
|
||||
let depth = self.loop_depth(loob);
|
||||
while let Some(nid) = stack.pop() {
|
||||
if seen.set(nid) {
|
||||
if depth > self.loop_depth(nid) {
|
||||
failed = true;
|
||||
log::error!("{depth} {} {nid} {:?}", self.loop_depth(nid), self[nid]);
|
||||
}
|
||||
|
||||
match self[nid].kind {
|
||||
Kind::Loop | Kind::Region => {
|
||||
stack.extend(&self[nid].inputs[..2]);
|
||||
}
|
||||
_ => stack.push(self[nid].inputs[0]),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if failed {
|
||||
self.graphviz_in_browser(disp);
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
fn load_loop_var(&mut self, index: usize, var: &mut Variable, loops: &mut [Loop]) {
|
||||
if var.value() != VOID {
|
||||
return;
|
||||
|
@ -1748,14 +1779,16 @@ impl Nodes {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_data_dep(&self, nid: Nid, n: Nid) -> bool {
|
||||
match self[n].kind {
|
||||
Kind::Return => self[n].inputs[1] == nid,
|
||||
_ if self.is_cfg(n) && !matches!(self[n].kind, Kind::Call { .. } | Kind::If) => false,
|
||||
fn is_data_dep(&self, val: Nid, user: Nid) -> bool {
|
||||
match self[user].kind {
|
||||
Kind::Return => self[user].inputs[1] == val,
|
||||
_ if self.is_cfg(user) && !matches!(self[user].kind, Kind::Call { .. } | Kind::If) => {
|
||||
false
|
||||
}
|
||||
Kind::Join => 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),
|
||||
Kind::Stre => self[user].inputs[3] != val,
|
||||
Kind::Load => self[user].inputs[2] != val,
|
||||
_ => self[user].inputs[0] != val || self[user].inputs[1..].contains(&val),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4426,6 +4459,7 @@ impl<'a> Codegen<'a> {
|
|||
self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID));
|
||||
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
||||
self.ci.nodes.gcm(&mut self.pool.nid_stack, &mut self.pool.nid_set);
|
||||
self.ci.nodes.check_loop_depth_integrity(self.ty_display(ty::Id::VOID));
|
||||
self.ci.nodes.basic_blocks();
|
||||
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
||||
} else {
|
||||
|
@ -4844,6 +4878,7 @@ mod tests {
|
|||
fb_driver;
|
||||
|
||||
// Purely Testing Examples;
|
||||
different_function_destinations;
|
||||
triggering_store_in_divergent_branch;
|
||||
wrong_dead_code_elimination;
|
||||
memory_swap;
|
||||
|
|
|
@ -336,6 +336,18 @@ impl Backend for HbvmBackend {
|
|||
}
|
||||
|
||||
impl Nodes {
|
||||
fn strip_offset(&self, region: Nid, ty: ty::Id, tys: &Types) -> (Nid, Offset) {
|
||||
if matches!(self[region].kind, Kind::BinOp { op: TokenKind::Add | TokenKind::Sub })
|
||||
&& self[region].lock_rc != 0
|
||||
&& let Kind::CInt { value } = self[self[region].inputs[2]].kind
|
||||
&& ty.loc(tys) == Loc::Reg
|
||||
{
|
||||
(self[region].inputs[1], value as _)
|
||||
} else {
|
||||
(region, 0)
|
||||
}
|
||||
}
|
||||
|
||||
fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) {
|
||||
// NOTE: this code is horible
|
||||
let fromc = Some(&from);
|
||||
|
@ -638,17 +650,10 @@ impl HbvmBackend {
|
|||
self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
||||
}
|
||||
|
||||
if let Some(PLoc::WideReg(r, size)) = ret {
|
||||
debug_assert_eq!(nodes[*node.inputs.last().unwrap()].kind, Kind::Stck);
|
||||
let stck = self.offsets[*node.inputs.last().unwrap() as usize];
|
||||
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
|
||||
}
|
||||
if let Some(PLoc::Reg(r, size)) = ret
|
||||
&& node.ty.loc(tys) == Loc::Stack
|
||||
if node.ty.loc(tys) == Loc::Stack
|
||||
&& let Some(PLoc::Reg(r, size) | PLoc::WideReg(r, size)) = ret
|
||||
{
|
||||
debug_assert_eq!(nodes[*node.inputs.last().unwrap()].kind, Kind::Stck);
|
||||
let stck = self.offsets[*node.inputs.last().unwrap() as usize];
|
||||
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
|
||||
self.emit(instrs::st(r, *allocs.last().unwrap(), 0, size));
|
||||
}
|
||||
}
|
||||
Kind::Global { global } => {
|
||||
|
@ -662,14 +667,7 @@ impl HbvmBackend {
|
|||
self.emit(instrs::addi64(allocs[0], base, offset as _));
|
||||
}
|
||||
Kind::Load => {
|
||||
let mut region = node.inputs[1];
|
||||
let mut offset = 0;
|
||||
if nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||
&& let Kind::CInt { value } = nodes[nodes[region].inputs[2]].kind
|
||||
{
|
||||
region = nodes[region].inputs[1];
|
||||
offset = value as Offset;
|
||||
}
|
||||
let (region, offset) = nodes.strip_offset(node.inputs[1], node.ty, tys);
|
||||
let size = tys.size_of(node.ty);
|
||||
if node.ty.loc(tys) != Loc::Stack {
|
||||
let (base, offset) = match nodes[region].kind {
|
||||
|
@ -681,16 +679,8 @@ impl HbvmBackend {
|
|||
}
|
||||
Kind::Stre if node.inputs[1] == VOID => {}
|
||||
Kind::Stre => {
|
||||
let mut region = node.inputs[2];
|
||||
let mut offset = 0;
|
||||
let (region, offset) = nodes.strip_offset(node.inputs[2], node.ty, tys);
|
||||
let size = u16::try_from(tys.size_of(node.ty)).expect("TODO");
|
||||
if nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||
&& let Kind::CInt { value } = nodes[nodes[region].inputs[2]].kind
|
||||
&& node.ty.loc(tys) == Loc::Reg
|
||||
{
|
||||
region = nodes[region].inputs[1];
|
||||
offset = value as Offset;
|
||||
}
|
||||
let (base, offset, src) = match nodes[region].kind {
|
||||
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
||||
(reg::STACK_PTR, self.offsets[region as usize] + offset, allocs[0])
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use {
|
||||
super::{HbvmBackend, Nid, Nodes},
|
||||
crate::{
|
||||
lexer::TokenKind,
|
||||
parser,
|
||||
reg::{self, Reg},
|
||||
son::{debug_assert_matches, Kind, ARG_START, MEM, VOID},
|
||||
|
@ -10,7 +9,8 @@ use {
|
|||
PLoc, Sig, Types,
|
||||
},
|
||||
alloc::{borrow::ToOwned, vec::Vec},
|
||||
core::{mem, ops::Range},
|
||||
core::{cell::RefCell, mem, ops::Range},
|
||||
hashbrown::HashSet,
|
||||
hbbytecode::{self as instrs},
|
||||
};
|
||||
|
||||
|
@ -101,6 +101,28 @@ impl HbvmBackend {
|
|||
let node = &fuc.nodes[nid];
|
||||
alloc_buf.clear();
|
||||
|
||||
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)
|
||||
);
|
||||
debug_assert!(
|
||||
fuc.marked.borrow().contains(&(allc, nid))
|
||||
|| nid == allc
|
||||
|| fuc.nodes.is_hard_zero(allc)
|
||||
|| allc == MEM
|
||||
|| matches!(node.kind, Kind::Loop | Kind::Region),
|
||||
"{nid} {:?}\n{allc} {:?}",
|
||||
fuc.nodes[nid],
|
||||
fuc.nodes[allc]
|
||||
);
|
||||
res.node_to_reg[allc as usize]
|
||||
};
|
||||
|
||||
let mut is_next_block = false;
|
||||
match node.kind {
|
||||
Kind::If => {
|
||||
|
@ -170,13 +192,14 @@ impl HbvmBackend {
|
|||
}
|
||||
Kind::Return => {
|
||||
let &[_, ret, ..] = node.inputs.as_slice() else { unreachable!() };
|
||||
alloc_buf.push(atr(ret));
|
||||
match retl {
|
||||
Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => {
|
||||
alloc_buf.push(atr(ret));
|
||||
self.emit(instrs::cp(r, atr(ret)));
|
||||
}
|
||||
Some(PLoc::Ref(..)) => alloc_buf.push(atr(MEM)),
|
||||
_ => {}
|
||||
Some(PLoc::Ref(..)) => alloc_buf.extend([atr(ret), atr(MEM)]),
|
||||
Some(_) => alloc_buf.push(atr(ret)),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
Kind::Die => self.emit(instrs::un()),
|
||||
|
@ -224,12 +247,7 @@ impl HbvmBackend {
|
|||
}
|
||||
Kind::Stck | Kind::Global { .. } => alloc_buf.push(atr(nid)),
|
||||
Kind::Load => {
|
||||
let mut region = node.inputs[1];
|
||||
if fuc.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||
&& let Kind::CInt { .. } = fuc.nodes[fuc.nodes[region].inputs[2]].kind
|
||||
{
|
||||
region = fuc.nodes[region].inputs[1];
|
||||
}
|
||||
let (region, _) = fuc.nodes.strip_offset(node.inputs[1], node.ty, tys);
|
||||
if node.ty.loc(tys) != Loc::Stack {
|
||||
alloc_buf.push(atr(nid));
|
||||
match fuc.nodes[region].kind {
|
||||
|
@ -240,14 +258,7 @@ impl HbvmBackend {
|
|||
}
|
||||
Kind::Stre if node.inputs[1] == VOID => {}
|
||||
Kind::Stre => {
|
||||
let mut region = node.inputs[2];
|
||||
if matches!(fuc.nodes[region].kind, Kind::BinOp {
|
||||
op: TokenKind::Add | TokenKind::Sub
|
||||
}) && let Kind::CInt { .. } = fuc.nodes[fuc.nodes[region].inputs[2]].kind
|
||||
&& node.ty.loc(tys) == Loc::Reg
|
||||
{
|
||||
region = fuc.nodes[region].inputs[1];
|
||||
}
|
||||
let (region, _) = fuc.nodes.strip_offset(node.inputs[2], node.ty, tys);
|
||||
match fuc.nodes[region].kind {
|
||||
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
||||
alloc_buf.push(atr(node.inputs[1]))
|
||||
|
@ -313,6 +324,7 @@ pub struct Function<'a> {
|
|||
tys: &'a Types,
|
||||
visited: BitSet,
|
||||
func: Func,
|
||||
marked: RefCell<HashSet<(Nid, Nid), crate::FnvBuildHasher>>,
|
||||
}
|
||||
|
||||
impl Function<'_> {
|
||||
|
@ -334,6 +346,7 @@ impl Function<'_> {
|
|||
.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))
|
||||
.inspect(|&(_, n)| _ = self.marked.borrow_mut().insert((nid, n)))
|
||||
.collect_into(buf);
|
||||
}
|
||||
|
||||
|
@ -347,20 +360,11 @@ impl Function<'_> {
|
|||
|
||||
fn phi_inputs_of(&self, nid: Nid, buf: &mut Vec<Nid>) {
|
||||
match self.nodes[nid].kind {
|
||||
Kind::Region => {
|
||||
Kind::Region | Kind::Loop => {
|
||||
for &inp in self.nodes[nid].outputs.as_slice() {
|
||||
if self.nodes[inp].is_data_phi() {
|
||||
buf.push(inp);
|
||||
buf.extend(&self.nodes[inp].inputs[1..]);
|
||||
buf.push(inp);
|
||||
}
|
||||
}
|
||||
}
|
||||
Kind::Loop => {
|
||||
for &inp in self.nodes[nid].outputs.as_slice() {
|
||||
if self.nodes[inp].is_data_phi() {
|
||||
buf.push(self.nodes[inp].inputs[1]);
|
||||
buf.push(inp);
|
||||
buf.push(self.nodes[inp].inputs[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -412,6 +416,7 @@ impl<'a> Function<'a> {
|
|||
sig,
|
||||
visited: Default::default(),
|
||||
func: Default::default(),
|
||||
marked: Default::default(),
|
||||
};
|
||||
s.visited.clear(s.nodes.values.len());
|
||||
s.emit_node(VOID);
|
||||
|
@ -580,13 +585,25 @@ impl<'a> Env<'a> {
|
|||
let mut use_buf = mem::take(&mut self.res.use_buf);
|
||||
|
||||
let mut phi_input_buf = mem::take(&mut self.res.phi_input_buf);
|
||||
for block in &self.func.blocks {
|
||||
for block in self.func.blocks.iter().rev() {
|
||||
self.ctx.phi_inputs_of(block.entry, &mut phi_input_buf);
|
||||
for param in phi_input_buf.drain(..) {
|
||||
if !visited.set(param) {
|
||||
for [a, rest @ ..] in phi_input_buf.drain(..).array_chunks::<3>() {
|
||||
if visited.set(a) {
|
||||
self.append_bundle(a, &mut bundle, &mut use_buf, None);
|
||||
}
|
||||
|
||||
for r in rest {
|
||||
if !visited.set(r) {
|
||||
continue;
|
||||
}
|
||||
self.append_bundle(param, &mut bundle, &mut use_buf);
|
||||
|
||||
self.append_bundle(
|
||||
r,
|
||||
&mut bundle,
|
||||
&mut use_buf,
|
||||
Some(self.res.node_to_reg[a as usize] as usize - 1),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.res.phi_input_buf = phi_input_buf;
|
||||
|
@ -595,13 +612,19 @@ impl<'a> Env<'a> {
|
|||
if visited.get(inst) || inst == 0 {
|
||||
continue;
|
||||
}
|
||||
self.append_bundle(inst, &mut bundle, &mut use_buf);
|
||||
self.append_bundle(inst, &mut bundle, &mut use_buf, None);
|
||||
}
|
||||
|
||||
self.res.use_buf = use_buf;
|
||||
}
|
||||
|
||||
fn append_bundle(&mut self, inst: Nid, bundle: &mut Bundle, use_buf: &mut Vec<(Nid, Nid)>) {
|
||||
fn append_bundle(
|
||||
&mut self,
|
||||
inst: Nid,
|
||||
bundle: &mut Bundle,
|
||||
use_buf: &mut Vec<(Nid, Nid)>,
|
||||
prefered: Option<usize>,
|
||||
) {
|
||||
let dom = self.ctx.idom_of(inst);
|
||||
self.ctx.uses_of(inst, use_buf);
|
||||
for (cursor, uinst) in use_buf.drain(..) {
|
||||
|
@ -611,7 +634,7 @@ impl<'a> Env<'a> {
|
|||
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(
|
||||
let new = range.end.min(
|
||||
self.ctx
|
||||
.instr_of(uinst)
|
||||
.filter(|_| {
|
||||
|
@ -621,6 +644,8 @@ impl<'a> Env<'a> {
|
|||
})
|
||||
.map_or(Nid::MAX, |n| n + 1) as usize,
|
||||
);
|
||||
|
||||
range.end = new;
|
||||
debug_assert!(range.start < range.end);
|
||||
|
||||
bundle.add(range);
|
||||
|
@ -632,6 +657,13 @@ impl<'a> Env<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
if let Some(prefered) = prefered
|
||||
&& !self.res.bundles[prefered].overlaps(bundle)
|
||||
{
|
||||
self.res.bundles[prefered].merge(bundle);
|
||||
bundle.clear();
|
||||
self.res.node_to_reg[inst as usize] = prefered as Reg + 1;
|
||||
} else {
|
||||
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) {
|
||||
Some((i, other)) => {
|
||||
other.merge(bundle);
|
||||
|
@ -639,11 +671,14 @@ impl<'a> Env<'a> {
|
|||
self.res.node_to_reg[inst as usize] = i as Reg + 1;
|
||||
}
|
||||
None => {
|
||||
self.res.bundles.push(mem::replace(bundle, Bundle::new(self.func.instrs.len())));
|
||||
self.res
|
||||
.bundles
|
||||
.push(mem::replace(bundle, Bundle::new(self.func.instrs.len())));
|
||||
self.res.node_to_reg[inst as usize] = self.res.bundles.len() as Reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reverse_cfg_dfs(
|
||||
&mut self,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use {
|
||||
super::{HbvmBackend, Nid, Nodes},
|
||||
crate::{
|
||||
lexer::TokenKind,
|
||||
parser, reg,
|
||||
son::{debug_assert_matches, Kind, ARG_START, MEM, NEVER, VOID},
|
||||
ty::{self, Arg, Loc},
|
||||
|
@ -540,6 +539,8 @@ impl<'a> Function<'a> {
|
|||
self.rg(*node.inputs.last().unwrap()),
|
||||
regalloc2::PReg::new(r as _, regalloc2::RegClass::Int),
|
||||
));
|
||||
} else if node.ty.loc(self.tys) == Loc::Stack {
|
||||
ops.push(self.urg(*node.inputs.last().unwrap()));
|
||||
}
|
||||
|
||||
self.add_instr(nid, ops);
|
||||
|
@ -565,13 +566,7 @@ impl<'a> Function<'a> {
|
|||
Kind::Assert { .. } => unreachable!(),
|
||||
Kind::End | Kind::Phi | Kind::Arg | Kind::Mem | Kind::Loops | Kind::Join => {}
|
||||
Kind::Load { .. } => {
|
||||
let mut region = node.inputs[1];
|
||||
if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||
&& self.nodes.is_const(self.nodes[region].inputs[2])
|
||||
&& node.ty.loc(self.tys) == Loc::Reg
|
||||
{
|
||||
region = self.nodes[region].inputs[1]
|
||||
}
|
||||
let (region, _) = self.nodes.strip_offset(node.inputs[1], node.ty, self.tys);
|
||||
let ops = match self.nodes[region].kind {
|
||||
Kind::Stck => vec![self.drg(nid)],
|
||||
_ => vec![self.drg(nid), self.urg(region)],
|
||||
|
@ -580,13 +575,7 @@ impl<'a> Function<'a> {
|
|||
}
|
||||
Kind::Stre => {
|
||||
debug_assert_ne!(self.tys.size_of(node.ty), 0);
|
||||
let mut region = node.inputs[2];
|
||||
if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
|
||||
&& self.nodes.is_const(self.nodes[region].inputs[2])
|
||||
&& node.ty.loc(self.tys) == Loc::Reg
|
||||
{
|
||||
region = self.nodes[region].inputs[1]
|
||||
}
|
||||
let (region, _) = self.nodes.strip_offset(node.inputs[2], node.ty, self.tys);
|
||||
let ops = match self.nodes[region].kind {
|
||||
_ if node.ty.loc(self.tys) == Loc::Stack => {
|
||||
if self.nodes[node.inputs[1]].kind == Kind::Arg {
|
||||
|
|
82
lang/tests/son_tests_different_function_destinations.txt
Normal file
82
lang/tests/son_tests_different_function_destinations.txt
Normal file
|
@ -0,0 +1,82 @@
|
|||
main:
|
||||
ADDI64 r254, r254, -208d
|
||||
ST r31, r254, 80a, 128h
|
||||
LRA r32, r0, :glob_stru
|
||||
JAL r31, r0, :new_stru
|
||||
ST r1, r32, 0a, 16h
|
||||
CP r1, r0
|
||||
LD r33, r32, 0a, 8h
|
||||
JEQ r33, r1, :0
|
||||
LI64 r1, 300d
|
||||
JMP :1
|
||||
0: LI64 r34, 1d
|
||||
ST r34, r32, 0a, 8h
|
||||
ST r34, r32, 8a, 8h
|
||||
ST r1, r32, 0a, 8h
|
||||
LD r35, r32, 0a, 8h
|
||||
JEQ r35, r1, :2
|
||||
LI64 r1, 200d
|
||||
JMP :1
|
||||
2: CP r36, r1
|
||||
LI64 r37, 3d
|
||||
ST r34, r32, 0a, 8h
|
||||
ST r34, r32, 8a, 8h
|
||||
ADDI64 r38, r254, 16d
|
||||
ST r34, r254, 16a, 8h
|
||||
ST r34, r254, 24a, 8h
|
||||
ST r34, r254, 32a, 8h
|
||||
ST r34, r254, 40a, 8h
|
||||
ST r34, r254, 48a, 8h
|
||||
ST r34, r254, 56a, 8h
|
||||
CP r39, r36
|
||||
8: JNE r39, r37, :3
|
||||
LD r40, r254, 48a, 8h
|
||||
CP r1, r36
|
||||
JEQ r40, r1, :4
|
||||
LI64 r1, 100d
|
||||
JMP :1
|
||||
4: ST r1, r254, 0a, 8h
|
||||
ST r1, r254, 8a, 8h
|
||||
ST r1, r254, 64a, 8h
|
||||
ST r1, r254, 72a, 8h
|
||||
ST r34, r254, 16a, 8h
|
||||
ST r34, r254, 24a, 8h
|
||||
ST r34, r254, 32a, 8h
|
||||
ST r34, r254, 40a, 8h
|
||||
ST r34, r254, 48a, 8h
|
||||
ST r34, r254, 56a, 8h
|
||||
CP r41, r1
|
||||
7: LD r42, r254, 48a, 8h
|
||||
JNE r41, r37, :5
|
||||
JEQ r42, r1, :6
|
||||
LI64 r1, 10d
|
||||
JMP :1
|
||||
6: JMP :1
|
||||
5: ADD64 r43, r41, r34
|
||||
MULI64 r44, r41, 16d
|
||||
ADD64 r45, r38, r44
|
||||
ST r1, r45, 0a, 8h
|
||||
ST r1, r45, 8a, 8h
|
||||
CP r36, r1
|
||||
CP r41, r43
|
||||
JMP :7
|
||||
3: MULI64 r46, r39, 16d
|
||||
ADD64 r43, r38, r46
|
||||
JAL r31, r0, :new_stru
|
||||
ST r1, r43, 0a, 16h
|
||||
ADD64 r39, r39, r34
|
||||
JMP :8
|
||||
1: LD r31, r254, 80a, 128h
|
||||
ADDI64 r254, r254, 208d
|
||||
JALA r0, r31, 0a
|
||||
new_stru:
|
||||
ADDI64 r254, r254, -16d
|
||||
ADDI64 r3, r254, 0d
|
||||
ST r0, r254, 0a, 8h
|
||||
ST r0, r254, 8a, 8h
|
||||
LD r1, r3, 0a, 16h
|
||||
ADDI64 r254, r254, 16d
|
||||
JALA r0, r31, 0a
|
||||
code size: 759
|
||||
ret: 0
|
||||
status: Ok(())
|
|
@ -1,16 +1,16 @@
|
|||
continue_and_state_change:
|
||||
LI64 r9, 3d
|
||||
LI64 r10, 4d
|
||||
LI64 r11, 2d
|
||||
LI64 r12, 10d
|
||||
6: JLTU r2, r12, :0
|
||||
CP r1, r0
|
||||
LI64 r10, 3d
|
||||
LI64 r11, 4d
|
||||
LI64 r12, 2d
|
||||
LI64 r3, 10d
|
||||
6: JLTU r2, r3, :0
|
||||
CP r1, r2
|
||||
JMP :1
|
||||
0: JNE r2, r11, :2
|
||||
CP r2, r10
|
||||
0: JNE r2, r12, :2
|
||||
CP r2, r11
|
||||
JMP :3
|
||||
2: JNE r2, r9, :4
|
||||
CP r1, r0
|
||||
2: JNE r2, r10, :4
|
||||
1: JMP :5
|
||||
4: ADDI64 r2, r2, 1d
|
||||
3: JMP :6
|
||||
|
|
|
@ -3,7 +3,7 @@ main:
|
|||
ST r31, r254, 6a, 24h
|
||||
ADDI64 r32, r254, 0d
|
||||
2: JAL r31, r0, :return_fn
|
||||
ST r1, r254, 0a, 6h
|
||||
ST r1, r32, 0a, 6h
|
||||
LD r33, r254, 0a, 1h
|
||||
ANDI r33, r33, 255d
|
||||
ANDI r0, r0, 255d
|
||||
|
|
|
@ -4,7 +4,7 @@ foo:
|
|||
ADDI64 r32, r254, 64d
|
||||
LRA r3, r0, :some_file
|
||||
JAL r31, r0, :get
|
||||
ST r1, r254, 64a, 16h
|
||||
ST r1, r32, 0a, 16h
|
||||
LD r33, r254, 64a, 1h
|
||||
ANDI r33, r33, 255d
|
||||
ANDI r0, r0, 255d
|
||||
|
@ -60,7 +60,7 @@ main:
|
|||
ST r31, r254, 16a, 24h
|
||||
ADDI64 r32, r254, 0d
|
||||
JAL r31, r0, :foo
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r32, 0a, 16h
|
||||
LD r33, r254, 0a, 1h
|
||||
ANDI r33, r33, 255d
|
||||
ANDI r0, r0, 255d
|
||||
|
|
|
@ -7,7 +7,7 @@ main:
|
|||
JAL r31, r0, :returner_bn
|
||||
ADDI64 r33, r254, 0d
|
||||
JAL r31, r0, :returner_cn
|
||||
ST r1, r254, 0a, 2h
|
||||
ST r1, r33, 0a, 2h
|
||||
LD r34, r254, 2a, 1h
|
||||
CP r1, r32
|
||||
CMPU r35, r1, r0
|
||||
|
|
|
@ -45,22 +45,21 @@ main:
|
|||
JNE r40, r39, :9
|
||||
LI64 r1, 69d
|
||||
JMP :3
|
||||
9: ADDI64 r3, r254, 40d
|
||||
CP r41, r3
|
||||
9: ADDI64 r41, r254, 40d
|
||||
JAL r31, r0, :new_foo
|
||||
ST r1, r254, 40a, 16h
|
||||
ST r1, r41, 0a, 16h
|
||||
CP r3, r41
|
||||
LD r42, r254, 40a, 8h
|
||||
JNE r42, r0, :10
|
||||
LI64 r1, 999d
|
||||
JMP :3
|
||||
10: LRA r4, r0, :"foo\0"
|
||||
CP r3, r41
|
||||
CP r2, r3
|
||||
LD r2, r2, 0a, 16h
|
||||
JAL r31, r0, :use_foo
|
||||
ADDI64 r43, r254, 0d
|
||||
JAL r31, r0, :no_foo
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r43, 0a, 16h
|
||||
JAL r31, r0, :decide
|
||||
ANDI r1, r1, 255d
|
||||
JNE r1, r0, :11
|
||||
|
@ -126,6 +125,6 @@ use_foo:
|
|||
ADDI64 r2, r254, 0d
|
||||
ADDI64 r254, r254, 16d
|
||||
JALA r0, r31, 0a
|
||||
code size: 1100
|
||||
code size: 1097
|
||||
ret: 0
|
||||
status: Ok(())
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
main:
|
||||
ADDI64 r254, r254, -16d
|
||||
ADDI64 r4, r254, 0d
|
||||
ADDI64 r7, r254, 0d
|
||||
CP r3, r0
|
||||
CP r4, r0
|
||||
CP r5, r0
|
||||
CP r6, r0
|
||||
ECA
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r7, 0a, 16h
|
||||
LD r7, r254, 0a, 1h
|
||||
ANDI r7, r7, 255d
|
||||
ANDI r0, r0, 255d
|
||||
|
|
|
@ -8,7 +8,7 @@ main:
|
|||
ST r34, r254, 0a, 8h
|
||||
ST r33, r254, 8a, 8h
|
||||
JAL r31, r0, :opaque
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r32, 0a, 16h
|
||||
LD r35, r254, 8a, 8h
|
||||
LD r36, r254, 16a, 8h
|
||||
ADD64 r37, r36, r35
|
||||
|
|
|
@ -3,7 +3,7 @@ main:
|
|||
ST r31, r254, 4a, 96h
|
||||
ADDI64 r32, r254, 0d
|
||||
JAL r31, r0, :random_color
|
||||
ST r1, r254, 0a, 4h
|
||||
ST r1, r32, 0a, 4h
|
||||
LD r33, r254, 0a, 1h
|
||||
LD r34, r254, 1a, 1h
|
||||
LD r35, r254, 2a, 1h
|
||||
|
|
|
@ -14,7 +14,7 @@ main:
|
|||
ST r31, r254, 16a, 24h
|
||||
ADDI64 r32, r254, 0d
|
||||
JAL r31, r0, :get_format
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r32, 0a, 16h
|
||||
LD r33, r254, 0a, 1h
|
||||
ANDI r33, r33, 255d
|
||||
ANDI r0, r0, 255d
|
||||
|
|
|
@ -16,7 +16,7 @@ main:
|
|||
ADDI64 r32, r254, 0d
|
||||
CP r3, r0
|
||||
JAL r31, r0, :constructor
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r32, 0a, 16h
|
||||
LD r31, r254, 16a, 16h
|
||||
ADDI64 r254, r254, 32d
|
||||
JALA r0, r31, 0a
|
||||
|
|
|
@ -5,7 +5,7 @@ main:
|
|||
ADDI64 r33, r254, 0d
|
||||
LD r2, r32, 0a, 4h
|
||||
JAL r31, r0, :u32_to_color
|
||||
ST r1, r254, 0a, 4h
|
||||
ST r1, r33, 0a, 4h
|
||||
LD r34, r254, 0a, 1h
|
||||
ANDI r1, r34, 255d
|
||||
LD r31, r254, 4a, 32h
|
||||
|
|
|
@ -21,7 +21,7 @@ main:
|
|||
CP r34, r1
|
||||
ADDI64 r35, r254, 0d
|
||||
JAL r31, r0, :optional
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r35, 0a, 16h
|
||||
LD r36, r254, 0a, 1h
|
||||
ANDI r36, r36, 255d
|
||||
ANDI r0, r0, 255d
|
||||
|
|
|
@ -14,13 +14,13 @@ main:
|
|||
ST r31, r254, 48a, 80h
|
||||
ADDI64 r32, r254, 32d
|
||||
JAL r31, r0, :foo
|
||||
ST r1, r254, 32a, 16h
|
||||
ST r1, r32, 0a, 16h
|
||||
ADDI64 r33, r254, 16d
|
||||
JAL r31, r0, :foo
|
||||
ST r1, r254, 16a, 16h
|
||||
ST r1, r33, 0a, 16h
|
||||
ADDI64 r34, r254, 0d
|
||||
JAL r31, r0, :foo
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r34, 0a, 16h
|
||||
LD r35, r254, 24a, 4h
|
||||
LD r36, r254, 12a, 4h
|
||||
ANDI r37, r35, 4294967295d
|
||||
|
|
|
@ -10,7 +10,7 @@ main:
|
|||
CP r3, r4
|
||||
LD r3, r3, 0a, 16h
|
||||
JAL r31, r0, :odher_pass
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r34, 0a, 16h
|
||||
LD r35, r254, 8a, 8h
|
||||
JNE r35, r33, :0
|
||||
CP r2, r34
|
||||
|
|
|
@ -5,7 +5,7 @@ main:
|
|||
CP r4, r0
|
||||
CP r3, r4
|
||||
JAL r31, r0, :maina
|
||||
ST r1, r254, 0a, 16h
|
||||
ST r1, r32, 0a, 16h
|
||||
LD r33, r254, 12a, 1h
|
||||
LD r34, r254, 3a, 1h
|
||||
SUB8 r35, r34, r33
|
||||
|
@ -18,7 +18,7 @@ maina:
|
|||
ST r31, r254, 20a, 40h
|
||||
ADDI64 r32, r254, 16d
|
||||
JAL r31, r0, :small_struct
|
||||
ST r1, r254, 16a, 4h
|
||||
ST r1, r32, 0a, 4h
|
||||
ADDI64 r33, r254, 0d
|
||||
ST r0, r254, 0a, 1h
|
||||
ST r0, r254, 1a, 1h
|
||||
|
|
Loading…
Reference in a new issue