authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-01-28 20:40:36+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-28 18:03:03-05:00
log1a324a8ad603853728e3a052ec82756c9128cb0c
treea2f77316e1c3d799ef95839299be944eed7c5713
parentd7deffee8d1861720ba4f9d3cb6a7f6dfb7ccb33

stage2 regalloc: Fix bug where regs were not marked as allocated


1 files changed, 44 insertions(+), 14 deletions(-)

src/register_manager.zig+44-14
......@@ -17,6 +17,10 @@ pub fn RegisterManager(
1717 comptime Register: type,
1818 comptime callee_preserved_regs: []const Register,
1919) type {
20 // architectures which do not have a concept of registers should
21 // refrain from using RegisterManager
22 assert(callee_preserved_regs.len > 0); // see note above
23
2024 return struct {
2125 /// Tracks the AIR instruction allocated to every register or
2226 /// `null` if no instruction is allocated to a register
......@@ -45,17 +49,20 @@ pub fn RegisterManager(
4549 }
4650
4751 fn getRegisterMask(reg: Register) ?FreeRegInt {
48 if (FreeRegInt == u0) return null;
4952 const index = reg.allocIndex() orelse return null;
5053 const shift = @intCast(ShiftInt, index);
5154 const mask = @as(FreeRegInt, 1) << shift;
5255 return mask;
5356 }
5457
58 fn markRegAllocated(self: *Self, reg: Register) void {
59 const mask = getRegisterMask(reg) orelse return;
60 self.allocated_registers |= mask;
61 }
62
5563 fn markRegUsed(self: *Self, reg: Register) void {
5664 const mask = getRegisterMask(reg) orelse return;
5765 self.free_registers &= ~mask;
58 self.allocated_registers |= mask;
5966 }
6067
6168 fn markRegFree(self: *Self, reg: Register) void {
......@@ -120,7 +127,6 @@ pub fn RegisterManager(
120127 insts: [count]?Air.Inst.Index,
121128 exceptions: []const Register,
122129 ) ?[count]Register {
123 comptime if (callee_preserved_regs.len == 0) return null;
124130 comptime assert(count > 0 and count <= callee_preserved_regs.len);
125131 assert(count + exceptions.len <= callee_preserved_regs.len);
126132
......@@ -138,19 +144,20 @@ pub fn RegisterManager(
138144 i += 1;
139145 }
140146 }
147 assert(i == count);
141148
142 if (i == count) {
143 for (regs) |reg, j| {
144 if (insts[j]) |inst| {
145 // Track the register
146 const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null
147 self.registers[index] = inst;
148 self.markRegUsed(reg);
149 }
149 for (regs) |reg, j| {
150 self.markRegAllocated(reg);
151
152 if (insts[j]) |inst| {
153 // Track the register
154 const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null
155 self.registers[index] = inst;
156 self.markRegUsed(reg);
150157 }
158 }
151159
152 return regs;
153 } else return null;
160 return regs;
154161 }
155162
156163 /// Allocates a register and optionally tracks it with a
......@@ -188,8 +195,9 @@ pub fn RegisterManager(
188195 if (i >= count) break;
189196 if (mem.indexOfScalar(Register, exceptions, reg) != null) continue;
190197 if (self.isRegFrozen(reg)) continue;
191 regs[i] = reg;
192198
199 regs[i] = reg;
200 self.markRegAllocated(reg);
193201 const index = reg.allocIndex().?; // allocIndex() on a callee-preserved reg should never return null
194202 if (insts[i]) |inst| {
195203 // Track the register
......@@ -233,6 +241,7 @@ pub fn RegisterManager(
233241 /// register.
234242 pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) !void {
235243 const index = reg.allocIndex() orelse return;
244 self.markRegAllocated(reg);
236245
237246 if (inst) |tracked_inst|
238247 if (!self.isRegFree(reg)) {
......@@ -260,6 +269,7 @@ pub fn RegisterManager(
260269 /// spilling is necessary.
261270 pub fn getRegAssumeFree(self: *Self, reg: Register, inst: Air.Inst.Index) void {
262271 const index = reg.allocIndex() orelse return;
272 self.markRegAllocated(reg);
263273
264274 assert(self.registers[index] == null);
265275 self.registers[index] = inst;
......@@ -424,6 +434,11 @@ test "tryAllocRegs" {
424434
425435 try expectEqual([_]MockRegister2{ .r0, .r1, .r2 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{}).?);
426436
437 try expect(function.register_manager.isRegAllocated(.r0));
438 try expect(function.register_manager.isRegAllocated(.r1));
439 try expect(function.register_manager.isRegAllocated(.r2));
440 try expect(!function.register_manager.isRegAllocated(.r3));
441
427442 // Exceptions
428443 //
429444 // TODO deprecated, remove test once no backend uses exceptions
......@@ -444,6 +459,11 @@ test "tryAllocRegs" {
444459 try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }, &.{}).?);
445460 }
446461 try expect(!function.register_manager.frozenRegsExist());
462
463 try expect(function.register_manager.isRegAllocated(.r0));
464 try expect(function.register_manager.isRegAllocated(.r1));
465 try expect(function.register_manager.isRegAllocated(.r2));
466 try expect(function.register_manager.isRegAllocated(.r3));
447467}
448468
449469test "allocRegs" {
......@@ -462,6 +482,11 @@ test "allocRegs" {
462482 mock_instruction,
463483 }, &.{}));
464484
485 try expect(function.register_manager.isRegAllocated(.r0));
486 try expect(function.register_manager.isRegAllocated(.r1));
487 try expect(function.register_manager.isRegAllocated(.r2));
488 try expect(!function.register_manager.isRegAllocated(.r3));
489
465490 // Exceptions
466491 //
467492 // TODO deprecated, remove test once no backend uses exceptions
......@@ -480,6 +505,11 @@ test "allocRegs" {
480505 try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, try function.register_manager.allocRegs(3, .{ null, null, null }, &.{}));
481506 }
482507 try expect(!function.register_manager.frozenRegsExist());
508
509 try expect(function.register_manager.isRegAllocated(.r0));
510 try expect(function.register_manager.isRegAllocated(.r1));
511 try expect(function.register_manager.isRegAllocated(.r2));
512 try expect(function.register_manager.isRegAllocated(.r3));
483513}
484514
485515test "getReg" {