authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-29 11:00:57+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-30 00:37:42+02:00
log60879bc8ae216ddd33fab2e07d1d460e32636c95
treebfe1ead44e3df0c7f74505bab0889b3e9c1eae65
parentee6e3aef5deb4aedd8f65e0ba7c44b4979ed6a96

x64: clean up instruction tracking for div/mul ops


1 files changed, 54 insertions(+), 17 deletions(-)

src/arch/x86_64/CodeGen.zig+54-17
...@@ -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 }
14051405
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 });
14091411
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 };
15021504
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 });
15061510
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}
15281532
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.
1532fn genIntMulDivOpMir(1536fn 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 }
15441548
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);
15511550
1552 switch (signedness) {1551 switch (signedness) {
...@@ -1610,6 +1609,7 @@ fn genIntMulDivOpMir(...@@ -1610,6 +1609,7 @@ fn genIntMulDivOpMir(
1610 }1609 }
1611}1610}
16121611
1612/// Clobbers .rax and .rdx registers.
1613fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue {1613fn 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 }
16821682
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 });
16861697
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);
16891718
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);
17591796
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);
17621799
1763 break :result MCValue{ .register = reg };1800 break :result result;
1764 },1801 },
1765 }1802 }
1766 };1803 };