authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-04-07 15:15:14+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-04-07 15:15:14+02:00
log4ff5a3cd94b0532f2cd713082948b00a8a36336f
tree16ec4456a977fbb1e4ae91bb62bbb405487357de
parentac2211118fe9030aa8a524549c9bb7caf8795f4d
signaturelock-open Commit is signed but in an unrecognized format.

stage2 regalloc: Add unit test for getReg


2 files changed, 40 insertions(+), 5 deletions(-)

src/codegen.zig+2-1
......@@ -1735,7 +1735,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
17351735
17361736 switch (result) {
17371737 .register => |reg| {
1738 try self.register_manager.getRegAssumeFree(toCanonicalReg(reg), &inst.base);
1738 try self.register_manager.registers.ensureCapacity(self.gpa, self.register_manager.registers.count() + 1);
1739 self.register_manager.getRegAssumeFree(toCanonicalReg(reg), &inst.base);
17391740 },
17401741 else => {},
17411742 }
src/register_manager.zig+38-4
......@@ -137,6 +137,7 @@ pub fn RegisterManager(
137137 /// Allocates the specified register with the specified
138138 /// instruction. Spills the register if it is currently
139139 /// allocated.
140 /// Before calling, must ensureCapacity + 1 on self.registers.
140141 pub fn getReg(self: *Self, reg: Register, inst: *ir.Inst) !void {
141142 if (!isTracked(reg)) return;
142143
......@@ -148,7 +149,7 @@ pub fn RegisterManager(
148149 regs_entry.value = inst;
149150 try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst);
150151 } else {
151 try self.getRegAssumeFree(reg, inst);
152 self.getRegAssumeFree(reg, inst);
152153 }
153154 }
154155
......@@ -160,7 +161,7 @@ pub fn RegisterManager(
160161 if (!self.isRegFree(reg)) {
161162 // Move the instruction that was previously there to a
162163 // stack allocation.
163 const regs_entry = self.registers.getEntry(reg).?;
164 const regs_entry = self.registers.remove(reg).?;
164165 const spilled_inst = regs_entry.value;
165166 try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst);
166167 self.markRegFree(reg);
......@@ -170,10 +171,11 @@ pub fn RegisterManager(
170171 /// Allocates the specified register with the specified
171172 /// instruction. Assumes that the register is free and no
172173 /// spilling is necessary.
173 pub fn getRegAssumeFree(self: *Self, reg: Register, inst: *ir.Inst) !void {
174 /// Before calling, must ensureCapacity + 1 on self.registers.
175 pub fn getRegAssumeFree(self: *Self, reg: Register, inst: *ir.Inst) void {
174176 if (!isTracked(reg)) return;
175177
176 try self.registers.putNoClobber(self.getFunction().gpa, reg, inst);
178 self.registers.putAssumeCapacityNoClobber(reg, inst);
177179 self.markRegUsed(reg);
178180 }
179181
......@@ -279,3 +281,35 @@ test "allocReg: spilling" {
279281 std.testing.expectEqual(@as(?MockRegister, .r3), try function.register_manager.allocReg(&mock_instruction));
280282 std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r2}, function.spilled.items);
281283}
284
285test "getReg" {
286 const allocator = std.testing.allocator;
287
288 var function = MockFunction{
289 .allocator = allocator,
290 };
291 defer function.deinit();
292
293 var mock_instruction = ir.Inst{
294 .tag = .breakpoint,
295 .ty = Type.initTag(.void),
296 .src = .unneeded,
297 };
298
299 std.testing.expect(!function.register_manager.isRegAllocated(.r2));
300 std.testing.expect(!function.register_manager.isRegAllocated(.r3));
301
302 try function.register_manager.registers.ensureCapacity(allocator, function.register_manager.registers.count() + 2);
303 try function.register_manager.getReg(.r3, &mock_instruction);
304
305 std.testing.expect(!function.register_manager.isRegAllocated(.r2));
306 std.testing.expect(function.register_manager.isRegAllocated(.r3));
307
308 // Spill r3
309 try function.register_manager.registers.ensureCapacity(allocator, function.register_manager.registers.count() + 2);
310 try function.register_manager.getReg(.r3, &mock_instruction);
311
312 std.testing.expect(!function.register_manager.isRegAllocated(.r2));
313 std.testing.expect(function.register_manager.isRegAllocated(.r3));
314 std.testing.expectEqualSlices(MockRegister, &[_]MockRegister{.r3}, function.spilled.items);
315}