adding global mutatuon to the test

This commit is contained in:
mlokr 2024-09-08 12:00:07 +02:00
parent ee30069195
commit bb41da484f
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
10 changed files with 287 additions and 174 deletions

View file

@ -217,6 +217,7 @@ fib := fn(n: int): int {
}
main := fn(): int {
complex_global_var += 5
return complex_global_var
}
```

View file

@ -2106,7 +2106,7 @@ impl Codegen {
}
E::BinOp { left, op, right } if op != T::Decl => 'ops: {
let left = self.expr_ctx(left, Ctx {
ty: ctx.ty.filter(|_| dbg!(dbg!(op).is_homogenous())),
ty: ctx.ty.filter(|_| op.is_homogenous()),
..Default::default()
})?;

View file

@ -13,16 +13,17 @@ use {
HashMap,
},
core::fmt,
hbvm::mem::softpaging::lookup,
std::{
cell::RefCell,
collections::{hash_map, BTreeMap},
default,
fmt::Display,
hash::{Hash as _, Hasher},
intrinsics::unreachable,
mem,
ops::{self, Range},
rc::Rc,
usize,
u32, usize,
},
};
@ -463,11 +464,43 @@ mod ty {
}
}
struct LookupEntry {
nid: u32,
hash: u64,
}
#[derive(Default)]
struct IdentityHash(u64);
impl std::hash::Hasher for IdentityHash {
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, _: &[u8]) {
unimplemented!()
}
fn write_u64(&mut self, i: u64) {
self.0 = i;
}
}
impl std::hash::Hash for LookupEntry {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u64(self.hash);
}
}
struct Nodes {
values: Vec<Result<Node, u32>>,
visited: BitSet,
free: u32,
lookup: HashMap<Nid, ()>,
lookup: std::collections::hash_map::HashMap<
LookupEntry,
(),
std::hash::BuildHasherDefault<IdentityHash>,
>,
}
impl Default for Nodes {
@ -504,7 +537,7 @@ impl Nodes {
let node = Node {
inputs: inps.into(),
kind: kind.clone(),
kind,
color: 0,
depth: u32::MAX,
lock_rc: 0,
@ -512,16 +545,18 @@ impl Nodes {
outputs: vec![],
};
let mut hasher = crate::FnvHasher::default();
node.key().hash(&mut hasher);
let (raw_entry, _) = Self::find_node(&mut self.lookup, &self.values, &node);
let mut lookup_meta = None;
if node.kind != Kind::Phi || node.inputs[2] != 0 {
let (raw_entry, hash) = Self::find_node(&mut self.lookup, &self.values, &node);
let entry = match raw_entry {
hash_map::RawEntryMut::Occupied(mut o) => return *o.get_key_value().0,
hash_map::RawEntryMut::Occupied(mut o) => return o.get_key_value().0.nid,
hash_map::RawEntryMut::Vacant(v) => v,
};
lookup_meta = Some((entry, hash));
}
if self.free == u32::MAX {
self.free = self.values.len() as _;
self.values.push(Err(u32::MAX));
@ -532,34 +567,41 @@ impl Nodes {
debug_assert_ne!(d, free);
self.values[d as usize].as_mut().unwrap().outputs.push(free);
}
self.free = mem::replace(&mut self.values[free as usize], Ok(node)).unwrap_err();
*entry.insert(free, ()).0
if let Some((entry, hash)) = lookup_meta {
entry.insert(LookupEntry { nid: free, hash }, ());
}
free
}
fn find_node<'a>(
lookup: &'a mut HashMap<Nid, ()>,
lookup: &'a mut std::collections::hash_map::HashMap<
LookupEntry,
(),
std::hash::BuildHasherDefault<IdentityHash>,
>,
values: &[Result<Node, u32>],
node: &Node,
) -> (hash_map::RawEntryMut<'a, u32, (), std::hash::BuildHasherDefault<crate::FnvHasher>>, u64)
{
) -> (
hash_map::RawEntryMut<'a, LookupEntry, (), std::hash::BuildHasherDefault<IdentityHash>>,
u64,
) {
let mut hasher = crate::FnvHasher::default();
node.key().hash(&mut hasher);
let hash = hasher.finish();
(
lookup
let entry = lookup
.raw_entry_mut()
.from_hash(hash, |&n| values[n as usize].as_ref().unwrap().key() == node.key()),
hash,
)
.from_hash(hash, |n| values[n.nid as usize].as_ref().unwrap().key() == node.key());
(entry, hash)
}
fn remove_node_lookup(&mut self, target: Nid) {
if self[target].kind != Kind::Phi || self[target].inputs[2] != 0 {
match Self::find_node(
&mut self.lookup,
&self.values,
&self.values[target as usize].as_ref().unwrap(),
self.values[target as usize].as_ref().unwrap(),
)
.0
{
@ -567,6 +609,7 @@ impl Nodes {
hash_map::RawEntryMut::Vacant(_) => unreachable!(),
};
}
}
fn new_node(&mut self, ty: impl Into<ty::Id>, kind: Kind, inps: impl Into<Vec<u32>>) -> Nid {
let id = self.new_node_nop(ty, kind, inps);
@ -619,12 +662,20 @@ impl Nodes {
Kind::Call { .. } => {}
Kind::If => return self.peephole_if(target),
Kind::Region => {}
Kind::Phi => {}
Kind::Phi => return self.peephole_phi(target),
Kind::Loop => {}
}
None
}
fn peephole_phi(&mut self, target: Nid) -> Option<Nid> {
if self[target].inputs[1] == self[target].inputs[2] {
return Some(self[target].inputs[1]);
}
None
}
fn peephole_if(&mut self, target: Nid) -> Option<Nid> {
let cond = self[target].inputs[1];
if let Kind::ConstInt { value } = self[cond].kind {
@ -720,7 +771,7 @@ impl Nodes {
}
if changed {
return Some(self.new_node(self[target].ty, self[target].kind.clone(), [lhs, rhs]));
return Some(self.new_node(self[target].ty, self[target].kind, [lhs, rhs]));
}
None
@ -731,11 +782,13 @@ impl Nodes {
}
fn replace(&mut self, target: Nid, with: Nid) {
let mut back_press = 0;
for i in 0..self[target].outputs.len() {
let out = self[target].outputs[i];
let out = self[target].outputs[i - back_press];
let index = self[out].inputs.iter().position(|&p| p == target).unwrap();
let rpl = self.modify_input(out, index, with);
self[with].outputs.push(rpl);
let prev_len = self[target].outputs.len();
self.modify_input(out, index, with);
back_press += (self[target].outputs.len() != prev_len) as usize;
}
self.remove(target);
@ -750,17 +803,19 @@ impl Nodes {
let (entry, hash) = Self::find_node(
&mut self.lookup,
&self.values,
&self.values[target as usize].as_ref().unwrap(),
self.values[target as usize].as_ref().unwrap(),
);
match entry {
hash_map::RawEntryMut::Occupied(mut other) => {
let rpl = *other.get_key_value().0;
log::dbg!("rplc");
let rpl = other.get_key_value().0.nid;
self[target].inputs[inp_index] = prev;
self.replace(target, rpl);
rpl
}
hash_map::RawEntryMut::Vacant(slot) => {
slot.insert_hashed_nocheck(hash, target, ());
log::dbg!("mod");
slot.insert(LookupEntry { nid: target, hash }, ());
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
self[prev].outputs.swap_remove(index);
self[with].outputs.push(target);
@ -913,8 +968,28 @@ impl Nodes {
failed = true;
}
let mut allowed_cfgs = 1 + (node.kind == Kind::If) as usize;
for &o in &node.outputs {
let mut occurs = 0;
if self.is_cfg(i) {
if allowed_cfgs == 0 && self.is_cfg(o) {
log::err!(
"multiple cfg outputs detected: {:?} -> {:?}",
node.kind,
self[o].kind
);
failed = true;
} else {
allowed_cfgs += self.is_cfg(o) as usize;
}
}
if matches!(node.kind, Kind::Region | Kind::Loop)
&& !self.is_cfg(o)
&& self[o].kind != Kind::Phi
{
log::err!("unexpected output node on region: {:?}", self[o].kind);
failed = true;
}
let other = match &self.values[o as usize] {
Ok(other) => other,
Err(_) => {
@ -923,10 +998,11 @@ impl Nodes {
continue;
}
};
occurs += self[o].inputs.iter().filter(|&&el| el == i).count();
if occurs == 0 {
let occurs = self[o].inputs.iter().filter(|&&el| el == i).count();
let self_occurs = self[i].outputs.iter().filter(|&&el| el == o).count();
if occurs != self_occurs {
log::err!(
"the edge is not bidirectional: {i} {:?} {o} {:?}",
"the edge is not bidirectional: {i} {:?} {self_occurs} {o} {:?} {occurs}",
node.kind,
other.kind
);
@ -961,11 +1037,19 @@ impl Nodes {
return true;
}
}
return false;
false
}
self.visited.clear(self.values.len());
climb_impl(self, from, &mut for_each)
}
fn late_peephole(&mut self, target: Nid) -> Nid {
if let Some(id) = self.peephole(target) {
self.replace(target, id);
return id;
}
target
}
}
impl ops::Index<u32> for Nodes {
@ -1625,16 +1709,23 @@ impl Codegen {
};
if self.ci.vars[index].value == 0 {
self.ci.nodes.unlock(self.ci.vars[index].value);
let loob = self.ci.loops.last_mut().unwrap();
let inps = [loob.node, loob.scope[index].value, loob.scope[index].value];
if self.ci.nodes[loob.scope[index].value].kind != Kind::Phi
|| self.ci.nodes[loob.scope[index].value].inputs[0] != loob.node
{
self.ci.nodes.unlock(self.ci.vars[index].value);
let inps = [loob.node, loob.scope[index].value, 0];
self.ci.nodes.unlock(inps[1]);
let ty = self.ci.nodes[inps[1]].ty;
// TODO: dont apply peepholes here
let phy = self.ci.nodes.new_node(ty, Kind::Phi, inps);
self.ci.nodes[phy].lock_rc += 2;
self.ci.vars[index].value = phy;
loob.scope[index].value = phy;
let phi = self.ci.nodes.new_node_nop(ty, Kind::Phi, inps);
self.ci.nodes[phi].lock_rc += 2;
self.ci.vars[index].value = phi;
loob.scope[index].value = phi;
} else {
self.ci.nodes.unlock_remove(self.ci.vars[index].value);
self.ci.vars[index].value = loob.scope[index].value;
self.ci.nodes.lock(self.ci.vars[index].value);
}
}
self.ci.nodes.check_scope_integrity(&self.ci.vars);
@ -1751,8 +1842,12 @@ impl Codegen {
let ty = self.ci.nodes[else_var.value].ty;
debug_assert_eq!(
ty, self.ci.nodes[then_var.value].ty,
"TODO: typecheck properly"
ty,
self.ci.nodes[then_var.value].ty,
"TODO: typecheck properly: {} != {}\n{}",
self.ty_display(ty),
self.ty_display(self.ci.nodes[then_var.value].ty),
self.errors.borrow()
);
let inps = [self.ci.ctrl, then_var.value, else_var.value];
@ -1826,33 +1921,35 @@ impl Codegen {
self.ci.nodes.check_scope_integrity(&self.ci.vars);
self.ci.nodes.check_scope_integrity(&break_scope);
self.ci.nodes.check_scope_integrity(&scope);
for ((dest_var, scope_var), loop_var) in
for ((dest_var, mut scope_var), loop_var) in
self.ci.vars.iter_mut().zip(scope).zip(break_scope)
{
if loop_var.value == 0 {
self.ci.nodes.unlock(loop_var.value);
debug_assert!(loop_var.value == dest_var.value);
self.ci.nodes.unlock(dest_var.value);
if loop_var.value != 0 {
self.ci.nodes.unlock(scope_var.value);
if loop_var.value != scope_var.value {
scope_var.value =
self.ci.nodes.modify_input(scope_var.value, 2, loop_var.value);
self.ci.nodes.lock(scope_var.value);
} else {
let phi = &self.ci.nodes[scope_var.value];
debug_assert_eq!(phi.kind, Kind::Phi);
debug_assert_eq!(phi.inputs[2], 0);
let prev = phi.inputs[1];
self.ci.nodes.replace(scope_var.value, prev);
scope_var.value = prev;
self.ci.nodes.lock(prev);
}
}
if dest_var.value == 0 {
self.ci.nodes.unlock_remove(dest_var.value);
dest_var.value = scope_var.value;
continue;
self.ci.nodes.lock(dest_var.value);
}
debug_assert_eq!(self.ci.nodes[scope_var.value].kind, Kind::Phi);
if scope_var.value == loop_var.value {
let orig = self.ci.nodes[scope_var.value].inputs[1];
self.ci.nodes.lock(orig);
self.ci.nodes.unlock(loop_var.value);
self.ci.nodes.unlock_remove(scope_var.value);
self.ci.nodes.unlock_remove(dest_var.value);
dest_var.value = orig;
continue;
}
self.ci.nodes.unlock(loop_var.value);
let phy = self.ci.nodes.modify_input(scope_var.value, 2, loop_var.value);
self.ci.nodes.unlock_remove(dest_var.value);
dest_var.value = phy;
}
self.ci.nodes.unlock(self.ci.ctrl);
@ -2198,7 +2295,7 @@ impl Codegen {
fn color_control(&mut self, mut ctrl: Nid) -> Option<Nid> {
for _ in 0..30 {
match self.ci.nodes[ctrl].kind.clone() {
match self.ci.nodes[ctrl].kind {
Kind::Start => unreachable!(),
Kind::End => unreachable!(),
Kind::Return => {
@ -2250,7 +2347,7 @@ impl Codegen {
(None, Some(n)) | (Some(n), None) => n,
(Some(l), Some(r)) if l == r => l,
(Some(left), Some(right)) => {
todo!()
todo!("{:?} {:?}", self.ci.nodes[left], self.ci.nodes[right]);
}
};
@ -2258,14 +2355,12 @@ impl Codegen {
return Some(dest);
}
debug_assert!(left_unreachable.is_none() || right_unreachable.is_none());
debug_assert_eq!(self.ci.nodes[dest].kind, Kind::Region);
for i in 0..self.ci.nodes[dest].outputs.len() {
let o = self.ci.nodes[dest].outputs[i];
if self.ci.nodes[o].kind == Kind::Phi {
self.color_phy(o);
self.color_phi(o);
self.ci.nodes[o].depth = self.ci.loop_depth;
}
}
@ -2284,15 +2379,15 @@ impl Codegen {
}
for i in 0..self.ci.nodes[ctrl].outputs.len() {
let maybe_phy = self.ci.nodes[ctrl].outputs[i];
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phy]
let maybe_phi = self.ci.nodes[ctrl].outputs[i];
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phi]
else {
continue;
};
_ = self.color_expr_consume(inputs[1]);
self.ci.nodes[maybe_phy].depth = self.ci.loop_depth;
self.ci.set_next_color(maybe_phy);
self.ci.nodes[maybe_phi].depth = self.ci.loop_depth;
self.ci.set_next_color(maybe_phi);
}
self.ci.nodes[ctrl].lock_rc = self.ci.code.len() as _;
@ -2307,7 +2402,7 @@ impl Codegen {
);
for i in 0..self.ci.nodes[ctrl].outputs.len() {
self.color_phy(self.ci.nodes[ctrl].outputs[i]);
self.color_phi(self.ci.nodes[ctrl].outputs[i]);
}
self.ci.loop_depth -= 1;
@ -2321,8 +2416,8 @@ impl Codegen {
unreachable!()
}
fn color_phy(&mut self, maybe_phy: Nid) {
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phy] else {
fn color_phi(&mut self, maybe_phi: Nid) {
let Node { kind: Kind::Phi, ref inputs, .. } = self.ci.nodes[maybe_phi] else {
return;
};
let &[region, left, right] = inputs.as_slice() else { unreachable!() };
@ -2330,14 +2425,14 @@ impl Codegen {
let lcolor = self.color_expr_consume(left);
let rcolor = self.color_expr_consume(right);
if self.ci.nodes[maybe_phy].color != 0 {
// loop phy
if self.ci.nodes[maybe_phi].color != 0 {
// loop phi
if let Some(c) = rcolor
&& !self.ci.nodes.climb_expr(right, |i, n| {
matches!(n.kind, Kind::Phi) && n.inputs[0] == region && i != maybe_phy
matches!(n.kind, Kind::Phi) && n.inputs[0] == region && i != maybe_phi
})
{
self.ci.recolor(right, c, self.ci.nodes[maybe_phy].color);
self.ci.recolor(right, c, self.ci.nodes[maybe_phi].color);
}
} else {
let color = match (lcolor, rcolor) {
@ -2348,7 +2443,7 @@ impl Codegen {
lc
}
};
self.ci.set_color(maybe_phy, color);
self.ci.set_color(maybe_phi, color);
}
}
@ -2396,7 +2491,7 @@ impl Codegen {
fn emit_control(&mut self, mut ctrl: Nid) -> Option<Nid> {
for _ in 0..30 {
match self.ci.nodes[ctrl].kind.clone() {
match self.ci.nodes[ctrl].kind {
Kind::Start => unreachable!(),
Kind::End => unreachable!(),
Kind::Return => {
@ -2439,14 +2534,14 @@ impl Codegen {
let mut parama = self.tys.parama(ret);
for i in 1..self.ci.nodes[ctrl].inputs.len() {
let arg = self.ci.nodes[ctrl].inputs[i];
node_loc!(self, arg) = match self.tys.size_of(self.tof(arg)) {
let dst = match self.tys.size_of(self.tof(arg)) {
0 => continue,
1..=8 => Loc { reg: parama.next() },
s => todo!("{s}"),
};
self.ci.regs.mark_leaked(node_loc!(self, arg).reg);
self.emit_expr_consume(arg);
self.ci.nodes[arg].depth = 0;
self.ci.emit(instrs::cp(dst.reg, node_loc!(self, arg).reg));
}
let reloc = Reloc::new(self.ci.code.len(), 3, 4);
@ -2770,8 +2865,7 @@ impl Codegen {
if color.rc == 0 {
if color.depth != self.ci.loop_depth {
self.ci.delayed_frees.push(node.color);
} else {
debug_assert_ne!(color.loc, Loc::default(), "{:?}", node);
} else if color.loc != Loc::default() {
self.ci.regs.free(color.loc.reg);
}
}

View file

@ -1,6 +1,6 @@
main:
ADDI64 r254, r254, -64d
ST r31, r254, 0a, 64h
ADDI64 r254, r254, -80d
ST r31, r254, 0a, 80h
JAL r31, r0, :check_platform
CP r32, r1
LI64 r33, 100d
@ -17,29 +17,31 @@ main:
CP r3, r36
CP r4, r33
JAL r31, r0, :set_pixel
CP r37, r35
ADDI64 r37, r37, 1d
CP r35, r37
CP r37, r1
CP r38, r35
ADDI64 r38, r38, 1d
CP r35, r38
JMP :1
0: CP r2, r35
CP r3, r36
CP r4, r33
JAL r31, r0, :set_pixel
CP r38, r1
LI64 r35, 0d
CP r37, r36
ADDI64 r37, r37, 1d
CP r36, r37
1: CP r37, r36
CP r38, r33
CMPS r37, r37, r38
CMPUI r37, r37, 0d
NOT r37, r37
JEQ r37, r0, :2
CP r39, r36
ADDI64 r39, r39, 1d
CP r36, r39
1: CP r39, r36
CP r40, r33
CMPS r39, r39, r40
CMPUI r39, r39, 0d
NOT r39, r39
JEQ r39, r0, :2
JMP :3
2: JMP :4
3: LI64 r1, 0d
LD r31, r254, 0a, 64h
ADDI64 r254, r254, 64d
LD r31, r254, 0a, 80h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
set_pixel:
ADDI64 r254, r254, -32d
@ -67,6 +69,6 @@ x86_fb_ptr:
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 505
code size: 511
ret: 0
status: Ok(())

View file

@ -1,11 +1,16 @@
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
LRA r32, r0, :complex_global_var
LRA r33, r0, :complex_global_var
LD r34, r33, 0a, 8h
ADDI64 r34, r34, 5d
ST r34, r32, 0a, 8h
LRA r32, r0, :complex_global_var
LD r1, r32, 0a, 8h
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 267
ret: 50
code size: 318
ret: 55
status: Ok(())

View file

@ -27,12 +27,11 @@ fib:
CP r35, r32
ADDI64 r35, r35, -1d
CP r32, r35
LI64 r35, 0d
JMP :2
1: CP r1, r33
LD r31, r254, 0a, 48h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
code size: 258
code size: 248
ret: 55
status: Ok(())

View file

@ -1,6 +1,6 @@
main:
ADDI64 r254, r254, -104d
ST r31, r254, 0a, 104h
ADDI64 r254, r254, -96d
ST r31, r254, 0a, 96h
JAL r31, r0, :check_platform
LI64 r32, 0d
CP r33, r32
@ -12,25 +12,30 @@ main:
CP r39, r37
4: ADDI64 r40, r35, 1d
JGTS r33, r40, :0
CP r2, r33
CP r3, r33
CP r4, r37
JAL r31, r0, :set_pixel
CP r41, r4
ADDI64 r42, r3, 1d
CP r43, r3
CP r41, r37
ADDI64 r33, r33, 1d
CP r42, r33
JMP :1
0: JAL r31, r0, :set_pixel
CP r41, r4
CP r42, r32
ADDI64 r43, r3, 1d
1: JNE r43, r41, :2
0: CP r2, r33
CP r3, r38
CP r4, r39
JAL r31, r0, :set_pixel
CP r41, r39
CP r33, r32
ADDI64 r42, r38, 1d
1: JNE r42, r41, :2
JMP :3
2: CP r2, r42
CP r35, r34
CP r4, r36
CP r3, r43
CP r4, r41
2: CP r35, r34
CP r37, r36
CP r38, r42
CP r39, r41
JMP :4
3: LD r31, r254, 0a, 104h
ADDI64 r254, r254, 104d
3: LD r31, r254, 0a, 96h
ADDI64 r254, r254, 96d
JALA r0, r31, 0a
set_pixel:
ADDI64 r254, r254, -8d
@ -53,6 +58,7 @@ x86_fb_ptr:
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 422
timed out
code size: 437
ret: 0
status: Ok(())

View file

@ -1,14 +1,16 @@
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LI64 r2, 10d
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LI64 r32, 10d
CP r2, r32
JAL r31, r0, :add_one
CP r32, r1
LI64 r2, 20d
LI64 r33, 20d
CP r2, r33
JAL r31, r0, :add_two
ADD64 r1, r1, r32
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
add_two:
ADDI64 r254, r254, -8d
@ -26,6 +28,6 @@ add_one:
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 254
code size: 260
ret: 33
status: Ok(())

View file

@ -1,28 +1,31 @@
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 10d
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LI64 r32, 10d
CP r2, r32
JAL r31, r0, :fib
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
fib:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
LI64 r33, 2d
JGTS r32, r33, :0
LI64 r1, 1d
JMP :1
0: ADDI64 r2, r32, -1d
0: ADDI64 r34, r32, -1d
CP r2, r34
JAL r31, r0, :fib
CP r34, r1
SUB64 r2, r32, r33
SUB64 r35, r32, r33
CP r2, r35
JAL r31, r0, :fib
ADD64 r1, r1, r34
1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
ADD64 r1, r34, r1
1: LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
code size: 212
code size: 221
ret: 55
status: Ok(())

View file

@ -1,10 +1,11 @@
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 10d
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LI64 r32, 10d
CP r2, r32
JAL r31, r0, :fib
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
fib:
ADDI64 r254, r254, -56d
@ -25,6 +26,6 @@ fib:
1: LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
code size: 204
code size: 207
ret: 55
status: Ok(())