changing the gcm to not mutate nodes in recursive functions

This commit is contained in:
Jakub Doka 2024-11-23 19:47:17 +01:00
parent 86ca959ea3
commit 5df4fb8882
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
16 changed files with 324 additions and 243 deletions

View file

@ -25,6 +25,7 @@
pointer_is_aligned_to, pointer_is_aligned_to,
maybe_uninit_fill maybe_uninit_fill
)] )]
#![feature(array_chunks)]
#![warn(clippy::dbg_macro)] #![warn(clippy::dbg_macro)]
#![expect(internal_features)] #![expect(internal_features)]
#![no_std] #![no_std]

View file

@ -124,24 +124,26 @@ impl Default for Nodes {
} }
impl Nodes { impl Nodes {
fn loop_depth(&self, target: Nid) -> LoopDepth { fn loop_depth(&self, target: Nid, scheds: Option<&[Nid]>) -> LoopDepth {
self[target].loop_depth.set(match self[target].kind { self[target].loop_depth.set(match self[target].kind {
Kind::Region | Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::If => { Kind::Region | Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::If => {
if self[target].loop_depth.get() != 0 { if self[target].loop_depth.get() != 0 {
return self[target].loop_depth.get(); return self[target].loop_depth.get();
} }
self.loop_depth(self[target].inputs[0]) self.loop_depth(self[target].inputs[0], scheds)
} }
Kind::Loop => { Kind::Loop => {
if self[target].loop_depth.get() == self.loop_depth(self[target].inputs[0]) + 1 { if self[target].loop_depth.get()
== self.loop_depth(self[target].inputs[0], scheds) + 1
{
return self[target].loop_depth.get(); return self[target].loop_depth.get();
} }
let depth = self.loop_depth(self[target].inputs[0]) + 1; let depth = self.loop_depth(self[target].inputs[0], scheds) + 1;
self[target].loop_depth.set(depth); self[target].loop_depth.set(depth);
let mut cursor = self[target].inputs[1]; let mut cursor = self[target].inputs[1];
while cursor != target { while cursor != target {
self[cursor].loop_depth.set(depth); self[cursor].loop_depth.set(depth);
let next = self.idom(cursor); let next = self.idom(cursor, scheds);
debug_assert_ne!(next, 0); debug_assert_ne!(next, 0);
if matches!(self[cursor].kind, Kind::Then | Kind::Else) { if matches!(self[cursor].kind, Kind::Then | Kind::Else) {
debug_assert_eq!(self[next].kind, Kind::If); debug_assert_eq!(self[next].kind, Kind::If);
@ -159,17 +161,21 @@ impl Nodes {
self[target].loop_depth.get() self[target].loop_depth.get()
} }
fn idepth(&self, target: Nid) -> IDomDepth { fn idepth(&self, target: Nid, scheds: Option<&[Nid]>) -> IDomDepth {
if target == VOID { if target == VOID {
return 0; return 0;
} }
if self[target].depth.get() == 0 { if self[target].depth.get() == 0 {
let depth = match self[target].kind { let depth = match self[target].kind {
Kind::End | Kind::Start => unreachable!("{:?}", self[target].kind), Kind::End | Kind::Start => unreachable!("{:?}", self[target].kind),
Kind::Region => { Kind::Region => self
self.idepth(self[target].inputs[0]).max(self.idepth(self[target].inputs[1])) .idepth(self[target].inputs[0], scheds)
.max(self.idepth(self[target].inputs[1], scheds)),
_ if self[target].kind.is_pinned() => self.idepth(self[target].inputs[0], scheds),
_ if let Some(scheds) = scheds => {
self.idepth(scheds[target as usize], Some(scheds))
} }
_ => self.idepth(self[target].inputs[0]), _ => self.idepth(self[target].inputs[0], scheds),
} + 1; } + 1;
self[target].depth.set(depth); self[target].depth.set(depth);
} }
@ -195,15 +201,14 @@ impl Nodes {
} }
} }
fn push_up_impl(&mut self, node: Nid, visited: &mut BitSet) { fn push_up_impl(&self, node: Nid, visited: &mut BitSet, scheds: &mut [Nid]) {
if !visited.set(node) { if !visited.set(node) {
return; return;
} }
for i in 1..self[node].inputs.len() { for &inp in &self[node].inputs[1..] {
let inp = self[node].inputs[i];
if !self[inp].kind.is_pinned() { if !self[inp].kind.is_pinned() {
self.push_up_impl(inp, visited); self.push_up_impl(inp, visited, scheds);
} }
} }
@ -213,32 +218,17 @@ impl Nodes {
let mut deepest = self[node].inputs[0]; let mut deepest = self[node].inputs[0];
for &inp in self[node].inputs[1..].iter() { for &inp in self[node].inputs[1..].iter() {
if self.idepth(inp) > self.idepth(deepest) { if self.idepth(inp, Some(scheds)) > self.idepth(deepest, Some(scheds)) {
if self[inp].kind.is_call() { if self[inp].kind.is_call() {
deepest = inp; deepest = inp;
} else { } else {
debug_assert!(!self.is_cfg(inp)); debug_assert!(!self.is_cfg(inp));
deepest = self.idom(inp); deepest = self.idom(inp, Some(scheds));
} }
} }
} }
if deepest == self[node].inputs[0] { scheds[node as usize] = deepest;
return;
}
let current = self[node].inputs[0];
let index = self[current].outputs.iter().position(|&p| p == node).unwrap();
self[current].outputs.remove(index);
self[node].inputs[0] = deepest;
debug_assert!(
!self[deepest].outputs.contains(&node) || self[deepest].kind.is_call(),
"{node} {:?} {deepest} {:?}",
self[node],
self[deepest]
);
self[deepest].outputs.push(node);
} }
fn collect_rpo(&self, node: Nid, rpo: &mut Vec<Nid>, visited: &mut BitSet) { fn collect_rpo(&self, node: Nid, rpo: &mut Vec<Nid>, visited: &mut BitSet) {
@ -253,21 +243,21 @@ impl Nodes {
rpo.push(node); rpo.push(node);
} }
fn push_up(&mut self, rpo: &mut Vec<Nid>, visited: &mut BitSet) { fn push_up(&self, rpo: &mut Vec<Nid>, visited: &mut BitSet, scheds: &mut [Nid]) {
debug_assert!(rpo.is_empty()); debug_assert!(rpo.is_empty());
self.collect_rpo(VOID, rpo, visited); self.collect_rpo(VOID, rpo, visited);
for &node in rpo.iter().rev() { for &node in rpo.iter().rev() {
self.loop_depth(node); self.loop_depth(node, Some(scheds));
for i in 0..self[node].inputs.len() { for i in 0..self[node].inputs.len() {
self.push_up_impl(self[node].inputs[i], visited); self.push_up_impl(self[node].inputs[i], visited, scheds);
} }
if matches!(self[node].kind, Kind::Loop | Kind::Region) { if matches!(self[node].kind, Kind::Loop | Kind::Region) {
for i in 0..self[node].outputs.len() { for i in 0..self[node].outputs.len() {
let usage = self[node].outputs[i]; let usage = self[node].outputs[i];
if self[usage].kind == Kind::Phi { if self[usage].kind == Kind::Phi {
self.push_up_impl(usage, visited); self.push_up_impl(usage, visited, scheds);
} }
} }
} }
@ -290,14 +280,14 @@ impl Nodes {
rpo.clear(); rpo.clear();
} }
fn better(&mut self, is: Nid, then: Nid) -> bool { fn better(&self, is: Nid, then: Nid, scheds: Option<&[Nid]>) -> bool {
debug_assert_ne!(self.idepth(is), self.idepth(then), "{is} {then}"); debug_assert_ne!(self.idepth(is, scheds), self.idepth(then, scheds), "{is} {then}");
self.loop_depth(is) < self.loop_depth(then) self.loop_depth(is, scheds) < self.loop_depth(then, scheds)
|| self.idepth(is) > self.idepth(then) || self.idepth(is, scheds) > self.idepth(then, scheds)
|| self[then].kind == Kind::If || self[then].kind == Kind::If
} }
fn is_forward_edge(&mut self, usage: Nid, def: Nid) -> bool { fn is_forward_edge(&self, usage: Nid, def: Nid) -> bool {
match self[usage].kind { match self[usage].kind {
Kind::Phi => { Kind::Phi => {
self[usage].inputs[2] != def || self[self[usage].inputs[0]].kind != Kind::Loop self[usage].inputs[2] != def || self[self[usage].inputs[0]].kind != Kind::Loop
@ -307,20 +297,27 @@ impl Nodes {
} }
} }
fn push_down(&mut self, node: Nid, visited: &mut BitSet, antideps: &mut [Nid]) { fn push_down(
&self,
node: Nid,
visited: &mut BitSet,
antideps: &mut [Nid],
scheds: &mut [Nid],
antidep_bounds: &mut Vec<Nid>,
) {
if !visited.set(node) { if !visited.set(node) {
return; return;
} }
for usage in self[node].outputs.clone() { for usage in self[node].outputs.clone() {
if self.is_forward_edge(usage, node) && self[node].kind == Kind::Stre { if self.is_forward_edge(usage, node) && self[node].kind == Kind::Stre {
self.push_down(usage, visited, antideps); self.push_down(usage, visited, antideps, scheds, antidep_bounds);
} }
} }
for usage in self[node].outputs.clone() { for usage in self[node].outputs.clone() {
if self.is_forward_edge(usage, node) { if self.is_forward_edge(usage, node) {
self.push_down(usage, visited, antideps); self.push_down(usage, visited, antideps, scheds, antidep_bounds);
} }
} }
@ -331,56 +328,60 @@ impl Nodes {
let mut min = None::<Nid>; let mut min = None::<Nid>;
for i in 0..self[node].outputs.len() { for i in 0..self[node].outputs.len() {
let usage = self[node].outputs[i]; let usage = self[node].outputs[i];
let ub = self.use_block(node, usage); let ub = self.use_block(node, usage, Some(scheds));
min = min.map(|m| self.common_dom(ub, m)).or(Some(ub)); min = min.map(|m| self.common_dom(ub, m, Some(scheds))).or(Some(ub));
} }
let mut min = min.unwrap(); let mut min = min.unwrap();
debug_assert!(self.dominates(self[node].inputs[0], min)); debug_assert!(self.dominates(scheds[node as usize], min, Some(scheds)));
let mut cursor = min; let mut cursor = min;
while cursor != self[node].inputs[0] { let mut fuel = self.values.len();
cursor = self.idom(cursor); while cursor != scheds[node as usize] {
if self.better(cursor, min) { debug_assert!(fuel != 0);
fuel -= 1;
cursor = self.idom(cursor, Some(scheds));
if self.better(cursor, min, Some(scheds)) {
min = cursor; min = cursor;
} }
} }
if self[node].kind == Kind::Load { if self[node].kind == Kind::Load {
min = self.find_antideps(node, min, antideps); min = self.find_antideps(node, min, antideps, scheds, antidep_bounds);
}
if self[node].kind == Kind::Stre {
antideps[node as usize] = self[node].inputs[0];
} }
if self[min].kind.ends_basic_block() { if self[min].kind.ends_basic_block() {
min = self.idom(min); min = self.idom(min, Some(scheds));
} }
self.assert_dominance(node, min, true); self.assert_dominance(node, min, true, Some(scheds));
let prev = self[node].inputs[0]; debug_assert!(
debug_assert!(self.idepth(min) >= self.idepth(prev)); self.idepth(min, Some(scheds)) >= self.idepth(scheds[node as usize], Some(scheds))
let index = self[prev].outputs.iter().position(|&p| p == node).unwrap(); );
self[prev].outputs.remove(index); scheds[node as usize] = min;
self[node].inputs[0] = min;
self[min].outputs.push(node);
} }
fn find_antideps(&mut self, load: Nid, mut min: Nid, antideps: &mut [Nid]) -> Nid { fn find_antideps(
&self,
load: Nid,
mut min: Nid,
antideps: &mut [Nid],
scheds: &[Nid],
antidep_bounds: &mut Vec<Nid>,
) -> Nid {
debug_assert!(self[load].kind == Kind::Load); debug_assert!(self[load].kind == Kind::Load);
let (aclass, _) = self.aclass_index(self[load].inputs[1]); let (aclass, _) = self.aclass_index(self[load].inputs[1]);
let mut cursor = min; let mut cursor = min;
while cursor != self[load].inputs[0] { while cursor != scheds[load as usize] {
antideps[cursor as usize] = load; antideps[cursor as usize] = load;
if self[cursor].clobbers.get(aclass as _) { if self[cursor].clobbers.get(aclass as _) {
min = self[cursor].inputs[0]; min = self[cursor].inputs[0];
break; break;
} }
cursor = self.idom(cursor); cursor = self.idom(cursor, Some(scheds));
} }
if self[load].inputs[2] == MEM { if self[load].inputs[2] == MEM {
@ -390,16 +391,19 @@ impl Nodes {
for out in self[self[load].inputs[2]].outputs.clone() { for out in self[self[load].inputs[2]].outputs.clone() {
match self[out].kind { match self[out].kind {
Kind::Stre => { Kind::Stre => {
let mut cursor = self[out].inputs[0]; let mut cursor = scheds[out as usize];
while cursor != antideps[out as usize] { while cursor != scheds[load as usize]
&& self.idepth(cursor, Some(scheds))
> self.idepth(scheds[load as usize], Some(scheds))
{
if antideps[cursor as usize] == load { if antideps[cursor as usize] == load {
min = self.common_dom(min, cursor); min = self.common_dom(min, cursor, Some(scheds));
if min == cursor { if min == cursor {
self.bind(load, out); antidep_bounds.extend([load, out]);
} }
break; break;
} }
cursor = self.idom(cursor); cursor = self.idom(cursor, Some(scheds));
} }
break; break;
} }
@ -409,12 +413,15 @@ impl Nodes {
.position(|&n| n == self[load].inputs[2]) .position(|&n| n == self[load].inputs[2])
.unwrap(); .unwrap();
let mut cursor = self[self[out].inputs[0]].inputs[n]; let mut cursor = self[self[out].inputs[0]].inputs[n];
while cursor != antideps[out as usize] { while cursor != scheds[load as usize]
&& self.idepth(cursor, Some(scheds))
> self.idepth(scheds[load as usize], Some(scheds))
{
if antideps[cursor as usize] == load { if antideps[cursor as usize] == load {
min = self.common_dom(min, cursor); min = self.common_dom(min, cursor, Some(scheds));
break; break;
} }
cursor = self.idom(cursor); cursor = self.idom(cursor, Some(scheds));
} }
} }
_ => {} _ => {}
@ -431,9 +438,9 @@ impl Nodes {
self[to].inputs.push(from); self[to].inputs.push(from);
} }
fn use_block(&self, target: Nid, from: Nid) -> Nid { fn use_block(&self, target: Nid, from: Nid, scheds: Option<&[Nid]>) -> Nid {
if self[from].kind != Kind::Phi { if self[from].kind != Kind::Phi {
return self.idom(from); return self.idom(from, scheds);
} }
let index = self[from].inputs.iter().position(|&n| n == target).unwrap_or_else(|| { let index = self[from].inputs.iter().position(|&n| n == target).unwrap_or_else(|| {
@ -442,26 +449,28 @@ impl Nodes {
self[self[from].inputs[0]].inputs[index - 1] self[self[from].inputs[0]].inputs[index - 1]
} }
fn idom(&self, target: Nid) -> Nid { fn idom(&self, target: Nid, scheds: Option<&[Nid]>) -> Nid {
match self[target].kind { match self[target].kind {
Kind::Start => VOID, Kind::Start => unreachable!(),
Kind::End => unreachable!(), Kind::End => unreachable!(),
Kind::Region => { Kind::Region => {
let &[lcfg, rcfg] = self[target].inputs.as_slice() else { unreachable!() }; let &[lcfg, rcfg] = self[target].inputs.as_slice() else { unreachable!() };
self.common_dom(lcfg, rcfg) self.common_dom(lcfg, rcfg, scheds)
} }
_ if self[target].kind.is_pinned() => self[target].inputs[0],
_ if let Some(scheds) = scheds => scheds[target as usize],
_ => self[target].inputs[0], _ => self[target].inputs[0],
} }
} }
fn common_dom(&self, mut a: Nid, mut b: Nid) -> Nid { fn common_dom(&self, mut a: Nid, mut b: Nid, scheds: Option<&[Nid]>) -> Nid {
while a != b { while a != b {
let [ldepth, rdepth] = [self.idepth(a), self.idepth(b)]; let [ldepth, rdepth] = [self.idepth(a, scheds), self.idepth(b, scheds)];
if ldepth >= rdepth { if ldepth >= rdepth {
a = self.idom(a); a = self.idom(a, scheds);
} }
if ldepth <= rdepth { if ldepth <= rdepth {
b = self.idom(b); b = self.idom(b, scheds);
} }
} }
a a
@ -581,16 +590,40 @@ impl Nodes {
} }
} }
fn gcm(&mut self, rpo: &mut Vec<Nid>, visited: &mut BitSet) { fn gcm(&mut self, scratch: &mut Vec<Nid>, bind_buf: &mut Vec<Nid>, visited: &mut BitSet) {
visited.clear(self.values.len()); visited.clear(self.values.len());
self.fix_loops(rpo, visited); self.fix_loops(bind_buf, visited);
debug_assert!(bind_buf.is_empty());
debug_assert!(scratch.is_empty());
scratch.resize(self.values.len() * 2, Nid::MAX);
let (antideps, scheds) = scratch.split_at_mut(self.values.len());
visited.clear(self.values.len()); visited.clear(self.values.len());
self.push_up(rpo, visited); self.push_up(bind_buf, visited, scheds);
visited.clear(self.values.len()); visited.clear(self.values.len());
debug_assert!(rpo.is_empty()); self.push_down(VOID, visited, antideps, scheds, bind_buf);
rpo.resize(self.values.len(), VOID);
self.push_down(VOID, visited, rpo); for &[from, to] in bind_buf.array_chunks() {
rpo.clear(); self.bind(from, to);
}
bind_buf.clear();
self[VOID].outputs =
self[VOID].outputs.iter().filter(|&&n| self[n].kind.is_at_start()).copied().collect();
for (&shed, n) in scheds.iter().zip(0u16..) {
if shed == Nid::MAX {
continue;
}
let prev = mem::replace(&mut self[n].inputs[0], shed);
if prev != VOID {
let index = self[prev].outputs.iter().position(|&o| o == n).unwrap();
self[prev].outputs.swap_remove(index);
}
self[shed].outputs.push(n);
}
scratch.clear();
} }
fn clear(&mut self) { fn clear(&mut self) {
@ -1429,9 +1462,9 @@ impl Nodes {
} }
return Some(self[target].inputs[2]); return Some(self[target].inputs[2]);
} }
_ if self.is_cfg(target) && self.idom(target) == NEVER => panic!(), K::Start => {}
K::Start _ if self.is_cfg(target) && self.idom(target, None) == NEVER => panic!(),
| K::Entry K::Entry
| K::Mem | K::Mem
| K::Loops | K::Loops
| K::End | K::End
@ -1468,7 +1501,7 @@ impl Nodes {
} }
} }
cursor = self.idom(cursor); cursor = self.idom(cursor, None);
} }
CondOptRes::Unknown CondOptRes::Unknown
@ -1563,7 +1596,7 @@ impl Nodes {
} }
#[expect(clippy::format_in_format_args)] #[expect(clippy::format_in_format_args)]
fn basic_blocks_instr(&mut self, out: &mut String, node: Nid) -> core::fmt::Result { fn basic_blocks_instr(&self, out: &mut String, node: Nid) -> core::fmt::Result {
match self[node].kind { match self[node].kind {
Kind::Assert { .. } | Kind::Start => unreachable!("{} {out}", self[node].kind), Kind::Assert { .. } | Kind::Start => unreachable!("{} {out}", self[node].kind),
Kind::End => return Ok(()), Kind::End => return Ok(()),
@ -1599,7 +1632,8 @@ impl Nodes {
if self[node].kind != Kind::Loop && self[node].kind != Kind::Region { if self[node].kind != Kind::Loop && self[node].kind != Kind::Region {
writeln!( writeln!(
out, out,
" {:<14} {}", " {:<3} {:<14} {}",
node,
format!("{:?}", self[node].inputs), format!("{:?}", self[node].inputs),
format!("{:?}", self[node].outputs) format!("{:?}", self[node].outputs)
)?; )?;
@ -1609,7 +1643,7 @@ impl Nodes {
} }
fn basic_blocks_low( fn basic_blocks_low(
&mut self, &self,
out: &mut String, out: &mut String,
mut node: Nid, mut node: Nid,
visited: &mut BitSet, visited: &mut BitSet,
@ -1709,7 +1743,7 @@ impl Nodes {
Ok(()) Ok(())
} }
fn basic_blocks(&mut self) { fn basic_blocks(&self) {
let mut out = String::new(); let mut out = String::new();
let mut visited = BitSet::default(); let mut visited = BitSet::default();
self.basic_blocks_low(&mut out, VOID, &mut visited).unwrap(); self.basic_blocks_low(&mut out, VOID, &mut visited).unwrap();
@ -1763,12 +1797,12 @@ impl Nodes {
let mut stack = vec![self[loob].inputs[1]]; let mut stack = vec![self[loob].inputs[1]];
let mut seen = BitSet::default(); let mut seen = BitSet::default();
seen.set(loob); seen.set(loob);
let depth = self.loop_depth(loob); let depth = self.loop_depth(loob, None);
while let Some(nid) = stack.pop() { while let Some(nid) = stack.pop() {
if seen.set(nid) { if seen.set(nid) {
if depth > self.loop_depth(nid) { if depth > self.loop_depth(nid, None) {
failed = true; failed = true;
log::error!("{depth} {} {nid} {:?}", self.loop_depth(nid), self[nid]); log::error!("{depth} {} {nid} {:?}", self.loop_depth(nid, None), self[nid]);
} }
match self[nid].kind { match self[nid].kind {
@ -1830,25 +1864,25 @@ impl Nodes {
aclass.last_store.set(lvar.last_store.get(), self); aclass.last_store.set(lvar.last_store.get(), self);
} }
fn assert_dominance(&mut self, nd: Nid, min: Nid, check_outputs: bool) { fn assert_dominance(&self, nd: Nid, min: Nid, check_outputs: bool, scheds: Option<&[Nid]>) {
if !cfg!(debug_assertions) { if !cfg!(debug_assertions) {
return; return;
} }
let node = self[nd].clone(); let node = self[nd].clone();
for &i in node.inputs.iter() { for &i in &node.inputs[1..] {
let dom = self.idom(i); let dom = self.idom(i, scheds);
debug_assert!( debug_assert!(
self.dominates(dom, min), self.dominates(dom, min, scheds),
"{dom} {min} {node:?} {:?}", "{dom} {min} {node:?} {:?}",
self.basic_blocks() self.basic_blocks()
); );
} }
if check_outputs { if check_outputs {
for &o in node.outputs.iter() { for &o in node.outputs.iter() {
let dom = self.use_block(nd, o); let dom = self.use_block(nd, o, scheds);
debug_assert!( debug_assert!(
self.dominates(min, dom), self.dominates(min, dom, scheds),
"{min} {dom} {node:?} {:?}", "{min} {dom} {node:?} {:?}",
self.basic_blocks() self.basic_blocks()
); );
@ -1856,17 +1890,19 @@ impl Nodes {
} }
} }
fn dominates(&self, dominator: Nid, mut dominated: Nid) -> bool { fn dominates(&self, dominator: Nid, mut dominated: Nid, scheds: Option<&[Nid]>) -> bool {
loop { loop {
if dominator == dominated { if dominator == dominated {
break true; break true;
} }
if self.idepth(dominator) > self.idepth(dominated) { debug_assert!(dominated != VOID);
if self.idepth(dominator, scheds) > self.idepth(dominated, scheds) {
break false; break false;
} }
dominated = self.idom(dominated); dominated = self.idom(dominated, scheds);
} }
} }
@ -2018,8 +2054,11 @@ impl Kind {
} }
fn is_pinned(&self) -> bool { fn is_pinned(&self) -> bool {
self.is_cfg() self.is_cfg() || self.is_at_start() || matches!(self, Self::Phi | Kind::Assert { .. })
|| matches!(self, Self::Phi | Self::Arg | Self::Mem | Self::Loops | Kind::Assert { .. }) }
fn is_at_start(&self) -> bool {
matches!(self, Self::Arg | Self::Mem | Self::Loops | Self::Entry)
} }
fn is_cfg(&self) -> bool { fn is_cfg(&self) -> bool {
@ -2384,7 +2423,8 @@ impl Ctx {
pub struct Pool { pub struct Pool {
cis: Vec<ItemCtx>, cis: Vec<ItemCtx>,
used_cis: usize, used_cis: usize,
nid_stack: Vec<Nid>, scratch1: Vec<Nid>,
scratch2: Vec<Nid>,
nid_set: BitSet, nid_set: BitSet,
} }
@ -2652,8 +2692,8 @@ impl<'a> Codegen<'a> {
if self.ci.nodes[value].kind == Kind::Load { if self.ci.nodes[value].kind == Kind::Load {
let (lindex, ..) = self.ci.nodes.aclass_index(self.ci.nodes[value].inputs[1]); let (lindex, ..) = self.ci.nodes.aclass_index(self.ci.nodes[value].inputs[1]);
let clobber = self.ci.scope.aclasses[lindex].clobber.get(); let clobber = self.ci.scope.aclasses[lindex].clobber.get();
if self.ci.nodes.idepth(clobber) if self.ci.nodes.idepth(clobber, None)
> self.ci.nodes.idepth(self.ci.scope.aclasses[index].clobber.get()) > self.ci.nodes.idepth(self.ci.scope.aclasses[index].clobber.get(), None)
{ {
self.ci.scope.aclasses[index].clobber.set(clobber, &mut self.ci.nodes); self.ci.scope.aclasses[index].clobber.set(clobber, &mut self.ci.nodes);
} }
@ -4732,7 +4772,7 @@ impl<'a> Codegen<'a> {
fn finalize(&mut self, prev_err_len: usize) -> bool { fn finalize(&mut self, prev_err_len: usize) -> bool {
use {AssertKind as AK, CondOptRes as CR}; use {AssertKind as AK, CondOptRes as CR};
self.ci.finalize(&mut self.pool.nid_stack, self.tys, self.files); self.ci.finalize(&mut self.pool.scratch1, self.tys, self.files);
//let mut to_remove = vec![]; //let mut to_remove = vec![];
for (id, node) in self.ci.nodes.iter() { for (id, node) in self.ci.nodes.iter() {
@ -4787,7 +4827,11 @@ impl<'a> Codegen<'a> {
if self.errors.borrow().len() == prev_err_len { if self.errors.borrow().len() == prev_err_len {
self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID)); 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.graphviz(self.ty_display(ty::Id::VOID));
self.ci.nodes.gcm(&mut self.pool.nid_stack, &mut self.pool.nid_set); self.ci.nodes.gcm(
&mut self.pool.scratch1,
&mut self.pool.scratch2,
&mut self.pool.nid_set,
);
self.ci.nodes.check_loop_depth_integrity(self.ty_display(ty::Id::VOID)); self.ci.nodes.check_loop_depth_integrity(self.ty_display(ty::Id::VOID));
self.ci.nodes.basic_blocks(); self.ci.nodes.basic_blocks();
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID)); self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));

View file

@ -362,6 +362,9 @@ impl Nodes {
let mut seen = BitSet::default(); let mut seen = BitSet::default();
seen.clear(self.values.len()); seen.clear(self.values.len());
let cfg_idx = outputs.iter().position(|&n| self.is_cfg(n)).unwrap();
outputs.swap(cfg_idx, 0);
for &o in outputs.iter() { for &o in outputs.iter() {
if (!self.is_cfg(o) if (!self.is_cfg(o)
&& self[o].outputs.iter().any(|&oi| { && self[o].outputs.iter().any(|&oi| {
@ -407,6 +410,28 @@ impl Nodes {
self[from] self[from]
); );
let bf = &buf;
debug_assert_eq!(
bf.iter()
.enumerate()
.filter(|(_, &b)| !self[b].kind.is_pinned())
.flat_map(|(i, &b)| self[b]
.inputs
.iter()
.filter(|&&b| !self[b].kind.is_pinned())
.filter_map(move |&inp| bf
.iter()
.position(|&n| inp == n)
.filter(|&j| i > j)
.map(|j| (bf[i], bf[j]))))
.collect::<Vec<_>>(),
vec![],
"{:?}",
bf
);
debug_assert!(self.is_cfg(bf[0]) || self[bf[0]].kind == Kind::Phi, "{:?}", self[bf[0]]);
if outputs.len() != buf.len() { if outputs.len() != buf.len() {
panic!("{:?} {:?}", outputs, buf); panic!("{:?} {:?}", outputs, buf);
} }

View file

@ -22,6 +22,7 @@ impl HbvmBackend {
files: &[parser::Ast], files: &[parser::Ast],
) -> (usize, bool) { ) -> (usize, bool) {
let tail = Function::build(nodes, tys, &mut self.ralloc, sig); let tail = Function::build(nodes, tys, &mut self.ralloc, sig);
nodes.basic_blocks();
let strip_load = |value| match nodes[value].kind { let strip_load = |value| match nodes[value].kind {
Kind::Load { .. } if nodes[value].ty.loc(tys) == Loc::Stack => nodes[value].inputs[1], Kind::Load { .. } if nodes[value].ty.loc(tys) == Loc::Stack => nodes[value].inputs[1],
@ -366,6 +367,8 @@ impl<'a> Function<'a> {
func.visited.clear(nodes.values.len()); func.visited.clear(nodes.values.len());
let mut s = Self { tail: true, nodes, tys, sig, func }; let mut s = Self { tail: true, nodes, tys, sig, func };
s.emit_node(VOID); s.emit_node(VOID);
debug_assert!(s.func.blocks.array_chunks().all(|[a, b]| a.end == b.start));
log::info!("{s:?}");
s.tail s.tail
} }
@ -513,9 +516,9 @@ impl Nodes {
} }
fn use_block_of(&self, inst: Nid, uinst: Nid) -> Nid { fn use_block_of(&self, inst: Nid, uinst: Nid) -> Nid {
let mut block = self.use_block(inst, uinst); let mut block = self.use_block(inst, uinst, None);
while !self[block].kind.starts_basic_block() { while !self[block].kind.starts_basic_block() {
block = self.idom(block); block = self.idom(block, None);
} }
block block
} }
@ -538,7 +541,7 @@ impl Nodes {
fn idom_of(&self, mut nid: Nid) -> Nid { fn idom_of(&self, mut nid: Nid) -> Nid {
while !self[nid].kind.starts_basic_block() { while !self[nid].kind.starts_basic_block() {
nid = self.idom(nid); nid = self.idom(nid, None);
} }
nid nid
} }
@ -643,12 +646,18 @@ impl<'a> Regalloc<'a> {
let mut range = b.range(); let mut range = b.range();
debug_assert!(range.start < range.end); debug_assert!(range.start < range.end);
range.start = range.start.max(s.instr_of(inst).map_or(0, |n| n + 1) as usize); range.start = range.start.max(s.instr_of(inst).map_or(0, |n| n + 1) as usize);
debug_assert!(range.start < range.end, "{:?}", range); debug_assert!(
range.start < range.end,
"{:?} {:?} {n} {inst}",
range,
self.nodes[inst]
);
let new = range.end.min( let new = range.end.min(
s.instr_of(uinst) s.instr_of(uinst)
.filter(|_| { .filter(|_| {
n == cursor n == cursor
&& self.nodes.loop_depth(dom) == self.nodes.loop_depth(cursor) && self.nodes.loop_depth(dom, None)
== self.nodes.loop_depth(cursor, None)
}) })
.map_or(Nid::MAX, |n| n + 1) as usize, .map_or(Nid::MAX, |n| n + 1) as usize,
); );
@ -700,10 +709,14 @@ impl<'a> Regalloc<'a> {
debug_assert!(self.res.dfs_buf.is_empty()); debug_assert!(self.res.dfs_buf.is_empty());
self.res.dfs_buf.push(from); self.res.dfs_buf.push(from);
debug_assert!(self.nodes.dominates(until, from)); debug_assert!(self.nodes.dominates(until, from, None));
while let Some(nid) = self.res.dfs_buf.pop() { while let Some(nid) = self.res.dfs_buf.pop() {
debug_assert!(self.nodes.dominates(until, nid), "{until} {:?}", self.nodes[until]); debug_assert!(
self.nodes.dominates(until, nid, None),
"{until} {:?}",
self.nodes[until]
);
each(self, nid, self.res.blocks[self.block_of(nid) as usize]); each(self, nid, self.res.blocks[self.block_of(nid) as usize]);
if nid == until { if nid == until {
continue; continue;

View file

@ -1,6 +1,6 @@
main: main:
ADDI64 r254, r254, -144d ADDI64 r254, r254, -136d
ST r31, r254, 80a, 64h ST r31, r254, 80a, 56h
LRA r32, r0, :glob_stru LRA r32, r0, :glob_stru
JAL r31, r0, :new_stru JAL r31, r0, :new_stru
ST r1, r32, 0a, 16h ST r1, r32, 0a, 16h
@ -16,58 +16,57 @@ main:
LI64 r32, 200d LI64 r32, 200d
CP r1, r32 CP r1, r32
JMP :1 JMP :1
2: LI64 r35, 3d 2: LI64 r34, 1d
LI64 r36, 1d ST r34, r32, 0a, 8h
ST r36, r32, 0a, 8h ST r34, r32, 8a, 8h
ST r36, r32, 8a, 8h ADDI64 r35, r254, 32d
ADDI64 r37, r254, 32d ST r34, r254, 32a, 8h
ST r36, r254, 32a, 8h ST r34, r254, 40a, 8h
ST r36, r254, 40a, 8h ST r34, r254, 48a, 8h
ST r36, r254, 48a, 8h ST r34, r254, 56a, 8h
ST r36, r254, 56a, 8h ST r34, r254, 64a, 8h
ST r36, r254, 64a, 8h ST r34, r254, 72a, 8h
ST r36, r254, 72a, 8h LI64 r36, 3d
CP r32, r33 CP r32, r33
8: JNE r32, r35, :3 8: JNE r32, r36, :3
LD r32, r254, 64a, 8h LD r32, r254, 64a, 8h
JEQ r32, r33, :4 JEQ r32, r33, :4
LI64 r32, 100d LI64 r32, 100d
CP r1, r32 CP r1, r32
JMP :1 JMP :1
4: ST r33, r254, 0a, 8h 4: ST r34, r254, 32a, 8h
ST r34, r254, 40a, 8h
ST r34, r254, 48a, 8h
ST r34, r254, 56a, 8h
ST r34, r254, 64a, 8h
ST r34, r254, 72a, 8h
ST r33, r254, 0a, 8h
ST r33, r254, 8a, 8h ST r33, r254, 8a, 8h
ST r33, r254, 16a, 8h ST r33, r254, 16a, 8h
ST r33, r254, 24a, 8h ST r33, r254, 24a, 8h
ST r36, r254, 32a, 8h
ST r36, r254, 40a, 8h
ST r36, r254, 48a, 8h
ST r36, r254, 56a, 8h
ST r36, r254, 64a, 8h
ST r36, r254, 72a, 8h
CP r32, r33 CP r32, r33
7: LD r38, r254, 64a, 8h 7: LD r37, r254, 64a, 8h
JNE r32, r35, :5 JNE r32, r36, :5
JEQ r38, r33, :6 JEQ r37, r33, :6
LI64 r32, 10d LI64 r32, 10d
CP r1, r32 CP r1, r32
JMP :1 JMP :1
6: CP r1, r33 6: CP r1, r33
JMP :1 JMP :1
5: ADD64 r34, r32, r36 5: MULI64 r37, r32, 16d
MULI64 r32, r32, 16d ADD64 r37, r35, r37
ADD64 r32, r37, r32 ST r33, r37, 0a, 8h
ST r33, r32, 0a, 8h ST r33, r37, 8a, 8h
ST r33, r32, 8a, 8h ADD64 r32, r32, r34
CP r32, r34
JMP :7 JMP :7
3: MULI64 r34, r32, 16d 3: MULI64 r37, r32, 16d
ADD64 r34, r37, r34 ADD64 r37, r35, r37
JAL r31, r0, :new_stru JAL r31, r0, :new_stru
ST r1, r34, 0a, 16h ST r1, r37, 0a, 16h
ADD64 r32, r32, r36 ADD64 r32, r32, r34
JMP :8 JMP :8
1: LD r31, r254, 80a, 64h 1: LD r31, r254, 80a, 56h
ADDI64 r254, r254, 144d ADDI64 r254, r254, 136d
JALA r0, r31, 0a JALA r0, r31, 0a
new_stru: new_stru:
ADDI64 r254, r254, -16d ADDI64 r254, r254, -16d
@ -77,6 +76,6 @@ new_stru:
LD r1, r13, 0a, 16h LD r1, r13, 0a, 16h
ADDI64 r254, r254, 16d ADDI64 r254, r254, 16d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 739 code size: 736
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -10,9 +10,9 @@ opaque:
process: process:
ADDI64 r254, r254, -48d ADDI64 r254, r254, -48d
ST r31, r254, 16a, 32h ST r31, r254, 16a, 32h
LI64 r32, 1000d
ADDI64 r33, r254, 0d ADDI64 r33, r254, 0d
ST r0, r254, 0a, 1h ST r0, r254, 0a, 1h
LI64 r32, 1000d
4: JGTU r32, r0, :0 4: JGTU r32, r0, :0
JMP :1 JMP :1
0: CP r2, r33 0: CP r2, r33

View file

@ -69,8 +69,8 @@ new:
ADDI64 r254, r254, 24d ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a
push: push:
ADDI64 r254, r254, -104d ADDI64 r254, r254, -88d
ST r31, r254, 0a, 104h ST r31, r254, 0a, 88h
CP r38, r2 CP r38, r2
CP r39, r3 CP r39, r3
LI64 r37, 1d LI64 r37, 1d
@ -95,12 +95,12 @@ push:
LD r32, r38, 0a, 8h LD r32, r38, 0a, 8h
ADD64 r41, r32, r33 ADD64 r41, r32, r33
CP r34, r35 CP r34, r35
7: LD r42, r38, 0a, 8h 7: LD r33, r38, 0a, 8h
LD r43, r38, 8a, 8h LD r36, r38, 8a, 8h
JNE r41, r32, :5 JNE r41, r32, :5
JEQ r43, r0, :6 JEQ r36, r0, :6
MUL64 r32, r43, r40 MUL64 r32, r36, r40
CP r2, r42 CP r2, r33
CP r3, r32 CP r3, r32
CP r4, r40 CP r4, r40
JAL r31, r0, :free JAL r31, r0, :free
@ -122,8 +122,8 @@ push:
ADD64 r32, r32, r37 ADD64 r32, r32, r37
ST r32, r38, 8a, 8h ST r32, r38, 8a, 8h
CP r1, r33 CP r1, r33
4: LD r31, r254, 0a, 104h 4: LD r31, r254, 0a, 88h
ADDI64 r254, r254, 104d ADDI64 r254, r254, 88d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 923 code size: 923
ret: 69 ret: 69

View file

@ -1,17 +1,17 @@
main: main:
ADDI64 r254, r254, -128d ADDI64 r254, r254, -128d
LI8 r15, 69b ADDI64 r15, r254, 0d
LI64 r16, 128d LI8 r16, 69b
LI64 r17, 128d
CP r13, r0 CP r13, r0
ADDI64 r17, r254, 0d 2: LD r14, r254, 42a, 1h
2: LD r18, r254, 42a, 1h JLTU r13, r17, :0
JLTU r13, r16, :0 ANDI r13, r14, 255d
ANDI r13, r18, 255d
CP r1, r13 CP r1, r13
JMP :1 JMP :1
0: ADDI64 r14, r13, 1d 0: ADDI64 r14, r13, 1d
ADD64 r13, r17, r13 ADD64 r13, r15, r13
ST r15, r13, 0a, 1h ST r16, r13, 0a, 1h
CP r13, r14 CP r13, r14
JMP :2 JMP :2
1: ADDI64 r254, r254, 128d 1: ADDI64 r254, r254, 128d

View file

@ -37,26 +37,26 @@ put_filled_rect:
ST r7, r254, 75a, 1h ST r7, r254, 75a, 1h
ADDI64 r7, r254, 75d ADDI64 r7, r254, 75d
CP r16, r7 CP r16, r7
LI64 r17, 25d ADDI64 r17, r254, 25d
LI64 r18, 2d LI8 r18, 5b
LI64 r19, 8d ST r18, r254, 25a, 1h
ADDI64 r20, r254, 25d LD r19, r13, 0a, 8h
ADDI64 r21, r254, 50d ST r19, r254, 26a, 4h
LI8 r22, 5b LI64 r20, 1d
ST r22, r254, 25a, 1h ST r20, r254, 30a, 4h
LD r23, r13, 0a, 8h
ST r23, r254, 26a, 4h
LI64 r24, 1d
ST r24, r254, 30a, 4h
ST r16, r254, 34a, 8h ST r16, r254, 34a, 8h
ST r22, r254, 50a, 1h LI64 r21, 25d
ST r23, r254, 51a, 4h ADDI64 r22, r254, 50d
ST r24, r254, 55a, 4h ST r18, r254, 50a, 1h
ST r19, r254, 51a, 4h
ST r20, r254, 55a, 4h
ST r16, r254, 59a, 8h ST r16, r254, 59a, 8h
LI64 r23, 2d
LI64 r24, 8d
LD r25, r15, 8a, 8h LD r25, r15, 8a, 8h
LD r13, r13, 8a, 8h LD r13, r13, 8a, 8h
ADD64 r26, r13, r25 ADD64 r26, r13, r25
SUB64 r26, r26, r24 SUB64 r26, r26, r20
LD r27, r14, 8a, 8h LD r27, r14, 8a, 8h
MUL64 r26, r27, r26 MUL64 r26, r27, r26
LD r14, r14, 0a, 8h LD r14, r14, 0a, 8h
@ -66,36 +66,36 @@ put_filled_rect:
MUL64 r25, r27, r25 MUL64 r25, r27, r25
ADD64 r14, r14, r25 ADD64 r14, r14, r25
ADD64 r14, r28, r14 ADD64 r14, r28, r14
3: JGTU r13, r24, :0 3: JGTU r13, r20, :0
JNE r13, r24, :1 JNE r13, r20, :1
ADDI64 r13, r254, 0d ADDI64 r13, r254, 0d
ST r22, r254, 0a, 1h ST r18, r254, 0a, 1h
ST r23, r254, 1a, 4h ST r19, r254, 1a, 4h
ST r24, r254, 5a, 4h ST r20, r254, 5a, 4h
ST r16, r254, 9a, 8h ST r16, r254, 9a, 8h
ST r14, r254, 17a, 8h ST r14, r254, 17a, 8h
CP r2, r19 CP r2, r24
CP r3, r18 CP r3, r23
CP r4, r13 CP r4, r13
CP r5, r17 CP r5, r21
ECA ECA
JMP :1 JMP :1
1: JMP :2 1: JMP :2
0: ST r14, r254, 67a, 8h 0: ST r14, r254, 67a, 8h
CP r2, r19 CP r2, r24
CP r3, r18 CP r3, r23
CP r4, r21 CP r4, r22
CP r5, r17 CP r5, r21
ECA ECA
ST r15, r254, 42a, 8h ST r15, r254, 42a, 8h
CP r2, r19 CP r2, r24
CP r3, r18 CP r3, r23
CP r4, r20 CP r4, r17
CP r5, r17 CP r5, r21
ECA ECA
SUB64 r13, r13, r23
SUB64 r15, r15, r27 SUB64 r15, r15, r27
ADD64 r14, r27, r14 ADD64 r14, r27, r14
SUB64 r13, r13, r18
JMP :3 JMP :3
2: ADDI64 r254, r254, 108d 2: ADDI64 r254, r254, 108d
JALA r0, r31, 0a JALA r0, r31, 0a

View file

@ -7,8 +7,8 @@ fib:
2: JNE r13, r15, :0 2: JNE r13, r15, :0
CP r1, r14 CP r1, r14
JMP :1 JMP :1
0: ADD64 r14, r16, r14 0: SUB64 r13, r13, r17
SUB64 r13, r13, r17 ADD64 r14, r16, r14
SWA r14, r16 SWA r14, r16
JMP :2 JMP :2
1: JALA r0, r31, 0a 1: JALA r0, r31, 0a

View file

@ -23,8 +23,8 @@ sqrt:
ADD64 r18, r18, r15 ADD64 r18, r18, r15
SLU64 r18, r18, r16 SLU64 r18, r18, r16
JLTU r13, r18, :2 JLTU r13, r18, :2
ADD64 r14, r15, r14
SUB64 r13, r13, r18 SUB64 r13, r13, r18
ADD64 r14, r15, r14
JMP :2 JMP :2
2: SRUI64 r15, r15, 1b 2: SRUI64 r15, r15, 1b
JMP :3 JMP :3

View file

@ -1,46 +1,45 @@
main: main:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
LI64 r17, 1d LI64 r17, 1d
LI64 r16, 4d LI64 r15, 4d
CP r14, r0 CP r14, r0
ADDI64 r18, r254, 0d ADDI64 r18, r254, 0d
CP r13, r14 CP r13, r14
6: JNE r13, r16, :0 6: JNE r13, r15, :0
LI64 r19, 2d ADDI64 r19, r254, 32d
ADDI64 r20, r254, 32d LI64 r20, 2d
CP r13, r14 CP r13, r14
4: LD r15, r254, 16a, 8h 4: LD r15, r254, 16a, 8h
JNE r13, r17, :1 JNE r13, r17, :1
CP r1, r15 CP r1, r15
JMP :2 JMP :2
1: MUL64 r21, r13, r19 1: ADD64 r16, r13, r17
ADD64 r16, r13, r17 SUB64 r15, r20, r16
SUB64 r13, r19, r16 MUL64 r21, r15, r20
MUL64 r22, r13, r19 MUL64 r22, r13, r20
CP r13, r14 CP r13, r14
5: JNE r13, r19, :3 5: JNE r13, r20, :3
CP r13, r16 CP r13, r16
JMP :4 JMP :4
3: ADD64 r15, r13, r17 3: ADD64 r15, r13, r17
ADD64 r23, r21, r13 ADD64 r23, r22, r13
ADD64 r13, r22, r13 ADD64 r13, r21, r13
MULI64 r23, r23, 8d MULI64 r23, r23, 8d
MULI64 r13, r13, 8d MULI64 r13, r13, 8d
ADD64 r23, r18, r23 ADD64 r23, r18, r23
ADD64 r13, r18, r13 ADD64 r13, r18, r13
BMC r23, r20, 8h BMC r23, r19, 8h
BMC r13, r23, 8h BMC r13, r23, 8h
BMC r20, r13, 8h BMC r19, r13, 8h
CP r13, r15 CP r13, r15
JMP :5 JMP :5
0: ADD64 r15, r13, r17 0: MULI64 r16, r13, 8d
MULI64 r19, r13, 8d ADD64 r16, r18, r16
ADD64 r19, r18, r19 ST r13, r16, 0a, 8h
ST r13, r19, 0a, 8h ADD64 r13, r13, r17
CP r13, r15
JMP :6 JMP :6
2: ADDI64 r254, r254, 40d 2: ADDI64 r254, r254, 40d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 270 code size: 267
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -28,8 +28,8 @@ fib_iter:
2: JNE r13, r15, :0 2: JNE r13, r15, :0
CP r1, r14 CP r1, r14
JMP :1 JMP :1
0: ADD64 r14, r16, r14 0: SUB64 r13, r13, r17
SUB64 r13, r13, r17 ADD64 r14, r16, r14
SWA r14, r16 SWA r14, r16
JMP :2 JMP :2
1: JALA r0, r31, 0a 1: JALA r0, r31, 0a

View file

@ -8,9 +8,9 @@ main:
4: JLTU r13, r17, :0 4: JLTU r13, r17, :0
LI64 r16, 10d LI64 r16, 10d
CP r13, r14 CP r13, r14
3: LD r17, r254, 2048a, 1h 3: LD r15, r254, 2048a, 1h
JLTU r13, r16, :1 JLTU r13, r16, :1
ANDI r13, r17, 255d ANDI r13, r15, 255d
CP r1, r13 CP r1, r13
JMP :2 JMP :2
1: ADD64 r15, r13, r14 1: ADD64 r15, r13, r14

View file

@ -1,24 +1,24 @@
main: main:
LI64 r16, 4621819117588971520d LI64 r16, 1d
LI64 r17, 1d LI64 r17, 4621819117588971520d
LI64 r18, 3d LI64 r18, 3d
CP r14, r0 CP r14, r0
CP r15, r14 CP r15, r14
3: JNE r15, r18, :0 3: JNE r15, r18, :0
CP r1, r17 CP r1, r16
JMP :1 JMP :1
0: ITF64 r19, r15 0: ITF64 r19, r15
CP r13, r14 CP r13, r14
5: JNE r13, r18, :2 5: JNE r13, r18, :2
ADD64 r15, r15, r17 ADD64 r15, r15, r16
JMP :3 JMP :3
2: ITF64 r20, r13 2: ITF64 r20, r13
FMUL64 r20, r20, r19 FMUL64 r20, r20, r19
FCMPLT64 r20, r20, r16 FCMPLT64 r20, r20, r17
NOT r20, r20 NOT r20, r20
ANDI r20, r20, 255d ANDI r20, r20, 255d
JNE r20, r0, :4 JNE r20, r0, :4
ADD64 r13, r13, r17 ADD64 r13, r13, r16
JMP :5 JMP :5
4: CP r1, r14 4: CP r1, r14
1: JALA r0, r31, 0a 1: JALA r0, r31, 0a

View file

@ -1,8 +1,8 @@
main: main:
ADDI64 r254, r254, -1d ADDI64 r254, r254, -1d
ST r0, r254, 0a, 1h
LI64 r14, 255d LI64 r14, 255d
LI8 r13, 1b LI8 r13, 1b
ST r0, r254, 0a, 1h
2: LD r15, r254, 0a, 1h 2: LD r15, r254, 0a, 1h
ANDI r16, r15, 255d ANDI r16, r15, 255d
CMPU r17, r16, r14 CMPU r17, r16, r14