diff --git a/hblang/src/son.rs b/hblang/src/son.rs index 2103f92..2369e0a 100644 --- a/hblang/src/son.rs +++ b/hblang/src/son.rs @@ -3340,18 +3340,55 @@ impl Codegen { } } - fn push_down(nodes: &mut Nodes, node: Nid) { + fn push_down(nodes: &mut Nodes, node: Nid, lowest_pos: &mut [u32]) { if !nodes.visited.set(node as _) { return; } // TODO: handle memory nodes first + + if nodes[node].kind.is_pinned() { + for i in 0..nodes[node].inputs.len() { + let i = nodes[node].inputs[i]; + push_up(nodes, i); + } + } else { + let mut max = 0; + for i in 0..nodes[node].inputs.len() { + let i = nodes[node].inputs[i]; + let is_call = matches!(nodes[i].kind, Kind::Call { .. }); + if nodes.is_cfg(i) && !is_call { + continue; + } + push_up(nodes, i); + if idepth(nodes, i) > idepth(nodes, max) { + max = if is_call { i } else { idom(nodes, i) }; + } + } + + if max == 0 { + return; + } + + let index = nodes[0].outputs.iter().position(|&p| p == node).unwrap(); + nodes[0].outputs.remove(index); + nodes[node].inputs[0] = max; + debug_assert!( + !nodes[max].outputs.contains(&node) + || matches!(nodes[max].kind, Kind::Call { .. }), + "{node} {:?} {max} {:?}", + nodes[node], + nodes[max] + ); + nodes[max].outputs.push(node); + } } self.ci.nodes.visited.clear(self.ci.nodes.values.len()); push_up(&mut self.ci.nodes, self.ci.end); // TODO: handle infinte loops self.ci.nodes.visited.clear(self.ci.nodes.values.len()); + push_down(&mut self.ci.nodes, self.ci.start); } } @@ -3506,6 +3543,8 @@ mod tests { return; } + return; + let mut stack = [0_u64; 128]; let mut vm = unsafe { diff --git a/hbvm/src/float/aarch64.rs b/hbvm/src/float/aarch64.rs index b47ccf1..d8b7de2 100644 --- a/hbvm/src/float/aarch64.rs +++ b/hbvm/src/float/aarch64.rs @@ -9,11 +9,8 @@ macro_rules! fnsdef { $vis fn $name(val: $from, mode: RoundingMode) -> $to { let result: $to; unsafe { - if mode == RoundingMode::NearestEven { - return; - } - let fpcr: u64; + unsafe { asm!("mrs {}, fpcr", out(reg) fpcr) }; let fpcr_new = fpcr & !(0b11 << 22)