authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-17 21:47:11+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-18 19:37:01+01:00
log13321c8070b52afb24f3c1b57eecbb2aa77fc4ec
tree8e1993c92445c3ecb25b44d3a94d469c56157126
parentf3f5a5d05b7056aceb408b701613242d053019ab

stage2 regalloc: fix tryAllocRegs for specific situations

Previously, tryAllocRegs did not take frozen registers into account when checking if enough registers are available.

2 files changed, 16 insertions(+), 11 deletions(-)

src/arch/aarch64/CodeGen.zig+7-4
......@@ -2648,16 +2648,19 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
26482648 if (rhs_should_be_register) {
26492649 if (!lhs_is_register and !rhs_is_register) {
26502650 const regs = try self.register_manager.allocRegs(2, .{
2651 Air.refToIndex(bin_op.rhs).?, Air.refToIndex(bin_op.lhs).?,
2651 Air.refToIndex(bin_op.lhs).?, Air.refToIndex(bin_op.rhs).?,
26522652 });
26532653 lhs_mcv = MCValue{ .register = regs[0] };
26542654 rhs_mcv = MCValue{ .register = regs[1] };
26552655 } else if (!rhs_is_register) {
26562656 rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.rhs).?) };
2657 } else if (!lhs_is_register) {
2658 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?) };
2659 }
2660 } else {
2661 if (!lhs_is_register) {
2662 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?) };
26572663 }
2658 }
2659 if (!lhs_is_register) {
2660 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?) };
26612664 }
26622665
26632666 // Move the operands to the newly allocated registers
src/register_manager.zig+9-7
......@@ -148,18 +148,19 @@ pub fn RegisterManager(
148148 ) ?[count]Register {
149149 comptime assert(count > 0 and count <= tracked_registers.len);
150150
151 const free_registers = @popCount(FreeRegInt, self.free_registers);
152 if (free_registers < count) return null;
151 const free_and_not_frozen_registers = self.free_registers & ~self.frozen_registers;
152 const free_and_not_frozen_registers_count = @popCount(FreeRegInt, free_and_not_frozen_registers);
153 if (free_and_not_frozen_registers_count < count) return null;
153154
154155 var regs: [count]Register = undefined;
155156 var i: usize = 0;
156157 for (tracked_registers) |reg| {
157158 if (i >= count) break;
158159 if (self.isRegFrozen(reg)) continue;
159 if (self.isRegFree(reg)) {
160 regs[i] = reg;
161 i += 1;
162 }
160 if (!self.isRegFree(reg)) continue;
161
162 regs[i] = reg;
163 i += 1;
163164 }
164165 assert(i == count);
165166
......@@ -193,7 +194,8 @@ pub fn RegisterManager(
193194 insts: [count]?Air.Inst.Index,
194195 ) AllocateRegistersError![count]Register {
195196 comptime assert(count > 0 and count <= tracked_registers.len);
196 if (count > tracked_registers.len - @popCount(FreeRegInt, self.frozen_registers)) return error.OutOfRegisters;
197 const frozen_registers_count = @popCount(FreeRegInt, self.frozen_registers);
198 if (count > tracked_registers.len - frozen_registers_count) return error.OutOfRegisters;
197199
198200 const result = self.tryAllocRegs(count, insts) orelse blk: {
199201 // We'll take over the first count registers. Spill