stage2 regalloc: fix tryAllocRegs for specific situations

Previously, tryAllocRegs did not take frozen registers into account
when checking if enough registers are available.
This commit is contained in:
joachimschmidt557 2022-03-17 21:47:11 +01:00 committed by Jakub Konka
parent f3f5a5d05b
commit 13321c8070
2 changed files with 16 additions and 11 deletions

View File

@ -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

View File

@ -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