| author | |
| committer | |
| log | 74a01e3d64cc5d941486e5bd037f6f55e030339c |
| tree | 9cdbe1d2c262d78e9bfec6dff5c4167e216fcaf4 |
| parent | e0b1170b676c04d1293970c717e13bdc01584671 |
5 files changed, 74 insertions(+), 116 deletions(-)
src/arch/aarch64/CodeGen.zig+7-7| ... | ... | @@ -774,7 +774,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 774 | 774 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 775 | 775 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 776 | 776 | if (abi_size <= ptr_bytes) { |
| 777 | if (self.register_manager.tryAllocReg(inst, &.{})) |reg| { | |
| 777 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 778 | 778 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 779 | 779 | } |
| 780 | 780 | } |
| ... | ... | @@ -797,7 +797,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 797 | 797 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 798 | 798 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 799 | 799 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 800 | const reg = try self.register_manager.allocReg(null, &.{}); | |
| 800 | const reg = try self.register_manager.allocReg(null); | |
| 801 | 801 | try self.genSetReg(ty, reg, mcv); |
| 802 | 802 | return reg; |
| 803 | 803 | } |
| ... | ... | @@ -806,7 +806,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 806 | 806 | /// `reg_owner` is the instruction that gets associated with the register in the register table. |
| 807 | 807 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 808 | 808 | fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue { |
| 809 | const reg = try self.register_manager.allocReg(reg_owner, &.{}); | |
| 809 | const reg = try self.register_manager.allocReg(reg_owner); | |
| 810 | 810 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); |
| 811 | 811 | return MCValue{ .register = reg }; |
| 812 | 812 | } |
| ... | ... | @@ -1270,7 +1270,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1270 | 1270 | .memory, |
| 1271 | 1271 | .stack_offset, |
| 1272 | 1272 | => { |
| 1273 | const reg = try self.register_manager.allocReg(null, &.{}); | |
| 1273 | const reg = try self.register_manager.allocReg(null); | |
| 1274 | 1274 | self.register_manager.freezeRegs(&.{reg}); |
| 1275 | 1275 | defer self.register_manager.unfreezeRegs(&.{reg}); |
| 1276 | 1276 | |
| ... | ... | @@ -1729,15 +1729,15 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1729 | 1729 | if (!lhs_is_register and !rhs_is_register) { |
| 1730 | 1730 | const regs = try self.register_manager.allocRegs(2, .{ |
| 1731 | 1731 | Air.refToIndex(bin_op.rhs).?, Air.refToIndex(bin_op.lhs).?, |
| 1732 | }, &.{}); | |
| 1732 | }); | |
| 1733 | 1733 | lhs_mcv = MCValue{ .register = regs[0] }; |
| 1734 | 1734 | rhs_mcv = MCValue{ .register = regs[1] }; |
| 1735 | 1735 | } else if (!rhs_is_register) { |
| 1736 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.rhs).?, &.{}) }; | |
| 1736 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.rhs).?) }; | |
| 1737 | 1737 | } |
| 1738 | 1738 | } |
| 1739 | 1739 | if (!lhs_is_register) { |
| 1740 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?, &.{}) }; | |
| 1740 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?) }; | |
| 1741 | 1741 | } |
| 1742 | 1742 | |
| 1743 | 1743 | // Move the operands to the newly allocated registers |
src/arch/arm/CodeGen.zig+34-34| ... | ... | @@ -750,7 +750,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 750 | 750 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 751 | 751 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 752 | 752 | if (abi_size <= ptr_bytes) { |
| 753 | if (self.register_manager.tryAllocReg(inst, &.{})) |reg| { | |
| 753 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 754 | 754 | return MCValue{ .register = reg }; |
| 755 | 755 | } |
| 756 | 756 | } |
| ... | ... | @@ -791,7 +791,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 791 | 791 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 792 | 792 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 793 | 793 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 794 | const reg = try self.register_manager.allocReg(null, &.{}); | |
| 794 | const reg = try self.register_manager.allocReg(null); | |
| 795 | 795 | try self.genSetReg(ty, reg, mcv); |
| 796 | 796 | return reg; |
| 797 | 797 | } |
| ... | ... | @@ -800,7 +800,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 800 | 800 | /// `reg_owner` is the instruction that gets associated with the register in the register table. |
| 801 | 801 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 802 | 802 | fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue { |
| 803 | const reg = try self.register_manager.allocReg(reg_owner, &.{}); | |
| 803 | const reg = try self.register_manager.allocReg(reg_owner); | |
| 804 | 804 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); |
| 805 | 805 | return MCValue{ .register = reg }; |
| 806 | 806 | } |
| ... | ... | @@ -1247,7 +1247,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1247 | 1247 | defer self.register_manager.unfreezeRegs(&.{base_mcv.register}); |
| 1248 | 1248 | |
| 1249 | 1249 | if (elem_size <= 4) { |
| 1250 | const dst_reg = try self.register_manager.allocReg(inst, &.{}); | |
| 1250 | const dst_reg = try self.register_manager.allocReg(inst); | |
| 1251 | 1251 | self.register_manager.freezeRegs(&.{dst_reg}); |
| 1252 | 1252 | defer self.register_manager.unfreezeRegs(&.{dst_reg}); |
| 1253 | 1253 | |
| ... | ... | @@ -1285,7 +1285,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1285 | 1285 | } else { |
| 1286 | 1286 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 1287 | 1287 | |
| 1288 | const addr_reg = try self.register_manager.allocReg(null, &.{}); | |
| 1288 | const addr_reg = try self.register_manager.allocReg(null); | |
| 1289 | 1289 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1290 | 1290 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1291 | 1291 | |
| ... | ... | @@ -1437,7 +1437,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1437 | 1437 | }, |
| 1438 | 1438 | .stack_offset => |off| { |
| 1439 | 1439 | if (elem_ty.abiSize(self.target.*) <= 4) { |
| 1440 | const tmp_reg = try self.register_manager.allocReg(null, &.{}); | |
| 1440 | const tmp_reg = try self.register_manager.allocReg(null); | |
| 1441 | 1441 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1442 | 1442 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| 1443 | 1443 | |
| ... | ... | @@ -1451,7 +1451,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1451 | 1451 | // larger |
| 1452 | 1452 | |
| 1453 | 1453 | const usize_ty = Type.initTag(.usize); |
| 1454 | const tmp_regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{}); | |
| 1454 | const tmp_regs = try self.register_manager.allocRegs(2, .{ null, null }); | |
| 1455 | 1455 | self.register_manager.freezeRegs(&tmp_regs); |
| 1456 | 1456 | defer self.register_manager.unfreezeRegs(&tmp_regs); |
| 1457 | 1457 | |
| ... | ... | @@ -1475,7 +1475,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1475 | 1475 | try self.genSetStack(usize_ty, off + 4, MCValue{ .register = tmp_regs[1] }); |
| 1476 | 1476 | } else { |
| 1477 | 1477 | // TODO optimize the register allocation |
| 1478 | const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, &.{}); | |
| 1478 | const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }); | |
| 1479 | 1479 | self.register_manager.freezeRegs(&regs); |
| 1480 | 1480 | defer self.register_manager.unfreezeRegs(&regs); |
| 1481 | 1481 | |
| ... | ... | @@ -1524,7 +1524,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1524 | 1524 | .stack_offset, |
| 1525 | 1525 | .stack_argument_offset, |
| 1526 | 1526 | => { |
| 1527 | const reg = try self.register_manager.allocReg(null, &.{}); | |
| 1527 | const reg = try self.register_manager.allocReg(null); | |
| 1528 | 1528 | self.register_manager.freezeRegs(&.{reg}); |
| 1529 | 1529 | defer self.register_manager.unfreezeRegs(&.{reg}); |
| 1530 | 1530 | |
| ... | ... | @@ -1597,7 +1597,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1597 | 1597 | }, |
| 1598 | 1598 | else => { |
| 1599 | 1599 | if (value_ty.abiSize(self.target.*) <= 4) { |
| 1600 | const tmp_reg = try self.register_manager.allocReg(null, &.{}); | |
| 1600 | const tmp_reg = try self.register_manager.allocReg(null); | |
| 1601 | 1601 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1602 | 1602 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| 1603 | 1603 | |
| ... | ... | @@ -1774,14 +1774,14 @@ fn genArmBinIntOp( |
| 1774 | 1774 | if (reuse_lhs) { |
| 1775 | 1775 | // Allocate 0 or 1 registers |
| 1776 | 1776 | if (!rhs_is_register and rhs_should_be_register) { |
| 1777 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_rhs).?, &.{}) }; | |
| 1777 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_rhs).?) }; | |
| 1778 | 1778 | branch.inst_table.putAssumeCapacity(Air.refToIndex(op_rhs).?, rhs_mcv); |
| 1779 | 1779 | } |
| 1780 | 1780 | dst_mcv = lhs; |
| 1781 | 1781 | } else if (reuse_rhs and can_swap_lhs_and_rhs) { |
| 1782 | 1782 | // Allocate 0 or 1 registers |
| 1783 | 1783 | if (!lhs_is_register and lhs_should_be_register) { |
| 1784 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_lhs).?, &.{}) }; | |
| 1784 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_lhs).?) }; | |
| 1785 | 1785 | branch.inst_table.putAssumeCapacity(Air.refToIndex(op_lhs).?, lhs_mcv); |
| 1786 | 1786 | } |
| 1787 | 1787 | dst_mcv = rhs; |
| ... | ... | @@ -1791,18 +1791,18 @@ fn genArmBinIntOp( |
| 1791 | 1791 | // Allocate 1 or 2 registers |
| 1792 | 1792 | if (lhs_should_be_register and rhs_should_be_register) { |
| 1793 | 1793 | if (lhs_is_register and rhs_is_register) { |
| 1794 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 1794 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 1795 | 1795 | } else if (lhs_is_register) { |
| 1796 | 1796 | // Move RHS to register |
| 1797 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 1797 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 1798 | 1798 | rhs_mcv = dst_mcv; |
| 1799 | 1799 | } else if (rhs_is_register) { |
| 1800 | 1800 | // Move LHS to register |
| 1801 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 1801 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 1802 | 1802 | lhs_mcv = dst_mcv; |
| 1803 | 1803 | } else { |
| 1804 | 1804 | // Move LHS and RHS to register |
| 1805 | const regs = try self.register_manager.allocRegs(2, .{ inst, Air.refToIndex(op_rhs).? }, &.{}); | |
| 1805 | const regs = try self.register_manager.allocRegs(2, .{ inst, Air.refToIndex(op_rhs).? }); | |
| 1806 | 1806 | lhs_mcv = MCValue{ .register = regs[0] }; |
| 1807 | 1807 | rhs_mcv = MCValue{ .register = regs[1] }; |
| 1808 | 1808 | dst_mcv = lhs_mcv; |
| ... | ... | @@ -1812,17 +1812,17 @@ fn genArmBinIntOp( |
| 1812 | 1812 | } else if (lhs_should_be_register) { |
| 1813 | 1813 | // RHS is immediate |
| 1814 | 1814 | if (lhs_is_register) { |
| 1815 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 1815 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 1816 | 1816 | } else { |
| 1817 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 1817 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 1818 | 1818 | lhs_mcv = dst_mcv; |
| 1819 | 1819 | } |
| 1820 | 1820 | } else if (rhs_should_be_register and can_swap_lhs_and_rhs) { |
| 1821 | 1821 | // LHS is immediate |
| 1822 | 1822 | if (rhs_is_register) { |
| 1823 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 1823 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 1824 | 1824 | } else { |
| 1825 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 1825 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 1826 | 1826 | rhs_mcv = dst_mcv; |
| 1827 | 1827 | } |
| 1828 | 1828 | |
| ... | ... | @@ -1983,32 +1983,32 @@ fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Ai |
| 1983 | 1983 | if (reuse_lhs) { |
| 1984 | 1984 | // Allocate 0 or 1 registers |
| 1985 | 1985 | if (!rhs_is_register) { |
| 1986 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_rhs).?, &.{}) }; | |
| 1986 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_rhs).?) }; | |
| 1987 | 1987 | branch.inst_table.putAssumeCapacity(Air.refToIndex(op_rhs).?, rhs_mcv); |
| 1988 | 1988 | } |
| 1989 | 1989 | dst_mcv = lhs; |
| 1990 | 1990 | } else if (reuse_rhs) { |
| 1991 | 1991 | // Allocate 0 or 1 registers |
| 1992 | 1992 | if (!lhs_is_register) { |
| 1993 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_lhs).?, &.{}) }; | |
| 1993 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(op_lhs).?) }; | |
| 1994 | 1994 | branch.inst_table.putAssumeCapacity(Air.refToIndex(op_lhs).?, lhs_mcv); |
| 1995 | 1995 | } |
| 1996 | 1996 | dst_mcv = rhs; |
| 1997 | 1997 | } else { |
| 1998 | 1998 | // Allocate 1 or 2 registers |
| 1999 | 1999 | if (lhs_is_register and rhs_is_register) { |
| 2000 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 2000 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 2001 | 2001 | } else if (lhs_is_register) { |
| 2002 | 2002 | // Move RHS to register |
| 2003 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 2003 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 2004 | 2004 | rhs_mcv = dst_mcv; |
| 2005 | 2005 | } else if (rhs_is_register) { |
| 2006 | 2006 | // Move LHS to register |
| 2007 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{}) }; | |
| 2007 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst) }; | |
| 2008 | 2008 | lhs_mcv = dst_mcv; |
| 2009 | 2009 | } else { |
| 2010 | 2010 | // Move LHS and RHS to register |
| 2011 | const regs = try self.register_manager.allocRegs(2, .{ inst, Air.refToIndex(op_rhs).? }, &.{}); | |
| 2011 | const regs = try self.register_manager.allocRegs(2, .{ inst, Air.refToIndex(op_rhs).? }); | |
| 2012 | 2012 | lhs_mcv = MCValue{ .register = regs[0] }; |
| 2013 | 2013 | rhs_mcv = MCValue{ .register = regs[1] }; |
| 2014 | 2014 | dst_mcv = lhs_mcv; |
| ... | ... | @@ -2056,17 +2056,17 @@ fn genArmMulConstant(self: *Self, inst: Air.Inst.Index, op: Air.Inst.Ref, op_ind |
| 2056 | 2056 | // Allocate registers for operands and/or destination |
| 2057 | 2057 | if (reuse_lhs) { |
| 2058 | 2058 | // Allocate 1 register |
| 2059 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(null, &.{}) }; | |
| 2059 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(null) }; | |
| 2060 | 2060 | dst_mcv = lhs; |
| 2061 | 2061 | } else { |
| 2062 | 2062 | // Allocate 1 or 2 registers |
| 2063 | 2063 | if (lhs_is_register) { |
| 2064 | 2064 | // Move RHS to register |
| 2065 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null, &.{}) }; | |
| 2065 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) }; | |
| 2066 | 2066 | rhs_mcv = dst_mcv; |
| 2067 | 2067 | } else { |
| 2068 | 2068 | // Move LHS and RHS to register |
| 2069 | const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{}); | |
| 2069 | const regs = try self.register_manager.allocRegs(2, .{ null, null }); | |
| 2070 | 2070 | lhs_mcv = MCValue{ .register = regs[0] }; |
| 2071 | 2071 | rhs_mcv = MCValue{ .register = regs[1] }; |
| 2072 | 2072 | dst_mcv = lhs_mcv; |
| ... | ... | @@ -2432,20 +2432,20 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2432 | 2432 | if (!lhs_is_register and !rhs_is_register) { |
| 2433 | 2433 | const regs = try self.register_manager.allocRegs(2, .{ |
| 2434 | 2434 | Air.refToIndex(bin_op.lhs).?, Air.refToIndex(bin_op.rhs).?, |
| 2435 | }, &.{}); | |
| 2435 | }); | |
| 2436 | 2436 | lhs_mcv = MCValue{ .register = regs[0] }; |
| 2437 | 2437 | rhs_mcv = MCValue{ .register = regs[1] }; |
| 2438 | 2438 | } else if (!rhs_is_register) { |
| 2439 | 2439 | const track_inst = if (self.liveness.operandDies(inst, 1)) null else Air.refToIndex(bin_op.rhs).?; |
| 2440 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) }; | |
| 2440 | rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst) }; | |
| 2441 | 2441 | } else if (!lhs_is_register) { |
| 2442 | 2442 | const track_inst = if (self.liveness.operandDies(inst, 0)) null else Air.refToIndex(bin_op.lhs).?; |
| 2443 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) }; | |
| 2443 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst) }; | |
| 2444 | 2444 | } |
| 2445 | 2445 | } else { |
| 2446 | 2446 | if (!lhs_is_register) { |
| 2447 | 2447 | const track_inst = if (self.liveness.operandDies(inst, 0)) null else Air.refToIndex(bin_op.lhs).?; |
| 2448 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) }; | |
| 2448 | lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst) }; | |
| 2449 | 2449 | } |
| 2450 | 2450 | } |
| 2451 | 2451 | |
| ... | ... | @@ -3185,7 +3185,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3185 | 3185 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3186 | 3186 | } else { |
| 3187 | 3187 | // TODO optimize the register allocation |
| 3188 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, &.{}); | |
| 3188 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); | |
| 3189 | 3189 | const src_reg = regs[0]; |
| 3190 | 3190 | const dst_reg = regs[1]; |
| 3191 | 3191 | const len_reg = regs[2]; |
src/arch/riscv64/CodeGen.zig+4-4| ... | ... | @@ -749,7 +749,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 749 | 749 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 750 | 750 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 751 | 751 | if (abi_size <= ptr_bytes) { |
| 752 | if (self.register_manager.tryAllocReg(inst, &.{})) |reg| { | |
| 752 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 753 | 753 | return MCValue{ .register = reg }; |
| 754 | 754 | } |
| 755 | 755 | } |
| ... | ... | @@ -772,7 +772,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 772 | 772 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 773 | 773 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 774 | 774 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 775 | const reg = try self.register_manager.allocReg(null, &.{}); | |
| 775 | const reg = try self.register_manager.allocReg(null); | |
| 776 | 776 | try self.genSetReg(ty, reg, mcv); |
| 777 | 777 | return reg; |
| 778 | 778 | } |
| ... | ... | @@ -781,7 +781,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 781 | 781 | /// `reg_owner` is the instruction that gets associated with the register in the register table. |
| 782 | 782 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 783 | 783 | fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue { |
| 784 | const reg = try self.register_manager.allocReg(reg_owner, &.{}); | |
| 784 | const reg = try self.register_manager.allocReg(reg_owner); | |
| 785 | 785 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); |
| 786 | 786 | return MCValue{ .register = reg }; |
| 787 | 787 | } |
| ... | ... | @@ -1211,7 +1211,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1211 | 1211 | .memory, |
| 1212 | 1212 | .stack_offset, |
| 1213 | 1213 | => { |
| 1214 | const reg = try self.register_manager.allocReg(null, &.{}); | |
| 1214 | const reg = try self.register_manager.allocReg(null); | |
| 1215 | 1215 | self.register_manager.freezeRegs(&.{reg}); |
| 1216 | 1216 | defer self.register_manager.unfreezeRegs(&.{reg}); |
| 1217 | 1217 |
src/arch/x86_64/CodeGen.zig+11-11| ... | ... | @@ -819,7 +819,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 819 | 819 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 820 | 820 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 821 | 821 | if (abi_size <= ptr_bytes) { |
| 822 | if (self.register_manager.tryAllocReg(inst, &.{})) |reg| { | |
| 822 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 823 | 823 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 824 | 824 | } |
| 825 | 825 | } |
| ... | ... | @@ -842,7 +842,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 842 | 842 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 843 | 843 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 844 | 844 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 845 | const reg = try self.register_manager.allocReg(null, &.{}); | |
| 845 | const reg = try self.register_manager.allocReg(null); | |
| 846 | 846 | try self.genSetReg(ty, reg, mcv); |
| 847 | 847 | return reg; |
| 848 | 848 | } |
| ... | ... | @@ -851,7 +851,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 851 | 851 | /// `reg_owner` is the instruction that gets associated with the register in the register table. |
| 852 | 852 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 853 | 853 | fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue { |
| 854 | const reg = try self.register_manager.allocReg(reg_owner, &.{}); | |
| 854 | const reg = try self.register_manager.allocReg(reg_owner); | |
| 855 | 855 | try self.genSetReg(ty, reg, mcv); |
| 856 | 856 | return MCValue{ .register = reg }; |
| 857 | 857 | } |
| ... | ... | @@ -932,7 +932,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 932 | 932 | const reg = switch (operand) { |
| 933 | 933 | .register => |reg| reg, |
| 934 | 934 | else => inner: { |
| 935 | const reg = try self.register_manager.allocReg(inst, &.{}); | |
| 935 | const reg = try self.register_manager.allocReg(inst); | |
| 936 | 936 | try self.genSetReg(src_ty, reg, operand); |
| 937 | 937 | break :inner reg; |
| 938 | 938 | }, |
| ... | ... | @@ -1401,7 +1401,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1401 | 1401 | self.register_manager.freezeRegs(&.{offset_reg}); |
| 1402 | 1402 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); |
| 1403 | 1403 | |
| 1404 | const addr_reg = try self.register_manager.allocReg(null, &.{}); | |
| 1404 | const addr_reg = try self.register_manager.allocReg(null); | |
| 1405 | 1405 | switch (slice_mcv) { |
| 1406 | 1406 | .stack_offset => |off| { |
| 1407 | 1407 | // mov reg, [rbp - 8] |
| ... | ... | @@ -1459,7 +1459,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1459 | 1459 | self.register_manager.freezeRegs(&.{offset_reg}); |
| 1460 | 1460 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); |
| 1461 | 1461 | |
| 1462 | const addr_reg = try self.register_manager.allocReg(null, &.{}); | |
| 1462 | const addr_reg = try self.register_manager.allocReg(null); | |
| 1463 | 1463 | switch (array) { |
| 1464 | 1464 | .stack_offset => |off| { |
| 1465 | 1465 | // lea reg, [rbp] |
| ... | ... | @@ -1640,7 +1640,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1640 | 1640 | }, |
| 1641 | 1641 | .stack_offset => |off| { |
| 1642 | 1642 | if (abi_size <= 8) { |
| 1643 | const tmp_reg = try self.register_manager.allocReg(null, &.{}); | |
| 1643 | const tmp_reg = try self.register_manager.allocReg(null); | |
| 1644 | 1644 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 1645 | 1645 | return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); |
| 1646 | 1646 | } |
| ... | ... | @@ -1648,7 +1648,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1648 | 1648 | self.register_manager.freezeRegs(&.{ .rax, .rcx }); |
| 1649 | 1649 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx }); |
| 1650 | 1650 | |
| 1651 | const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{}); | |
| 1651 | const regs = try self.register_manager.allocRegs(3, .{ null, null, null }); | |
| 1652 | 1652 | const addr_reg = regs[0]; |
| 1653 | 1653 | const count_reg = regs[1]; |
| 1654 | 1654 | const tmp_reg = regs[2]; |
| ... | ... | @@ -1957,7 +1957,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 1957 | 1957 | break :blk reg; |
| 1958 | 1958 | } else { |
| 1959 | 1959 | self.register_manager.freezeRegs(&.{reg}); |
| 1960 | const result_reg = try self.register_manager.allocReg(inst, &.{}); | |
| 1960 | const result_reg = try self.register_manager.allocReg(inst); | |
| 1961 | 1961 | try self.genSetReg(ptr_ty, result_reg, mcv); |
| 1962 | 1962 | break :blk result_reg; |
| 1963 | 1963 | } |
| ... | ... | @@ -3386,7 +3386,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 3386 | 3386 | self.register_manager.freezeRegs(&.{ .rax, .rcx }); |
| 3387 | 3387 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx }); |
| 3388 | 3388 | |
| 3389 | const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{}); | |
| 3389 | const regs = try self.register_manager.allocRegs(3, .{ null, null, null }); | |
| 3390 | 3390 | const addr_reg = regs[0]; |
| 3391 | 3391 | const count_reg = regs[1]; |
| 3392 | 3392 | const tmp_reg = regs[2]; |
| ... | ... | @@ -3554,7 +3554,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3554 | 3554 | self.register_manager.freezeRegs(&.{ .rax, .rcx, .rbp }); |
| 3555 | 3555 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rbp }); |
| 3556 | 3556 | |
| 3557 | const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{}); | |
| 3557 | const regs = try self.register_manager.allocRegs(3, .{ null, null, null }); | |
| 3558 | 3558 | const addr_reg = regs[0]; |
| 3559 | 3559 | const count_reg = regs[1]; |
| 3560 | 3560 | const tmp_reg = regs[2]; |
src/register_manager.zig+18-60| ... | ... | @@ -118,17 +118,12 @@ pub fn RegisterManager( |
| 118 | 118 | /// Allocates a specified number of registers, optionally |
| 119 | 119 | /// tracking them. Returns `null` if not enough registers are |
| 120 | 120 | /// free. |
| 121 | /// | |
| 122 | /// Exceptions are deprecated, use freezeRegs and unfreezeRegs | |
| 123 | /// instead. | |
| 124 | 121 | pub fn tryAllocRegs( |
| 125 | 122 | self: *Self, |
| 126 | 123 | comptime count: comptime_int, |
| 127 | 124 | insts: [count]?Air.Inst.Index, |
| 128 | exceptions: []const Register, | |
| 129 | 125 | ) ?[count]Register { |
| 130 | 126 | comptime assert(count > 0 and count <= callee_preserved_regs.len); |
| 131 | assert(count + exceptions.len <= callee_preserved_regs.len); | |
| 132 | 127 | |
| 133 | 128 | const free_registers = @popCount(FreeRegInt, self.free_registers); |
| 134 | 129 | if (free_registers < count) return null; |
| ... | ... | @@ -137,7 +132,6 @@ pub fn RegisterManager( |
| 137 | 132 | var i: usize = 0; |
| 138 | 133 | for (callee_preserved_regs) |reg| { |
| 139 | 134 | if (i >= count) break; |
| 140 | if (mem.indexOfScalar(Register, exceptions, reg) != null) continue; | |
| 141 | 135 | if (self.isRegFrozen(reg)) continue; |
| 142 | 136 | if (self.isRegFree(reg)) { |
| 143 | 137 | regs[i] = reg; |
| ... | ... | @@ -163,29 +157,21 @@ pub fn RegisterManager( |
| 163 | 157 | /// Allocates a register and optionally tracks it with a |
| 164 | 158 | /// corresponding instruction. Returns `null` if all registers |
| 165 | 159 | /// are allocated. |
| 166 | /// | |
| 167 | /// Exceptions are deprecated, use freezeRegs and unfreezeRegs | |
| 168 | /// instead. | |
| 169 | pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, exceptions: []const Register) ?Register { | |
| 170 | return if (tryAllocRegs(self, 1, .{inst}, exceptions)) |regs| regs[0] else null; | |
| 160 | pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index) ?Register { | |
| 161 | return if (tryAllocRegs(self, 1, .{inst})) |regs| regs[0] else null; | |
| 171 | 162 | } |
| 172 | 163 | |
| 173 | 164 | /// Allocates a specified number of registers, optionally |
| 174 | /// tracking them. Asserts that count + exceptions.len is not | |
| 165 | /// tracking them. Asserts that count is not | |
| 175 | 166 | /// larger than the total number of registers available. |
| 176 | /// | |
| 177 | /// Exceptions are deprecated, use freezeRegs and unfreezeRegs | |
| 178 | /// instead. | |
| 179 | 167 | pub fn allocRegs( |
| 180 | 168 | self: *Self, |
| 181 | 169 | comptime count: comptime_int, |
| 182 | 170 | insts: [count]?Air.Inst.Index, |
| 183 | exceptions: []const Register, | |
| 184 | 171 | ) ![count]Register { |
| 185 | 172 | comptime assert(count > 0 and count <= callee_preserved_regs.len); |
| 186 | assert(count + exceptions.len <= callee_preserved_regs.len); | |
| 187 | 173 | |
| 188 | const result = self.tryAllocRegs(count, insts, exceptions) orelse blk: { | |
| 174 | const result = self.tryAllocRegs(count, insts) orelse blk: { | |
| 189 | 175 | // We'll take over the first count registers. Spill |
| 190 | 176 | // the instructions that were previously there to a |
| 191 | 177 | // stack allocations. |
| ... | ... | @@ -193,7 +179,6 @@ pub fn RegisterManager( |
| 193 | 179 | var i: usize = 0; |
| 194 | 180 | for (callee_preserved_regs) |reg| { |
| 195 | 181 | if (i >= count) break; |
| 196 | if (mem.indexOfScalar(Register, exceptions, reg) != null) continue; | |
| 197 | 182 | if (self.isRegFrozen(reg)) continue; |
| 198 | 183 | |
| 199 | 184 | regs[i] = reg; |
| ... | ... | @@ -229,11 +214,8 @@ pub fn RegisterManager( |
| 229 | 214 | |
| 230 | 215 | /// Allocates a register and optionally tracks it with a |
| 231 | 216 | /// corresponding instruction. |
| 232 | /// | |
| 233 | /// Exceptions are deprecated, use freezeRegs and unfreezeRegs | |
| 234 | /// instead. | |
| 235 | pub fn allocReg(self: *Self, inst: ?Air.Inst.Index, exceptions: []const Register) !Register { | |
| 236 | return (try self.allocRegs(1, .{inst}, exceptions))[0]; | |
| 217 | pub fn allocReg(self: *Self, inst: ?Air.Inst.Index) !Register { | |
| 218 | return (try self.allocRegs(1, .{inst}))[0]; | |
| 237 | 219 | } |
| 238 | 220 | |
| 239 | 221 | /// Spills the register if it is currently allocated. If a |
| ... | ... | @@ -365,9 +347,9 @@ test "tryAllocReg: no spilling" { |
| 365 | 347 | |
| 366 | 348 | const mock_instruction: Air.Inst.Index = 1; |
| 367 | 349 | |
| 368 | try expectEqual(@as(?MockRegister1, .r2), function.register_manager.tryAllocReg(mock_instruction, &.{})); | |
| 369 | try expectEqual(@as(?MockRegister1, .r3), function.register_manager.tryAllocReg(mock_instruction, &.{})); | |
| 370 | try expectEqual(@as(?MockRegister1, null), function.register_manager.tryAllocReg(mock_instruction, &.{})); | |
| 350 | try expectEqual(@as(?MockRegister1, .r2), function.register_manager.tryAllocReg(mock_instruction)); | |
| 351 | try expectEqual(@as(?MockRegister1, .r3), function.register_manager.tryAllocReg(mock_instruction)); | |
| 352 | try expectEqual(@as(?MockRegister1, null), function.register_manager.tryAllocReg(mock_instruction)); | |
| 371 | 353 | |
| 372 | 354 | try expect(function.register_manager.isRegAllocated(.r2)); |
| 373 | 355 | try expect(function.register_manager.isRegAllocated(.r3)); |
| ... | ... | @@ -393,33 +375,25 @@ test "allocReg: spilling" { |
| 393 | 375 | |
| 394 | 376 | const mock_instruction: Air.Inst.Index = 1; |
| 395 | 377 | |
| 396 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(mock_instruction, &.{})); | |
| 397 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction, &.{})); | |
| 378 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(mock_instruction)); | |
| 379 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction)); | |
| 398 | 380 | |
| 399 | 381 | // Spill a register |
| 400 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(mock_instruction, &.{})); | |
| 382 | try expectEqual(@as(?MockRegister1, .r2), try function.register_manager.allocReg(mock_instruction)); | |
| 401 | 383 | try expectEqualSlices(MockRegister1, &[_]MockRegister1{.r2}, function.spilled.items); |
| 402 | 384 | |
| 403 | 385 | // No spilling necessary |
| 404 | 386 | function.register_manager.freeReg(.r3); |
| 405 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction, &.{})); | |
| 387 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction)); | |
| 406 | 388 | try expectEqualSlices(MockRegister1, &[_]MockRegister1{.r2}, function.spilled.items); |
| 407 | 389 | |
| 408 | // Exceptions | |
| 409 | // | |
| 410 | // TODO deprecated, remove test once no backend uses exceptions | |
| 411 | // anymore | |
| 412 | function.register_manager.freeReg(.r2); | |
| 413 | function.register_manager.freeReg(.r3); | |
| 414 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction, &.{.r2})); | |
| 415 | ||
| 416 | 390 | // Frozen registers |
| 417 | 391 | function.register_manager.freeReg(.r3); |
| 418 | 392 | { |
| 419 | 393 | function.register_manager.freezeRegs(&.{.r2}); |
| 420 | 394 | defer function.register_manager.unfreezeRegs(&.{.r2}); |
| 421 | 395 | |
| 422 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction, &.{})); | |
| 396 | try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction)); | |
| 423 | 397 | } |
| 424 | 398 | try expect(!function.register_manager.frozenRegsExist()); |
| 425 | 399 | } |
| ... | ... | @@ -432,22 +406,13 @@ test "tryAllocRegs" { |
| 432 | 406 | }; |
| 433 | 407 | defer function.deinit(); |
| 434 | 408 | |
| 435 | try expectEqual([_]MockRegister2{ .r0, .r1, .r2 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{}).?); | |
| 409 | try expectEqual([_]MockRegister2{ .r0, .r1, .r2 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }).?); | |
| 436 | 410 | |
| 437 | 411 | try expect(function.register_manager.isRegAllocated(.r0)); |
| 438 | 412 | try expect(function.register_manager.isRegAllocated(.r1)); |
| 439 | 413 | try expect(function.register_manager.isRegAllocated(.r2)); |
| 440 | 414 | try expect(!function.register_manager.isRegAllocated(.r3)); |
| 441 | 415 | |
| 442 | // Exceptions | |
| 443 | // | |
| 444 | // TODO deprecated, remove test once no backend uses exceptions | |
| 445 | // anymore | |
| 446 | function.register_manager.freeReg(.r0); | |
| 447 | function.register_manager.freeReg(.r1); | |
| 448 | function.register_manager.freeReg(.r2); | |
| 449 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{.r1}).?); | |
| 450 | ||
| 451 | 416 | // Frozen registers |
| 452 | 417 | function.register_manager.freeReg(.r0); |
| 453 | 418 | function.register_manager.freeReg(.r2); |
| ... | ... | @@ -456,7 +421,7 @@ test "tryAllocRegs" { |
| 456 | 421 | function.register_manager.freezeRegs(&.{.r1}); |
| 457 | 422 | defer function.register_manager.unfreezeRegs(&.{.r1}); |
| 458 | 423 | |
| 459 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{}).?); | |
| 424 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }).?); | |
| 460 | 425 | } |
| 461 | 426 | try expect(!function.register_manager.frozenRegsExist()); |
| 462 | 427 | |
| ... | ... | @@ -480,20 +445,13 @@ test "allocRegs" { |
| 480 | 445 | mock_instruction, |
| 481 | 446 | mock_instruction, |
| 482 | 447 | mock_instruction, |
| 483 | }, &.{})); | |
| 448 | })); | |
| 484 | 449 | |
| 485 | 450 | try expect(function.register_manager.isRegAllocated(.r0)); |
| 486 | 451 | try expect(function.register_manager.isRegAllocated(.r1)); |
| 487 | 452 | try expect(function.register_manager.isRegAllocated(.r2)); |
| 488 | 453 | try expect(!function.register_manager.isRegAllocated(.r3)); |
| 489 | 454 | |
| 490 | // Exceptions | |
| 491 | // | |
| 492 | // TODO deprecated, remove test once no backend uses exceptions | |
| 493 | // anymore | |
| 494 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, try function.register_manager.allocRegs(3, .{ null, null, null }, &.{.r1})); | |
| 495 | try expectEqualSlices(MockRegister2, &[_]MockRegister2{ .r0, .r2 }, function.spilled.items); | |
| 496 | ||
| 497 | 455 | // Frozen registers |
| 498 | 456 | function.register_manager.freeReg(.r0); |
| 499 | 457 | function.register_manager.freeReg(.r2); |
| ... | ... | @@ -502,7 +460,7 @@ test "allocRegs" { |
| 502 | 460 | function.register_manager.freezeRegs(&.{.r1}); |
| 503 | 461 | defer function.register_manager.unfreezeRegs(&.{.r1}); |
| 504 | 462 | |
| 505 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, try function.register_manager.allocRegs(3, .{ null, null, null }, &.{})); | |
| 463 | try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, try function.register_manager.allocRegs(3, .{ null, null, null })); | |
| 506 | 464 | } |
| 507 | 465 | try expect(!function.register_manager.frozenRegsExist()); |
| 508 | 466 |