diff --git a/lang/src/backend/hbvm.rs b/lang/src/backend/hbvm.rs index b2b61fc..61982d6 100644 --- a/lang/src/backend/hbvm.rs +++ b/lang/src/backend/hbvm.rs @@ -413,8 +413,15 @@ impl Nodes { && self.is_const(self[o].inputs[2]) && op.cond_op(self[o].ty).is_none()) }), + Kind::BinOp { op: TokenKind::Mul } if node.ty.is_float() => { + false + && node.outputs.iter().all(|&n| { + self[n].kind == Kind::BinOp { op: TokenKind::Add } + && self[n].inputs[1] == nid + }) + } Kind::BinOp { op: TokenKind::Add | TokenKind::Sub } => { - self.is_locked(node.inputs[1]) + (self.is_locked(node.inputs[1]) && !self[node.inputs[1]].ty.is_float()) || (self.is_const(node.inputs[2]) && node.outputs.iter().all(|&n| self.uses_direct_offset_of(n, nid, tys))) } diff --git a/lang/src/backend/hbvm/regalloc.rs b/lang/src/backend/hbvm/regalloc.rs index 89eccf8..0d080da 100644 --- a/lang/src/backend/hbvm/regalloc.rs +++ b/lang/src/backend/hbvm/regalloc.rs @@ -348,6 +348,18 @@ impl HbvmBackend { && let Some(op) = op.imm_binop(node.ty) { self.emit(op(atr(nid), atr(lhs), value as _)); + } else if node.kind == (Kind::BinOp { op: TokenKind::Add }) + && node.ty.is_float() + && nodes.is_locked(lhs) + { + let fma = [instrs::fma32, instrs::fma64] + [node.ty.simple_size().unwrap().ilog2() as usize - 2]; + self.emit(fma( + atr(nid), + atr(nodes[lhs].inputs[1]), + atr(nodes[lhs].inputs[2]), + atr(rhs), + )); } else if let Some(against) = op.cmp_against() { let op_ty = nodes[rhs].ty; let [dst, lhs, rhs] = [atr(nid), atr(lhs), atr(rhs)];