| ... | @@ -1563,28 +1563,63 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1563,28 +1563,63 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1563 | const lhs = try self.resolveInst(op_lhs); | 1563 | const lhs = try self.resolveInst(op_lhs); |
| 1564 | const rhs = try self.resolveInst(op_rhs); | 1564 | const rhs = try self.resolveInst(op_rhs); |
| 1565 | | 1565 | |
| | 1566 | const lhs_is_register = lhs == .register; |
| | 1567 | const rhs_is_register = rhs == .register; |
| | 1568 | const reuse_lhs = lhs_is_register and self.reuseOperand(inst, 0, lhs); |
| | 1569 | const reuse_rhs = !reuse_lhs and rhs_is_register and self.reuseOperand(inst, 1, rhs); |
| | 1570 | |
| 1566 | // Destination must be a register | 1571 | // Destination must be a register |
| 1567 | // LHS must be a register | 1572 | // LHS must be a register |
| 1568 | // RHS must be a register | 1573 | // RHS must be a register |
| 1569 | var dst_mcv: MCValue = undefined; | 1574 | var dst_mcv: MCValue = undefined; |
| 1570 | var lhs_mcv: MCValue = undefined; | 1575 | var lhs_mcv: MCValue = lhs; |
| 1571 | var rhs_mcv: MCValue = undefined; | 1576 | var rhs_mcv: MCValue = rhs; |
| 1572 | if (self.reuseOperand(inst, 0, lhs)) { | 1577 | |
| 1573 | // LHS is the destination | 1578 | // Allocate registers for operands and/or destination |
| 1574 | lhs_mcv = if (lhs != .register) try self.copyToNewRegister(inst, lhs) else lhs; | 1579 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 1575 | rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs; | 1580 | if (reuse_lhs) { |
| 1576 | dst_mcv = lhs_mcv; | 1581 | // Allocate 0 or 1 registers |
| 1577 | } else if (self.reuseOperand(inst, 1, rhs)) { | 1582 | if (!rhs_is_register) { |
| 1578 | // RHS is the destination | 1583 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(op_rhs, &.{lhs.register}) }; |
| 1579 | lhs_mcv = if (lhs != .register) try self.copyToNewRegister(inst, lhs) else lhs; | 1584 | branch.inst_table.putAssumeCapacity(op_rhs, rhs_mcv); |
| 1580 | rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs; | 1585 | } |
| 1581 | dst_mcv = rhs_mcv; | 1586 | dst_mcv = lhs; |
| | 1587 | } else if (reuse_rhs) { |
| | 1588 | // Allocate 0 or 1 registers |
| | 1589 | if (!lhs_is_register) { |
| | 1590 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(op_lhs, &.{rhs.register}) }; |
| | 1591 | branch.inst_table.putAssumeCapacity(op_lhs, lhs_mcv); |
| | 1592 | } |
| | 1593 | dst_mcv = rhs; |
| 1582 | } else { | 1594 | } else { |
| 1583 | // TODO save 1 copy instruction by directly allocating the destination register | 1595 | // Allocate 1 or 2 registers |
| 1584 | // LHS is the destination | 1596 | if (lhs_is_register and rhs_is_register) { |
| 1585 | lhs_mcv = try self.copyToNewRegister(inst, lhs); | 1597 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{ lhs.register, rhs.register }) }; |
| 1586 | rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs; | 1598 | } else if (lhs_is_register) { |
| 1587 | dst_mcv = lhs_mcv; | 1599 | // Move RHS to register |
| | 1600 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{lhs.register}) }; |
| | 1601 | rhs_mcv = dst_mcv; |
| | 1602 | } else if (rhs_is_register) { |
| | 1603 | // Move LHS to register |
| | 1604 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{rhs.register}) }; |
| | 1605 | lhs_mcv = dst_mcv; |
| | 1606 | } else { |
| | 1607 | // Move LHS and RHS to register |
| | 1608 | const regs = try self.register_manager.allocRegs(2, .{ inst, op_rhs }, &.{}); |
| | 1609 | lhs_mcv = MCValue{ .register = regs[0] }; |
| | 1610 | rhs_mcv = MCValue{ .register = regs[1] }; |
| | 1611 | dst_mcv = lhs_mcv; |
| | 1612 | |
| | 1613 | branch.inst_table.putAssumeCapacity(op_rhs, rhs_mcv); |
| | 1614 | } |
| | 1615 | } |
| | 1616 | |
| | 1617 | // Move the operands to the newly allocated registers |
| | 1618 | if (!lhs_is_register) { |
| | 1619 | try self.genSetReg(op_lhs.src, op_lhs.ty, lhs_mcv.register, lhs); |
| | 1620 | } |
| | 1621 | if (!rhs_is_register) { |
| | 1622 | try self.genSetReg(op_rhs.src, op_rhs.ty, rhs_mcv.register, rhs); |
| 1588 | } | 1623 | } |
| 1589 | | 1624 | |
| 1590 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mul(.al, dst_mcv.register, lhs_mcv.register, rhs_mcv.register).toU32()); | 1625 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mul(.al, dst_mcv.register, lhs_mcv.register, rhs_mcv.register).toU32()); |