From 981c17ff19cee72265612e4e9f9cf7f0bfc94697 Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Thu, 14 Nov 2024 20:25:52 +0100 Subject: [PATCH] fixing function destinations --- lang/README.md | 35 +++++ lang/src/lib.rs | 1 + lang/src/son.rs | 139 +++++++++++------- lang/src/son/hbvm.rs | 44 +++--- lang/src/son/hbvm/my_regalloc.rs | 129 ++++++++++------ lang/src/son/hbvm/their_regalloc.rs | 19 +-- ..._tests_different_function_destinations.txt | 82 +++++++++++ .../son_tests_exhaustive_loop_testing.txt | 18 +-- .../son_tests_null_check_in_the_loop.txt | 2 +- ...ests_null_check_returning_small_global.txt | 4 +- lang/tests/son_tests_nullable_structure.txt | 2 +- lang/tests/son_tests_nullable_types.txt | 11 +- lang/tests/son_tests_optional_from_eca.txt | 4 +- ...ts_overwrite_aliasing_overoptimization.txt | 2 +- .../son_tests_returning_global_struct.txt | 2 +- .../son_tests_returning_optional_issues.txt | 2 +- .../son_tests_scheduling_block_did_dirty.txt | 2 +- lang/tests/son_tests_small_struct_bitcast.txt | 2 +- ...son_tests_storing_into_nullable_struct.txt | 2 +- ...sts_struct_return_from_module_function.txt | 6 +- lang/tests/son_tests_structs.txt | 2 +- lang/tests/son_tests_wide_ret.txt | 4 +- 22 files changed, 340 insertions(+), 174 deletions(-) create mode 100644 lang/tests/son_tests_different_function_destinations.txt diff --git a/lang/README.md b/lang/README.md index 1080c28..ae70755 100644 --- a/lang/README.md +++ b/lang/README.md @@ -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 { diff --git a/lang/src/lib.rs b/lang/src/lib.rs index f0d61c1..fa5488f 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -1,4 +1,5 @@ #![feature( + iter_array_chunks, assert_matches, let_chains, if_let_guard, diff --git a/lang/src/son.rs b/lang/src/son.rs index d6391d3..24d65c0 100644 --- a/lang/src/son.rs +++ b/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 { - self[other].loop_depth.set(depth - 1); - } + 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,21 +176,22 @@ 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; - } - cursor = self.idom(cursor); - } + fn fix_loops(&mut self, stack: &mut Vec, seen: &mut BitSet) { + debug_assert!(stack.is_empty()); - self[l].outputs.push(NEVER); - self[NEVER].inputs.push(l); + stack.push(NEVER); + + while let Some(node) = stack.pop() { + if seen.set(node) && self.is_cfg(node) { + stack.extend(self[node].inputs.iter()); + } + } + + for l in self[LOOPS].outputs.clone() { + if !seen.get(l) { + self[l].outputs.push(NEVER); + self[NEVER].inputs.push(l); + } } } @@ -599,7 +582,8 @@ impl Nodes { } fn gcm(&mut self, rpo: &mut Vec, 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; diff --git a/lang/src/son/hbvm.rs b/lang/src/son/hbvm.rs index 6b30995..1a79b6d 100644 --- a/lang/src/son/hbvm.rs +++ b/lang/src/son/hbvm.rs @@ -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]) diff --git a/lang/src/son/hbvm/my_regalloc.rs b/lang/src/son/hbvm/my_regalloc.rs index 6c84121..ad33569 100644 --- a/lang/src/son/hbvm/my_regalloc.rs +++ b/lang/src/son/hbvm/my_regalloc.rs @@ -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>, } 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) { 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) { - continue; + 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( + r, + &mut bundle, + &mut use_buf, + Some(self.res.node_to_reg[a as usize] as usize - 1), + ); } - self.append_bundle(param, &mut bundle, &mut use_buf); } } 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, + ) { 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,15 +657,25 @@ impl<'a> Env<'a> { return; } - match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) { - Some((i, other)) => { - other.merge(bundle); - bundle.clear(); - 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.node_to_reg[inst as usize] = self.res.bundles.len() as Reg; + 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); + bundle.clear(); + 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.node_to_reg[inst as usize] = self.res.bundles.len() as Reg; + } } } } diff --git a/lang/src/son/hbvm/their_regalloc.rs b/lang/src/son/hbvm/their_regalloc.rs index 2d8d2eb..6483b43 100644 --- a/lang/src/son/hbvm/their_regalloc.rs +++ b/lang/src/son/hbvm/their_regalloc.rs @@ -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 { diff --git a/lang/tests/son_tests_different_function_destinations.txt b/lang/tests/son_tests_different_function_destinations.txt new file mode 100644 index 0000000..4d251d1 --- /dev/null +++ b/lang/tests/son_tests_different_function_destinations.txt @@ -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(()) diff --git a/lang/tests/son_tests_exhaustive_loop_testing.txt b/lang/tests/son_tests_exhaustive_loop_testing.txt index 483ea0f..1eb2f62 100644 --- a/lang/tests/son_tests_exhaustive_loop_testing.txt +++ b/lang/tests/son_tests_exhaustive_loop_testing.txt @@ -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 diff --git a/lang/tests/son_tests_null_check_in_the_loop.txt b/lang/tests/son_tests_null_check_in_the_loop.txt index a840337..7bc2475 100644 --- a/lang/tests/son_tests_null_check_in_the_loop.txt +++ b/lang/tests/son_tests_null_check_in_the_loop.txt @@ -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 diff --git a/lang/tests/son_tests_null_check_returning_small_global.txt b/lang/tests/son_tests_null_check_returning_small_global.txt index 6c7d9c0..e20ea67 100644 --- a/lang/tests/son_tests_null_check_returning_small_global.txt +++ b/lang/tests/son_tests_null_check_returning_small_global.txt @@ -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 diff --git a/lang/tests/son_tests_nullable_structure.txt b/lang/tests/son_tests_nullable_structure.txt index 04fc68e..e83b737 100644 --- a/lang/tests/son_tests_nullable_structure.txt +++ b/lang/tests/son_tests_nullable_structure.txt @@ -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 diff --git a/lang/tests/son_tests_nullable_types.txt b/lang/tests/son_tests_nullable_types.txt index 688f300..0422f72 100644 --- a/lang/tests/son_tests_nullable_types.txt +++ b/lang/tests/son_tests_nullable_types.txt @@ -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(()) diff --git a/lang/tests/son_tests_optional_from_eca.txt b/lang/tests/son_tests_optional_from_eca.txt index 00ada79..d6d85eb 100644 --- a/lang/tests/son_tests_optional_from_eca.txt +++ b/lang/tests/son_tests_optional_from_eca.txt @@ -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 diff --git a/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt b/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt index c3a469c..dbeae42 100644 --- a/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt +++ b/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt @@ -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 diff --git a/lang/tests/son_tests_returning_global_struct.txt b/lang/tests/son_tests_returning_global_struct.txt index a9020ad..a247eff 100644 --- a/lang/tests/son_tests_returning_global_struct.txt +++ b/lang/tests/son_tests_returning_global_struct.txt @@ -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 diff --git a/lang/tests/son_tests_returning_optional_issues.txt b/lang/tests/son_tests_returning_optional_issues.txt index 6d3cf8c..54b2e2d 100644 --- a/lang/tests/son_tests_returning_optional_issues.txt +++ b/lang/tests/son_tests_returning_optional_issues.txt @@ -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 diff --git a/lang/tests/son_tests_scheduling_block_did_dirty.txt b/lang/tests/son_tests_scheduling_block_did_dirty.txt index 386085c..2ef56ac 100644 --- a/lang/tests/son_tests_scheduling_block_did_dirty.txt +++ b/lang/tests/son_tests_scheduling_block_did_dirty.txt @@ -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 diff --git a/lang/tests/son_tests_small_struct_bitcast.txt b/lang/tests/son_tests_small_struct_bitcast.txt index 0e299b4..1e7a2bd 100644 --- a/lang/tests/son_tests_small_struct_bitcast.txt +++ b/lang/tests/son_tests_small_struct_bitcast.txt @@ -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 diff --git a/lang/tests/son_tests_storing_into_nullable_struct.txt b/lang/tests/son_tests_storing_into_nullable_struct.txt index e521e2b..226507f 100644 --- a/lang/tests/son_tests_storing_into_nullable_struct.txt +++ b/lang/tests/son_tests_storing_into_nullable_struct.txt @@ -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 diff --git a/lang/tests/son_tests_struct_return_from_module_function.txt b/lang/tests/son_tests_struct_return_from_module_function.txt index 1fa54fa..1e0f82e 100644 --- a/lang/tests/son_tests_struct_return_from_module_function.txt +++ b/lang/tests/son_tests_struct_return_from_module_function.txt @@ -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 diff --git a/lang/tests/son_tests_structs.txt b/lang/tests/son_tests_structs.txt index de32c6e..243c6c2 100644 --- a/lang/tests/son_tests_structs.txt +++ b/lang/tests/son_tests_structs.txt @@ -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 diff --git a/lang/tests/son_tests_wide_ret.txt b/lang/tests/son_tests_wide_ret.txt index ff6a7c2..127fa72 100644 --- a/lang/tests/son_tests_wide_ret.txt +++ b/lang/tests/son_tests_wide_ret.txt @@ -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