Commit 13321c8070

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-03-17 21:47:11
stage2 regalloc: fix tryAllocRegs for specific situations
Previously, tryAllocRegs did not take frozen registers into account when checking if enough registers are available.
1 parent f3f5a5d
Changed files (2)
src/arch/aarch64/CodeGen.zig
@@ -2648,16 +2648,19 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
         if (rhs_should_be_register) {
             if (!lhs_is_register and !rhs_is_register) {
                 const regs = try self.register_manager.allocRegs(2, .{
-                    Air.refToIndex(bin_op.rhs).?, Air.refToIndex(bin_op.lhs).?,
+                    Air.refToIndex(bin_op.lhs).?, Air.refToIndex(bin_op.rhs).?,
                 });
                 lhs_mcv = MCValue{ .register = regs[0] };
                 rhs_mcv = MCValue{ .register = regs[1] };
             } else if (!rhs_is_register) {
                 rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.rhs).?) };
+            } else if (!lhs_is_register) {
+                lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?) };
+            }
+        } else {
+            if (!lhs_is_register) {
+                lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?) };
             }
-        }
-        if (!lhs_is_register) {
-            lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?) };
         }
 
         // Move the operands to the newly allocated registers
src/register_manager.zig
@@ -148,18 +148,19 @@ pub fn RegisterManager(
         ) ?[count]Register {
             comptime assert(count > 0 and count <= tracked_registers.len);
 
-            const free_registers = @popCount(FreeRegInt, self.free_registers);
-            if (free_registers < count) return null;
+            const free_and_not_frozen_registers = self.free_registers & ~self.frozen_registers;
+            const free_and_not_frozen_registers_count = @popCount(FreeRegInt, free_and_not_frozen_registers);
+            if (free_and_not_frozen_registers_count < count) return null;
 
             var regs: [count]Register = undefined;
             var i: usize = 0;
             for (tracked_registers) |reg| {
                 if (i >= count) break;
                 if (self.isRegFrozen(reg)) continue;
-                if (self.isRegFree(reg)) {
-                    regs[i] = reg;
-                    i += 1;
-                }
+                if (!self.isRegFree(reg)) continue;
+
+                regs[i] = reg;
+                i += 1;
             }
             assert(i == count);
 
@@ -193,7 +194,8 @@ pub fn RegisterManager(
             insts: [count]?Air.Inst.Index,
         ) AllocateRegistersError![count]Register {
             comptime assert(count > 0 and count <= tracked_registers.len);
-            if (count > tracked_registers.len - @popCount(FreeRegInt, self.frozen_registers)) return error.OutOfRegisters;
+            const frozen_registers_count = @popCount(FreeRegInt, self.frozen_registers);
+            if (count > tracked_registers.len - frozen_registers_count) return error.OutOfRegisters;
 
             const result = self.tryAllocRegs(count, insts) orelse blk: {
                 // We'll take over the first count registers. Spill