authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-10-20 15:59:02+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-10-20 16:14:52+02:00
log67941926b25e1adfdc47d22f7223af12cf3f5b01
treea03c7f044da3c415f8fa9fa67c6d99a743d47440
parentdd62d5941ea77f2ae226b28b0da71abeb92f6140
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: Remove remaining legacy binOp code


1 files changed, 44 insertions(+), 331 deletions(-)

src/arch/aarch64/CodeGen.zig+44-331
...@@ -1497,7 +1497,7 @@ fn allocRegs(...@@ -1497,7 +1497,7 @@ fn allocRegs(
1497/// instructions which are binary operations acting on two registers1497/// instructions which are binary operations acting on two registers
1498///1498///
1499/// Returns the destination register1499/// Returns the destination register
1500fn binOpRegisterNew(1500fn binOpRegister(
1501 self: *Self,1501 self: *Self,
1502 mir_tag: Mir.Inst.Tag,1502 mir_tag: Mir.Inst.Tag,
1503 lhs_bind: ReadArg.Bind,1503 lhs_bind: ReadArg.Bind,
...@@ -1582,7 +1582,7 @@ fn binOpRegisterNew(...@@ -1582,7 +1582,7 @@ fn binOpRegisterNew(
1582/// an immediate1582/// an immediate
1583///1583///
1584/// Returns the destination register1584/// Returns the destination register
1585fn binOpImmediateNew(1585fn binOpImmediate(
1586 self: *Self,1586 self: *Self,
1587 mir_tag: Mir.Inst.Tag,1587 mir_tag: Mir.Inst.Tag,
1588 lhs_bind: ReadArg.Bind,1588 lhs_bind: ReadArg.Bind,
...@@ -1639,258 +1639,6 @@ fn binOpImmediateNew(...@@ -1639,258 +1639,6 @@ fn binOpImmediateNew(
1639 return MCValue{ .register = dest_reg };1639 return MCValue{ .register = dest_reg };
1640}1640}
16411641
1642/// Don't call this function directly. Use binOp instead.
1643///
1644/// Calling this function signals an intention to generate a Mir
1645/// instruction of the form
1646///
1647/// op dest, lhs, rhs
1648///
1649/// Asserts that generating an instruction of that form is possible.
1650fn binOpRegister(
1651 self: *Self,
1652 mir_tag: Mir.Inst.Tag,
1653 lhs: MCValue,
1654 rhs: MCValue,
1655 lhs_ty: Type,
1656 rhs_ty: Type,
1657 metadata: ?BinOpMetadata,
1658) !MCValue {
1659 const lhs_is_register = lhs == .register;
1660 const rhs_is_register = rhs == .register;
1661
1662 if (lhs_is_register) assert(lhs.register == self.registerAlias(lhs.register, lhs_ty));
1663 if (rhs_is_register) assert(rhs.register == self.registerAlias(rhs.register, rhs_ty));
1664
1665 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1666 self.register_manager.lockReg(lhs.register)
1667 else
1668 null;
1669 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
1670
1671 const rhs_lock: ?RegisterLock = if (rhs_is_register)
1672 self.register_manager.lockReg(rhs.register)
1673 else
1674 null;
1675 defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
1676
1677 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1678
1679 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
1680 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1681 break :inst Air.refToIndex(md.lhs).?;
1682 } else null;
1683
1684 const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1685 const reg = self.registerAlias(raw_reg, lhs_ty);
1686
1687 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1688
1689 break :blk reg;
1690 };
1691 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
1692 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
1693
1694 const rhs_reg = if (rhs_is_register)
1695 // lhs is almost always equal to rhs, except in shifts. In
1696 // order to guarantee that registers will have equal sizes, we
1697 // use the register alias of rhs corresponding to the size of
1698 // lhs.
1699 self.registerAlias(rhs.register, lhs_ty)
1700 else blk: {
1701 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1702 break :inst Air.refToIndex(md.rhs).?;
1703 } else null;
1704
1705 const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1706
1707 // Here, we deliberately use lhs as lhs and rhs may differ in
1708 // the case of shifts. See comment above.
1709 const reg = self.registerAlias(raw_reg, lhs_ty);
1710
1711 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1712
1713 break :blk reg;
1714 };
1715 const new_rhs_lock = self.register_manager.lockReg(rhs_reg);
1716 defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
1717
1718 const dest_reg = switch (mir_tag) {
1719 else => if (metadata) |md| blk: {
1720 if (lhs_is_register and self.reuseOperand(md.inst, md.lhs, 0, lhs)) {
1721 break :blk lhs_reg;
1722 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
1723 break :blk rhs_reg;
1724 } else {
1725 const raw_reg = try self.register_manager.allocReg(md.inst, gp);
1726 break :blk self.registerAlias(raw_reg, lhs_ty);
1727 }
1728 } else blk: {
1729 const raw_reg = try self.register_manager.allocReg(null, gp);
1730 break :blk self.registerAlias(raw_reg, lhs_ty);
1731 },
1732 };
1733
1734 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
1735 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
1736
1737 const mir_data: Mir.Inst.Data = switch (mir_tag) {
1738 .add_shifted_register,
1739 .adds_shifted_register,
1740 .sub_shifted_register,
1741 .subs_shifted_register,
1742 => .{ .rrr_imm6_shift = .{
1743 .rd = dest_reg,
1744 .rn = lhs_reg,
1745 .rm = rhs_reg,
1746 .imm6 = 0,
1747 .shift = .lsl,
1748 } },
1749 .mul,
1750 .lsl_register,
1751 .asr_register,
1752 .lsr_register,
1753 .sdiv,
1754 .udiv,
1755 => .{ .rrr = .{
1756 .rd = dest_reg,
1757 .rn = lhs_reg,
1758 .rm = rhs_reg,
1759 } },
1760 .smull,
1761 .umull,
1762 => .{ .rrr = .{
1763 .rd = dest_reg.toX(),
1764 .rn = lhs_reg,
1765 .rm = rhs_reg,
1766 } },
1767 .and_shifted_register,
1768 .orr_shifted_register,
1769 .eor_shifted_register,
1770 => .{ .rrr_imm6_logical_shift = .{
1771 .rd = dest_reg,
1772 .rn = lhs_reg,
1773 .rm = rhs_reg,
1774 .imm6 = 0,
1775 .shift = .lsl,
1776 } },
1777 else => unreachable,
1778 };
1779
1780 _ = try self.addInst(.{
1781 .tag = mir_tag,
1782 .data = mir_data,
1783 });
1784
1785 return MCValue{ .register = dest_reg };
1786}
1787
1788/// Don't call this function directly. Use binOp instead.
1789///
1790/// Calling this function signals an intention to generate a Mir
1791/// instruction of the form
1792///
1793/// op dest, lhs, #rhs_imm
1794///
1795/// Set lhs_and_rhs_swapped to true iff inst.bin_op.lhs corresponds to
1796/// rhs and vice versa. This parameter is only used when maybe_inst !=
1797/// null.
1798///
1799/// Asserts that generating an instruction of that form is possible.
1800fn binOpImmediate(
1801 self: *Self,
1802 mir_tag: Mir.Inst.Tag,
1803 lhs: MCValue,
1804 rhs: MCValue,
1805 lhs_ty: Type,
1806 lhs_and_rhs_swapped: bool,
1807 metadata: ?BinOpMetadata,
1808) !MCValue {
1809 const lhs_is_register = lhs == .register;
1810
1811 if (lhs_is_register) assert(lhs.register == self.registerAlias(lhs.register, lhs_ty));
1812
1813 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1814 self.register_manager.lockReg(lhs.register)
1815 else
1816 null;
1817 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
1818
1819 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1820
1821 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
1822 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1823 break :inst Air.refToIndex(
1824 if (lhs_and_rhs_swapped) md.rhs else md.lhs,
1825 ).?;
1826 } else null;
1827
1828 const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1829 const reg = self.registerAlias(raw_reg, lhs_ty);
1830
1831 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1832
1833 break :blk reg;
1834 };
1835 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
1836 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
1837
1838 const dest_reg = switch (mir_tag) {
1839 else => if (metadata) |md| blk: {
1840 if (lhs_is_register and self.reuseOperand(
1841 md.inst,
1842 if (lhs_and_rhs_swapped) md.rhs else md.lhs,
1843 if (lhs_and_rhs_swapped) 1 else 0,
1844 lhs,
1845 )) {
1846 break :blk lhs_reg;
1847 } else {
1848 const raw_reg = try self.register_manager.allocReg(md.inst, gp);
1849 break :blk self.registerAlias(raw_reg, lhs_ty);
1850 }
1851 } else blk: {
1852 const raw_reg = try self.register_manager.allocReg(null, gp);
1853 break :blk self.registerAlias(raw_reg, lhs_ty);
1854 },
1855 };
1856
1857 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
1858
1859 const mir_data: Mir.Inst.Data = switch (mir_tag) {
1860 .add_immediate,
1861 .adds_immediate,
1862 .sub_immediate,
1863 .subs_immediate,
1864 => .{ .rr_imm12_sh = .{
1865 .rd = dest_reg,
1866 .rn = lhs_reg,
1867 .imm12 = @intCast(u12, rhs.immediate),
1868 } },
1869 .lsl_immediate,
1870 .asr_immediate,
1871 .lsr_immediate,
1872 => .{ .rr_shift = .{
1873 .rd = dest_reg,
1874 .rn = lhs_reg,
1875 .shift = @intCast(u6, rhs.immediate),
1876 } },
1877 else => unreachable,
1878 };
1879
1880 _ = try self.addInst(.{
1881 .tag = mir_tag,
1882 .data = mir_data,
1883 });
1884
1885 return MCValue{ .register = dest_reg };
1886}
1887
1888const BinOpMetadata = struct {
1889 inst: Air.Inst.Index,
1890 lhs: Air.Inst.Ref,
1891 rhs: Air.Inst.Ref,
1892};
1893
1894fn addSub(1642fn addSub(
1895 self: *Self,1643 self: *Self,
1896 tag: Air.Inst.Tag,1644 tag: Air.Inst.Tag,
...@@ -1938,12 +1686,12 @@ fn addSub(...@@ -1938,12 +1686,12 @@ fn addSub(
1938 };1686 };
19391687
1940 if (rhs_immediate_ok) {1688 if (rhs_immediate_ok) {
1941 return try self.binOpImmediateNew(mir_tag_immediate, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);1689 return try self.binOpImmediate(mir_tag_immediate, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);
1942 } else if (lhs_immediate_ok) {1690 } else if (lhs_immediate_ok) {
1943 // swap lhs and rhs1691 // swap lhs and rhs
1944 return try self.binOpImmediateNew(mir_tag_immediate, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);1692 return try self.binOpImmediate(mir_tag_immediate, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);
1945 } else {1693 } else {
1946 return try self.binOpRegisterNew(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1694 return try self.binOpRegister(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
1947 }1695 }
1948 } else {1696 } else {
1949 return self.fail("TODO binary operations on int with bits > 64", .{});1697 return self.fail("TODO binary operations on int with bits > 64", .{});
...@@ -1971,7 +1719,7 @@ fn mul(...@@ -1971,7 +1719,7 @@ fn mul(
1971 // TODO add optimisations for multiplication1719 // TODO add optimisations for multiplication
1972 // with immediates, for example a * 2 can be1720 // with immediates, for example a * 2 can be
1973 // lowered to a << 11721 // lowered to a << 1
1974 return try self.binOpRegisterNew(.mul, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1722 return try self.binOpRegister(.mul, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
1975 } else {1723 } else {
1976 return self.fail("TODO binary operations on int with bits > 64", .{});1724 return self.fail("TODO binary operations on int with bits > 64", .{});
1977 }1725 }
...@@ -2019,11 +1767,11 @@ fn divTrunc(...@@ -2019,11 +1767,11 @@ fn divTrunc(
2019 switch (int_info.signedness) {1767 switch (int_info.signedness) {
2020 .signed => {1768 .signed => {
2021 // TODO optimize integer division by constants1769 // TODO optimize integer division by constants
2022 return try self.binOpRegisterNew(.sdiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1770 return try self.binOpRegister(.sdiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2023 },1771 },
2024 .unsigned => {1772 .unsigned => {
2025 // TODO optimize integer division by constants1773 // TODO optimize integer division by constants
2026 return try self.binOpRegisterNew(.udiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1774 return try self.binOpRegister(.udiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2027 },1775 },
2028 }1776 }
2029 } else {1777 } else {
...@@ -2056,7 +1804,7 @@ fn divFloor(...@@ -2056,7 +1804,7 @@ fn divFloor(
2056 },1804 },
2057 .unsigned => {1805 .unsigned => {
2058 // TODO optimize integer division by constants1806 // TODO optimize integer division by constants
2059 return try self.binOpRegisterNew(.udiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1807 return try self.binOpRegister(.udiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2060 },1808 },
2061 }1809 }
2062 } else {1810 } else {
...@@ -2086,11 +1834,11 @@ fn divExact(...@@ -2086,11 +1834,11 @@ fn divExact(
2086 switch (int_info.signedness) {1834 switch (int_info.signedness) {
2087 .signed => {1835 .signed => {
2088 // TODO optimize integer division by constants1836 // TODO optimize integer division by constants
2089 return try self.binOpRegisterNew(.sdiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1837 return try self.binOpRegister(.sdiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2090 },1838 },
2091 .unsigned => {1839 .unsigned => {
2092 // TODO optimize integer division by constants1840 // TODO optimize integer division by constants
2093 return try self.binOpRegisterNew(.udiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1841 return try self.binOpRegister(.udiv, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2094 },1842 },
2095 }1843 }
2096 } else {1844 } else {
...@@ -2248,7 +1996,7 @@ fn bitwise(...@@ -2248,7 +1996,7 @@ fn bitwise(
2248 else => unreachable,1996 else => unreachable,
2249 };1997 };
22501998
2251 return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);1999 return try self.binOpRegister(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2252 } else {2000 } else {
2253 return self.fail("TODO binary operations on int with bits > 64", .{});2001 return self.fail("TODO binary operations on int with bits > 64", .{});
2254 }2002 }
...@@ -2293,12 +2041,12 @@ fn shiftExact(...@@ -2293,12 +2041,12 @@ fn shiftExact(
2293 };2041 };
22942042
2295 if (rhs_immediate) |imm| {2043 if (rhs_immediate) |imm| {
2296 return try self.binOpImmediateNew(mir_tag_immediate, lhs_bind, imm, lhs_ty, false, maybe_inst);2044 return try self.binOpImmediate(mir_tag_immediate, lhs_bind, imm, lhs_ty, false, maybe_inst);
2297 } else {2045 } else {
2298 // We intentionally pass lhs_ty here in order to2046 // We intentionally pass lhs_ty here in order to
2299 // prevent using the 32-bit register alias when2047 // prevent using the 32-bit register alias when
2300 // lhs_ty is > 32 bits.2048 // lhs_ty is > 32 bits.
2301 return try self.binOpRegisterNew(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, lhs_ty, maybe_inst);2049 return try self.binOpRegister(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, lhs_ty, maybe_inst);
2302 }2050 }
2303 } else {2051 } else {
2304 return self.fail("TODO binary operations on int with bits > 64", .{});2052 return self.fail("TODO binary operations on int with bits > 64", .{});
...@@ -2367,7 +2115,7 @@ fn booleanOp(...@@ -2367,7 +2115,7 @@ fn booleanOp(
2367 else => unreachable,2115 else => unreachable,
2368 };2116 };
23692117
2370 return try self.binOpRegisterNew(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);2118 return try self.binOpRegister(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2371 },2119 },
2372 else => unreachable,2120 else => unreachable,
2373 }2121 }
...@@ -2598,12 +2346,12 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2598,12 +2346,12 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
25982346
2599 const dest = blk: {2347 const dest = blk: {
2600 if (rhs_immediate_ok) {2348 if (rhs_immediate_ok) {
2601 break :blk try self.binOpImmediateNew(mir_tag_immediate, lhs_bind, rhs_immediate.?, lhs_ty, false, null);2349 break :blk try self.binOpImmediate(mir_tag_immediate, lhs_bind, rhs_immediate.?, lhs_ty, false, null);
2602 } else if (lhs_immediate_ok) {2350 } else if (lhs_immediate_ok) {
2603 // swap lhs and rhs2351 // swap lhs and rhs
2604 break :blk try self.binOpImmediateNew(mir_tag_immediate, rhs_bind, lhs_immediate.?, rhs_ty, true, null);2352 break :blk try self.binOpImmediate(mir_tag_immediate, rhs_bind, lhs_immediate.?, rhs_ty, true, null);
2605 } else {2353 } else {
2606 break :blk try self.binOpRegisterNew(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);2354 break :blk try self.binOpRegister(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
2607 }2355 }
2608 };2356 };
26092357
...@@ -2634,8 +2382,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2634,8 +2382,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2634 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2382 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2635 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });2383 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
2636 const result: MCValue = result: {2384 const result: MCValue = result: {
2637 const lhs = try self.resolveInst(extra.lhs);2385 const mod = self.bin_file.options.module.?;
2638 const rhs = try self.resolveInst(extra.rhs);2386
2387 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2388 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2639 const lhs_ty = self.air.typeOf(extra.lhs);2389 const lhs_ty = self.air.typeOf(extra.lhs);
2640 const rhs_ty = self.air.typeOf(extra.rhs);2390 const rhs_ty = self.air.typeOf(extra.rhs);
26412391
...@@ -2647,20 +2397,19 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2647,20 +2397,19 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2647 switch (lhs_ty.zigTypeTag()) {2397 switch (lhs_ty.zigTypeTag()) {
2648 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),2398 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
2649 .Int => {2399 .Int => {
2400 assert(lhs_ty.eql(rhs_ty, mod));
2650 const int_info = lhs_ty.intInfo(self.target.*);2401 const int_info = lhs_ty.intInfo(self.target.*);
2651
2652 if (int_info.bits <= 32) {2402 if (int_info.bits <= 32) {
2653 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);2403 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
26542404
2655 try self.spillCompareFlagsIfOccupied();2405 try self.spillCompareFlagsIfOccupied();
2656 self.condition_flags_inst = null;
26572406
2658 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {2407 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
2659 .signed => .smull,2408 .signed => .smull,
2660 .unsigned => .umull,2409 .unsigned => .umull,
2661 };2410 };
26622411
2663 const dest = try self.binOpRegister(base_tag, lhs, rhs, lhs_ty, rhs_ty, null);2412 const dest = try self.binOpRegister(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
2664 const dest_reg = dest.register;2413 const dest_reg = dest.register;
2665 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);2414 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
2666 defer self.register_manager.unlockReg(dest_reg_lock);2415 defer self.register_manager.unlockReg(dest_reg_lock);
...@@ -2709,50 +2458,27 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2709,50 +2458,27 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2709 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);2458 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
27102459
2711 try self.spillCompareFlagsIfOccupied();2460 try self.spillCompareFlagsIfOccupied();
2712 self.condition_flags_inst = null;
2713
2714 // TODO this should really be put in a helper similar to `binOpRegister`
2715 const lhs_is_register = lhs == .register;
2716 const rhs_is_register = rhs == .register;
2717
2718 const lhs_lock: ?RegisterLock = if (lhs_is_register)
2719 self.register_manager.lockRegAssumeUnused(lhs.register)
2720 else
2721 null;
2722 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
2723
2724 const rhs_lock: ?RegisterLock = if (rhs_is_register)
2725 self.register_manager.lockRegAssumeUnused(rhs.register)
2726 else
2727 null;
2728 defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
2729
2730 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
2731 const raw_reg = try self.register_manager.allocReg(null, gp);
2732 const reg = self.registerAlias(raw_reg, lhs_ty);
2733 break :blk reg;
2734 };
2735 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
2736 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
27372461
2738 const rhs_reg = if (rhs_is_register) rhs.register else blk: {2462 var lhs_reg: Register = undefined;
2739 const raw_reg = try self.register_manager.allocReg(null, gp);2463 var rhs_reg: Register = undefined;
2740 const reg = self.registerAlias(raw_reg, rhs_ty);2464 var dest_reg: Register = undefined;
2741 break :blk reg;2465 var dest_high_reg: Register = undefined;
2742 };2466 var truncated_reg: Register = undefined;
2743 const new_rhs_lock = self.register_manager.lockReg(rhs_reg);
2744 defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
2745
2746 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
2747 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
27482467
2749 const dest_reg = blk: {2468 const read_args = [_]ReadArg{
2750 const raw_reg = try self.register_manager.allocReg(null, gp);2469 .{ .ty = lhs_ty, .bind = lhs_bind, .class = gp, .reg = &lhs_reg },
2751 const reg = self.registerAlias(raw_reg, lhs_ty);2470 .{ .ty = rhs_ty, .bind = rhs_bind, .class = gp, .reg = &rhs_reg },
2752 break :blk reg;
2753 };2471 };
2754 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);2472 const write_args = [_]WriteArg{
2755 defer self.register_manager.unlockReg(dest_reg_lock);2473 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_reg },
2474 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_high_reg },
2475 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &truncated_reg },
2476 };
2477 try self.allocRegs(
2478 &read_args,
2479 &write_args,
2480 null,
2481 );
27562482
2757 switch (int_info.signedness) {2483 switch (int_info.signedness) {
2758 .signed => {2484 .signed => {
...@@ -2766,10 +2492,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2766,10 +2492,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2766 } },2492 } },
2767 });2493 });
27682494
2769 const dest_high_reg = try self.register_manager.allocReg(null, gp);
2770 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
2771 defer self.register_manager.unlockReg(dest_high_reg_lock);
2772
2773 // smulh dest_high, lhs, rhs2495 // smulh dest_high, lhs, rhs
2774 _ = try self.addInst(.{2496 _ = try self.addInst(.{
2775 .tag = .smulh,2497 .tag = .smulh,
...@@ -2816,10 +2538,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2816,10 +2538,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2816 }2538 }
2817 },2539 },
2818 .unsigned => {2540 .unsigned => {
2819 const dest_high_reg = try self.register_manager.allocReg(null, gp);
2820 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
2821 defer self.register_manager.unlockReg(dest_high_reg_lock);
2822
2823 // umulh dest_high, lhs, rhs2541 // umulh dest_high, lhs, rhs
2824 _ = try self.addInst(.{2542 _ = try self.addInst(.{
2825 .tag = .umulh,2543 .tag = .umulh,
...@@ -2870,10 +2588,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2870,10 +2588,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2870 },2588 },
2871 }2589 }
28722590
2873 const truncated_reg = try self.register_manager.allocReg(null, gp);
2874 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
2875 defer self.register_manager.unlockReg(truncated_reg_lock);
2876
2877 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);2591 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
28782592
2879 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });2593 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
...@@ -2893,6 +2607,8 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2893,6 +2607,8 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2893 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2607 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2894 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });2608 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
2895 const result: MCValue = result: {2609 const result: MCValue = result: {
2610 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2611 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2896 const lhs_ty = self.air.typeOf(extra.lhs);2612 const lhs_ty = self.air.typeOf(extra.lhs);
2897 const rhs_ty = self.air.typeOf(extra.rhs);2613 const rhs_ty = self.air.typeOf(extra.rhs);
28982614
...@@ -2910,9 +2626,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2910,9 +2626,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
29102626
2911 try self.spillCompareFlagsIfOccupied();2627 try self.spillCompareFlagsIfOccupied();
29122628
2913 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2914 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2915
2916 var lhs_reg: Register = undefined;2629 var lhs_reg: Register = undefined;
2917 var rhs_reg: Register = undefined;2630 var rhs_reg: Register = undefined;
2918 var dest_reg: Register = undefined;2631 var dest_reg: Register = undefined;