| ... | @@ -1404,8 +1404,10 @@ fn airMul(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1404,8 +1404,10 @@ fn airMul(self: *Self, inst: Air.Inst.Index) !void { |
| 1404 | } | 1404 | } |
| 1405 | | 1405 | |
| 1406 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. | 1406 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. |
| 1407 | try self.register_manager.getReg(.rax, null); | 1407 | try self.register_manager.getReg(.rax, inst); |
| 1408 | try self.register_manager.getReg(.rdx, null); | 1408 | try self.register_manager.getReg(.rdx, null); |
| | 1409 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1410 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); |
| 1409 | | 1411 | |
| 1410 | const lhs = try self.resolveInst(bin_op.lhs); | 1412 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1411 | const rhs = try self.resolveInst(bin_op.rhs); | 1413 | const rhs = try self.resolveInst(bin_op.rhs); |
| ... | @@ -1501,8 +1503,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1501,8 +1503,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1501 | }; | 1503 | }; |
| 1502 | | 1504 | |
| 1503 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. | 1505 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. |
| 1504 | try self.register_manager.getReg(.rax, null); | 1506 | try self.register_manager.getReg(.rax, inst); |
| 1505 | try self.register_manager.getReg(.rdx, null); | 1507 | try self.register_manager.getReg(.rdx, null); |
| | 1508 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1509 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); |
| 1506 | | 1510 | |
| 1507 | const lhs = try self.resolveInst(bin_op.lhs); | 1511 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1508 | const rhs = try self.resolveInst(bin_op.rhs); | 1512 | const rhs = try self.resolveInst(bin_op.rhs); |
| ... | @@ -1527,7 +1531,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1527,7 +1531,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1527 | } | 1531 | } |
| 1528 | | 1532 | |
| 1529 | /// Generates signed or unsigned integer multiplication/division. | 1533 | /// Generates signed or unsigned integer multiplication/division. |
| 1530 | /// Requires use of .rax and .rdx registers. Spills them if necessary. | 1534 | /// Clobbers .rax and .rdx registers. |
| 1531 | /// Quotient is saved in .rax and remainder in .rdx. | 1535 | /// Quotient is saved in .rax and remainder in .rdx. |
| 1532 | fn genIntMulDivOpMir( | 1536 | fn genIntMulDivOpMir( |
| 1533 | self: *Self, | 1537 | self: *Self, |
| ... | @@ -1542,11 +1546,6 @@ fn genIntMulDivOpMir( | ... | @@ -1542,11 +1546,6 @@ fn genIntMulDivOpMir( |
| 1542 | return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{}); | 1546 | return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{}); |
| 1543 | } | 1547 | } |
| 1544 | | 1548 | |
| 1545 | try self.register_manager.getReg(.rax, null); | | |
| 1546 | try self.register_manager.getReg(.rdx, null); | | |
| 1547 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); | | |
| 1548 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); | | |
| 1549 | | | |
| 1550 | try self.genSetReg(ty, .rax, lhs); | 1549 | try self.genSetReg(ty, .rax, lhs); |
| 1551 | | 1550 | |
| 1552 | switch (signedness) { | 1551 | switch (signedness) { |
| ... | @@ -1610,6 +1609,7 @@ fn genIntMulDivOpMir( | ... | @@ -1610,6 +1609,7 @@ fn genIntMulDivOpMir( |
| 1610 | } | 1609 | } |
| 1611 | } | 1610 | } |
| 1612 | | 1611 | |
| | 1612 | /// Clobbers .rax and .rdx registers. |
| 1613 | fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { | 1613 | fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { |
| 1614 | const signedness = ty.intInfo(self.target.*).signedness; | 1614 | const signedness = ty.intInfo(self.target.*).signedness; |
| 1615 | const dividend = switch (lhs) { | 1615 | const dividend = switch (lhs) { |
| ... | @@ -1680,14 +1680,42 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1680,14 +1680,42 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void { |
| 1680 | return self.fail("TODO implement {}", .{tag}); | 1680 | return self.fail("TODO implement {}", .{tag}); |
| 1681 | } | 1681 | } |
| 1682 | | 1682 | |
| | 1683 | const signedness = ty.intInfo(self.target.*).signedness; |
| | 1684 | |
| 1683 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. | 1685 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. |
| 1684 | try self.register_manager.getReg(.rax, null); | 1686 | const track_rax: ?Air.Inst.Index = blk: { |
| | 1687 | if (signedness == .unsigned) break :blk inst; |
| | 1688 | switch (tag) { |
| | 1689 | .div_exact, .div_trunc => break :blk inst, |
| | 1690 | else => break :blk null, |
| | 1691 | } |
| | 1692 | }; |
| | 1693 | try self.register_manager.getReg(.rax, track_rax); |
| 1685 | try self.register_manager.getReg(.rdx, null); | 1694 | try self.register_manager.getReg(.rdx, null); |
| | 1695 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1696 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); |
| 1686 | | 1697 | |
| 1687 | const lhs = try self.resolveInst(bin_op.lhs); | 1698 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1688 | const rhs = try self.resolveInst(bin_op.rhs); | 1699 | lhs.freezeIfRegister(&self.register_manager); |
| | 1700 | defer lhs.unfreezeIfRegister(&self.register_manager); |
| | 1701 | |
| | 1702 | const rhs = blk: { |
| | 1703 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 1704 | if (signedness == .signed) { |
| | 1705 | switch (tag) { |
| | 1706 | .div_floor => { |
| | 1707 | rhs.freezeIfRegister(&self.register_manager); |
| | 1708 | defer rhs.unfreezeIfRegister(&self.register_manager); |
| | 1709 | break :blk try self.copyToRegisterWithInstTracking(inst, ty, rhs); |
| | 1710 | }, |
| | 1711 | else => {}, |
| | 1712 | } |
| | 1713 | } |
| | 1714 | break :blk rhs; |
| | 1715 | }; |
| | 1716 | rhs.freezeIfRegister(&self.register_manager); |
| | 1717 | defer rhs.unfreezeIfRegister(&self.register_manager); |
| 1689 | | 1718 | |
| 1690 | const signedness = ty.intInfo(self.target.*).signedness; | | |
| 1691 | if (signedness == .unsigned) { | 1719 | if (signedness == .unsigned) { |
| 1692 | try self.genIntMulDivOpMir(.div, ty, signedness, lhs, rhs); | 1720 | try self.genIntMulDivOpMir(.div, ty, signedness, lhs, rhs); |
| 1693 | break :result MCValue{ .register = .rax }; | 1721 | break :result MCValue{ .register = .rax }; |
| ... | @@ -1719,9 +1747,13 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1719,9 +1747,13 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void { |
| 1719 | } | 1747 | } |
| 1720 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. | 1748 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. |
| 1721 | try self.register_manager.getReg(.rax, null); | 1749 | try self.register_manager.getReg(.rax, null); |
| 1722 | try self.register_manager.getReg(.rdx, null); | 1750 | try self.register_manager.getReg(.rdx, inst); |
| | 1751 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1752 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); |
| | 1753 | |
| 1723 | const lhs = try self.resolveInst(bin_op.lhs); | 1754 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1724 | const rhs = try self.resolveInst(bin_op.rhs); | 1755 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 1756 | |
| 1725 | const signedness = ty.intInfo(self.target.*).signedness; | 1757 | const signedness = ty.intInfo(self.target.*).signedness; |
| 1726 | try self.genIntMulDivOpMir(switch (signedness) { | 1758 | try self.genIntMulDivOpMir(switch (signedness) { |
| 1727 | .signed => .idiv, | 1759 | .signed => .idiv, |
| ... | @@ -1739,12 +1771,17 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1739,12 +1771,17 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1739 | if (ty.zigTypeTag() != .Int) { | 1771 | if (ty.zigTypeTag() != .Int) { |
| 1740 | return self.fail("TODO implement .mod for operands of dst type {}", .{ty.zigTypeTag()}); | 1772 | return self.fail("TODO implement .mod for operands of dst type {}", .{ty.zigTypeTag()}); |
| 1741 | } | 1773 | } |
| | 1774 | const signedness = ty.intInfo(self.target.*).signedness; |
| | 1775 | |
| 1742 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. | 1776 | // Spill .rax and .rdx upfront to ensure we don't spill the operands too late. |
| 1743 | try self.register_manager.getReg(.rax, null); | 1777 | try self.register_manager.getReg(.rax, null); |
| 1744 | try self.register_manager.getReg(.rdx, null); | 1778 | try self.register_manager.getReg(.rdx, if (signedness == .unsigned) inst else null); |
| | 1779 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1780 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); |
| | 1781 | |
| 1745 | const lhs = try self.resolveInst(bin_op.lhs); | 1782 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1746 | const rhs = try self.resolveInst(bin_op.rhs); | 1783 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1747 | const signedness = ty.intInfo(self.target.*).signedness; | 1784 | |
| 1748 | switch (signedness) { | 1785 | switch (signedness) { |
| 1749 | .unsigned => { | 1786 | .unsigned => { |
| 1750 | try self.genIntMulDivOpMir(switch (signedness) { | 1787 | try self.genIntMulDivOpMir(switch (signedness) { |
| ... | @@ -1757,10 +1794,10 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1757,10 +1794,10 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1757 | const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs); | 1794 | const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs); |
| 1758 | try self.genIntMulComplexOpMir(ty, div_floor, rhs); | 1795 | try self.genIntMulComplexOpMir(ty, div_floor, rhs); |
| 1759 | | 1796 | |
| 1760 | const reg = try self.copyToTmpRegister(ty, lhs); | 1797 | const result = try self.copyToRegisterWithInstTracking(inst, ty, lhs); |
| 1761 | try self.genBinMathOpMir(.sub, ty, .{ .register = reg }, div_floor); | 1798 | try self.genBinMathOpMir(.sub, ty, result, div_floor); |
| 1762 | | 1799 | |
| 1763 | break :result MCValue{ .register = reg }; | 1800 | break :result result; |
| 1764 | }, | 1801 | }, |
| 1765 | } | 1802 | } |
| 1766 | }; | 1803 | }; |