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 {
14041404 }
14051405
14061406 // 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);
14081408 try self.register_manager.getReg(.rdx, null);
1409 self.register_manager.freezeRegs(&.{ .rax, .rdx });
1410 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });
14091411
14101412 const lhs = try self.resolveInst(bin_op.lhs);
14111413 const rhs = try self.resolveInst(bin_op.rhs);
......@@ -1501,8 +1503,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
15011503 };
15021504
15031505 // 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);
15051507 try self.register_manager.getReg(.rdx, null);
1508 self.register_manager.freezeRegs(&.{ .rax, .rdx });
1509 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });
15061510
15071511 const lhs = try self.resolveInst(bin_op.lhs);
15081512 const rhs = try self.resolveInst(bin_op.rhs);
......@@ -1527,7 +1531,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
15271531}
15281532
15291533/// 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.
15311535/// Quotient is saved in .rax and remainder in .rdx.
15321536fn genIntMulDivOpMir(
15331537 self: *Self,
......@@ -1542,11 +1546,6 @@ fn genIntMulDivOpMir(
15421546 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});
15431547 }
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
15501549 try self.genSetReg(ty, .rax, lhs);
15511550
15521551 switch (signedness) {
......@@ -1610,6 +1609,7 @@ fn genIntMulDivOpMir(
16101609 }
16111610}
16121611
1612/// Clobbers .rax and .rdx registers.
16131613fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue {
16141614 const signedness = ty.intInfo(self.target.*).signedness;
16151615 const dividend = switch (lhs) {
......@@ -1680,14 +1680,42 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
16801680 return self.fail("TODO implement {}", .{tag});
16811681 }
16821682
1683 const signedness = ty.intInfo(self.target.*).signedness;
1684
16831685 // 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);
16851694 try self.register_manager.getReg(.rdx, null);
1695 self.register_manager.freezeRegs(&.{ .rax, .rdx });
1696 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });
16861697
16871698 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;
16911719 if (signedness == .unsigned) {
16921720 try self.genIntMulDivOpMir(.div, ty, signedness, lhs, rhs);
16931721 break :result MCValue{ .register = .rax };
......@@ -1719,9 +1747,13 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void {
17191747 }
17201748 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
17211749 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
17231754 const lhs = try self.resolveInst(bin_op.lhs);
17241755 const rhs = try self.resolveInst(bin_op.rhs);
1756
17251757 const signedness = ty.intInfo(self.target.*).signedness;
17261758 try self.genIntMulDivOpMir(switch (signedness) {
17271759 .signed => .idiv,
......@@ -1739,12 +1771,17 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
17391771 if (ty.zigTypeTag() != .Int) {
17401772 return self.fail("TODO implement .mod for operands of dst type {}", .{ty.zigTypeTag()});
17411773 }
1774 const signedness = ty.intInfo(self.target.*).signedness;
1775
17421776 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
17431777 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
17451782 const lhs = try self.resolveInst(bin_op.lhs);
17461783 const rhs = try self.resolveInst(bin_op.rhs);
1747 const signedness = ty.intInfo(self.target.*).signedness;
1784
17481785 switch (signedness) {
17491786 .unsigned => {
17501787 try self.genIntMulDivOpMir(switch (signedness) {
......@@ -1757,10 +1794,10 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
17571794 const div_floor = try self.genInlineIntDivFloor(ty, lhs, rhs);
17581795 try self.genIntMulComplexOpMir(ty, div_floor, rhs);
17591796
1760 const reg = try self.copyToTmpRegister(ty, lhs);
1761 try self.genBinMathOpMir(.sub, ty, .{ .register = reg }, div_floor);
1797 const result = try self.copyToRegisterWithInstTracking(inst, ty, lhs);
1798 try self.genBinMathOpMir(.sub, ty, result, div_floor);
17621799
1763 break :result MCValue{ .register = reg };
1800 break :result result;
17641801 },
17651802 }
17661803 };