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