authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-26 09:06:42+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-26 12:05:51+02:00
log0e0b00fd48ea680f2d69207297e877f54dd9ec89
tree9baa6bd9110641ce42d4e02bbd1d054f6a70dde2
parentab88165326abfd81c5046e8c064bd6603198ed94

regalloc: use StaticBitSet internally


6 files changed, 121 insertions(+), 442 deletions(-)

src/arch/aarch64/abi.zig+8-10
......@@ -27,14 +27,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
2727// Register classes
2828const RegisterBitSet = RegisterManager.RegisterBitSet;
2929pub const RegisterClass = struct {
30 pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
31 // TODO uncomment once #11680 is fixed.
32 // pub const gp: RegisterBitSet = blk: {
33 // var set = RegisterBitSet.initEmpty();
34 // set.setRangeValue(.{
35 // .start = 0,
36 // .end = callee_preserved_regs.len,
37 // }, true);
38 // break :blk set;
39 // };
30 pub const gp: RegisterBitSet = blk: {
31 var set = RegisterBitSet.initEmpty();
32 set.setRangeValue(.{
33 .start = 0,
34 .end = callee_preserved_regs.len,
35 }, true);
36 break :blk set;
37 };
4038};
src/arch/arm/abi.zig+8-10
......@@ -15,14 +15,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
1515// Register classes
1616const RegisterBitSet = RegisterManager.RegisterBitSet;
1717pub const RegisterClass = struct {
18 pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
19 // TODO uncomment once #11680 is fixed.
20 // pub const gp: RegisterBitSet = blk: {
21 // var set = RegisterBitSet.initEmpty();
22 // set.setRangeValue(.{
23 // .start = 0,
24 // .end = caller_preserved_regs.len + callee_preserved_regs.len,
25 // }, true);
26 // break :blk set;
27 // };
18 pub const gp: RegisterBitSet = blk: {
19 var set = RegisterBitSet.initEmpty();
20 set.setRangeValue(.{
21 .start = 0,
22 .end = caller_preserved_regs.len + callee_preserved_regs.len,
23 }, true);
24 break :blk set;
25 };
2826};
src/arch/riscv64/abi.zig+8-10
......@@ -13,14 +13,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
1313// Register classes
1414const RegisterBitSet = RegisterManager.RegisterBitSet;
1515pub const RegisterClass = struct {
16 pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
17 // TODO uncomment once #11680 is fixed.
18 // pub const gp: RegisterBitSet = blk: {
19 // var set = RegisterBitSet.initEmpty();
20 // set.setRangeValue(.{
21 // .start = 0,
22 // .end = callee_preserved_regs.len,
23 // }, true);
24 // break :blk set;
25 // };
16 pub const gp: RegisterBitSet = blk: {
17 var set = RegisterBitSet.initEmpty();
18 set.setRangeValue(.{
19 .start = 0,
20 .end = callee_preserved_regs.len,
21 }, true);
22 break :blk set;
23 };
2624};
src/arch/sparc64/abi.zig+8-10
......@@ -43,14 +43,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
4343// Register classes
4444const RegisterBitSet = RegisterManager.RegisterBitSet;
4545pub const RegisterClass = struct {
46 pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
47 // TODO uncomment once #11680 is fixed.
48 // pub const gp: RegisterBitSet = blk: {
49 // var set = RegisterBitSet.initEmpty();
50 // set.setRangeValue(.{
51 // .start = 0,
52 // .end = allocatable_regs.len,
53 // }, true);
54 // break :blk set;
55 // };
46 pub const gp: RegisterBitSet = blk: {
47 var set = RegisterBitSet.initEmpty();
48 set.setRangeValue(.{
49 .start = 0,
50 .end = allocatable_regs.len,
51 }, true);
52 break :blk set;
53 };
5654};
src/arch/x86_64/abi.zig+16-22
......@@ -393,26 +393,20 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
393393// Register classes
394394const RegisterBitSet = RegisterManager.RegisterBitSet;
395395pub const RegisterClass = struct {
396 pub const gp: RegisterBitSet = @as(RegisterBitSet, std.math.maxInt(std.meta.Int(
397 .unsigned,
398 caller_preserved_regs.len + callee_preserved_regs.len,
399 )));
400 pub const sse: RegisterBitSet = std.math.maxInt(RegisterBitSet) - gp;
401 // TODO uncomment once #11680 is fixed.
402 // pub const gp: RegisterBitSet = blk: {
403 // var set = RegisterBitSet.initEmpty();
404 // set.setRangeValue(.{
405 // .start = 0,
406 // .end = caller_preserved_regs.len + callee_preserved_regs.len,
407 // }, true);
408 // break :blk set;
409 // };
410 // pub const sse: RegisterBitSet = blk: {
411 // var set = RegisterBitSet.initEmpty();
412 // set.setRangeValue(.{
413 // .start = caller_preserved_regs.len + callee_preserved_regs.len,
414 // .end = allocatable_registers.len,
415 // }, true);
416 // break :blk set;
417 // };
396 pub const gp: RegisterBitSet = blk: {
397 var set = RegisterBitSet.initEmpty();
398 set.setRangeValue(.{
399 .start = 0,
400 .end = caller_preserved_regs.len + callee_preserved_regs.len,
401 }, true);
402 break :blk set;
403 };
404 pub const sse: RegisterBitSet = blk: {
405 var set = RegisterBitSet.initEmpty();
406 set.setRangeValue(.{
407 .start = caller_preserved_regs.len + callee_preserved_regs.len,
408 .end = allocatable_registers.len,
409 }, true);
410 break :blk set;
411 };
418412};
src/register_manager.zig+73-380
......@@ -4,6 +4,7 @@ const mem = std.mem;
44const assert = std.debug.assert;
55const Allocator = std.mem.Allocator;
66const Air = @import("Air.zig");
7const StaticBitSet = std.bit_set.StaticBitSet;
78const Type = @import("type.zig").Type;
89const Module = @import("Module.zig");
910const expect = std.testing.expect;
......@@ -41,49 +42,39 @@ pub fn RegisterManager(
4142 registers: [tracked_registers.len]Air.Inst.Index = undefined,
4243 /// Tracks which registers are free (in which case the
4344 /// corresponding bit is set to 1)
44 free_registers: RegisterBitSet = math.maxInt(RegisterBitSet),
45 free_registers: RegisterBitSet = RegisterBitSet.initFull(),
4546 /// Tracks all registers allocated in the course of this
4647 /// function
47 allocated_registers: RegisterBitSet = 0,
48 allocated_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
4849 /// Tracks registers which are locked from being allocated
49 locked_registers: RegisterBitSet = 0,
50 locked_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
5051
5152 const Self = @This();
5253
53 /// An integer whose bits represent all the registers and
54 /// whether they are free.
55 pub const RegisterBitSet = std.meta.Int(.unsigned, tracked_registers.len);
56 const ShiftInt = math.Log2Int(RegisterBitSet);
54 pub const RegisterBitSet = StaticBitSet(tracked_registers.len);
5755
5856 fn getFunction(self: *Self) *Function {
5957 return @fieldParentPtr(Function, "register_manager", self);
6058 }
6159
6260 fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool {
63 const mask = getRegisterMask(reg) orelse return true;
64 return mask & register_class == 0;
65 }
66
67 fn getRegisterMask(reg: Register) ?RegisterBitSet {
68 const index = indexOfRegIntoTracked(reg) orelse return null;
69 const shift = @intCast(ShiftInt, index);
70 const mask = @as(RegisterBitSet, 1) << shift;
71 return mask;
61 const index = indexOfRegIntoTracked(reg) orelse return true;
62 return !register_class.isSet(index);
7263 }
7364
7465 fn markRegAllocated(self: *Self, reg: Register) void {
75 const mask = getRegisterMask(reg) orelse return;
76 self.allocated_registers |= mask;
66 const index = indexOfRegIntoTracked(reg) orelse return;
67 self.allocated_registers.set(index);
7768 }
7869
7970 fn markRegUsed(self: *Self, reg: Register) void {
80 const mask = getRegisterMask(reg) orelse return;
81 self.free_registers &= ~mask;
71 const index = indexOfRegIntoTracked(reg) orelse return;
72 self.free_registers.unset(index);
8273 }
8374
8475 fn markRegFree(self: *Self, reg: Register) void {
85 const mask = getRegisterMask(reg) orelse return;
86 self.free_registers |= mask;
76 const index = indexOfRegIntoTracked(reg) orelse return;
77 self.free_registers.set(index);
8778 }
8879
8980 pub fn indexOfReg(
......@@ -96,14 +87,14 @@ pub fn RegisterManager(
9687 return null;
9788 }
9889
99 pub fn indexOfRegIntoTracked(reg: Register) ?ShiftInt {
90 pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt {
10091 return indexOfReg(tracked_registers, reg);
10192 }
10293
10394 /// Returns true when this register is not tracked
10495 pub fn isRegFree(self: Self, reg: Register) bool {
105 const mask = getRegisterMask(reg) orelse return true;
106 return self.free_registers & mask != 0;
96 const index = indexOfRegIntoTracked(reg) orelse return true;
97 return self.free_registers.isSet(index);
10798 }
10899
109100 /// Returns whether this register was allocated in the course
......@@ -111,16 +102,16 @@ pub fn RegisterManager(
111102 ///
112103 /// Returns false when this register is not tracked
113104 pub fn isRegAllocated(self: Self, reg: Register) bool {
114 const mask = getRegisterMask(reg) orelse return false;
115 return self.allocated_registers & mask != 0;
105 const index = indexOfRegIntoTracked(reg) orelse return false;
106 return self.allocated_registers.isSet(index);
116107 }
117108
118109 /// Returns whether this register is locked
119110 ///
120111 /// Returns false when this register is not tracked
121112 pub fn isRegLocked(self: Self, reg: Register) bool {
122 const mask = getRegisterMask(reg) orelse return false;
123 return self.locked_registers & mask != 0;
113 const index = indexOfRegIntoTracked(reg) orelse return false;
114 return self.locked_registers.isSet(index);
124115 }
125116
126117 pub const RegisterLock = struct {
......@@ -139,8 +130,8 @@ pub fn RegisterManager(
139130 log.debug(" register already locked", .{});
140131 return null;
141132 }
142 const mask = getRegisterMask(reg) orelse return null;
143 self.locked_registers |= mask;
133 const index = indexOfRegIntoTracked(reg) orelse return null;
134 self.locked_registers.set(index);
144135 return RegisterLock{ .register = reg };
145136 }
146137
......@@ -149,8 +140,8 @@ pub fn RegisterManager(
149140 pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
150141 log.debug("locking asserting free {}", .{reg});
151142 assert(!self.isRegLocked(reg));
152 const mask = getRegisterMask(reg) orelse unreachable;
153 self.locked_registers |= mask;
143 const index = indexOfRegIntoTracked(reg) orelse unreachable;
144 self.locked_registers.set(index);
154145 return RegisterLock{ .register = reg };
155146 }
156147
......@@ -172,13 +163,13 @@ pub fn RegisterManager(
172163 /// Call `lockReg` to obtain the lock first.
173164 pub fn unlockReg(self: *Self, lock: RegisterLock) void {
174165 log.debug("unlocking {}", .{lock.register});
175 const mask = getRegisterMask(lock.register) orelse return;
176 self.locked_registers &= ~mask;
166 const index = indexOfRegIntoTracked(lock.register) orelse return;
167 self.locked_registers.unset(index);
177168 }
178169
179170 /// Returns true when at least one register is locked
180171 pub fn lockedRegsExist(self: Self) bool {
181 return self.locked_registers != 0;
172 return self.locked_registers.count() > 0;
182173 }
183174
184175 /// Allocates a specified number of registers, optionally
......@@ -192,10 +183,15 @@ pub fn RegisterManager(
192183 ) ?[count]Register {
193184 comptime assert(count > 0 and count <= tracked_registers.len);
194185
195 const free_registers = self.free_registers & register_class;
196 const free_and_not_locked_registers = free_registers & ~self.locked_registers;
197 const free_and_not_locked_registers_count = @popCount(RegisterBitSet, free_and_not_locked_registers);
198 if (free_and_not_locked_registers_count < count) return null;
186 var free_and_not_locked_registers = self.free_registers;
187 free_and_not_locked_registers.setIntersection(register_class);
188
189 var unlocked_registers = self.locked_registers;
190 unlocked_registers.toggleAll();
191
192 free_and_not_locked_registers.setIntersection(unlocked_registers);
193
194 if (free_and_not_locked_registers.count() < count) return null;
199195
200196 var regs: [count]Register = undefined;
201197 var i: usize = 0;
......@@ -242,10 +238,10 @@ pub fn RegisterManager(
242238 ) AllocateRegistersError![count]Register {
243239 comptime assert(count > 0 and count <= tracked_registers.len);
244240
245 const available_registers_count = @popCount(RegisterBitSet, register_class);
246 const locked_registers = self.locked_registers & register_class;
247 const locked_registers_count = @popCount(RegisterBitSet, locked_registers);
248 if (count > available_registers_count - locked_registers_count) return error.OutOfRegisters;
241 var locked_registers = self.locked_registers;
242 locked_registers.setIntersection(register_class);
243
244 if (count > register_class.count() - locked_registers.count()) return error.OutOfRegisters;
249245
250246 const result = self.tryAllocRegs(count, insts, register_class) orelse blk: {
251247 // We'll take over the first count registers. Spill
......@@ -255,7 +251,7 @@ pub fn RegisterManager(
255251 var i: usize = 0;
256252 for (tracked_registers) |reg| {
257253 if (i >= count) break;
258 if (excludeRegister(reg, register_class)) continue;
254 if (excludeRegister(reg, register_class)) break;
259255 if (self.isRegLocked(reg)) continue;
260256
261257 regs[i] = reg;
......@@ -352,334 +348,6 @@ pub fn RegisterManager(
352348 };
353349}
354350
355// TODO delete current implementation of RegisterManager above, and uncomment the one
356// below once #11680 is fixed:
357// https://github.com/ziglang/zig/issues/11680
358
359//pub fn RegisterManager(
360// comptime Function: type,
361// comptime Register: type,
362// comptime tracked_registers: []const Register,
363//) type {
364// // architectures which do not have a concept of registers should
365// // refrain from using RegisterManager
366// assert(tracked_registers.len > 0); // see note above
367
368// return struct {
369// /// Tracks the AIR instruction allocated to every register. If
370// /// no instruction is allocated to a register (i.e. the
371// /// register is free), the value in that slot is undefined.
372// ///
373// /// The key must be canonical register.
374// registers: [tracked_registers.len]Air.Inst.Index = undefined,
375// /// Tracks which registers are free (in which case the
376// /// corresponding bit is set to 1)
377// free_registers: RegisterBitSet = RegisterBitSet.initFull(),
378// /// Tracks all registers allocated in the course of this
379// /// function
380// allocated_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
381// /// Tracks registers which are locked from being allocated
382// locked_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
383
384// const Self = @This();
385
386// pub const RegisterBitSet = StaticBitSet(tracked_registers.len);
387
388// fn getFunction(self: *Self) *Function {
389// return @fieldParentPtr(Function, "register_manager", self);
390// }
391
392// fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool {
393// const index = indexOfRegIntoTracked(reg) orelse return true;
394// return !register_class.isSet(index);
395// }
396
397// fn markRegAllocated(self: *Self, reg: Register) void {
398// const index = indexOfRegIntoTracked(reg) orelse return;
399// self.allocated_registers.set(index);
400// }
401
402// fn markRegUsed(self: *Self, reg: Register) void {
403// const index = indexOfRegIntoTracked(reg) orelse return;
404// self.free_registers.unset(index);
405// }
406
407// fn markRegFree(self: *Self, reg: Register) void {
408// const index = indexOfRegIntoTracked(reg) orelse return;
409// self.free_registers.set(index);
410// }
411
412// pub fn indexOfReg(
413// comptime registers: []const Register,
414// reg: Register,
415// ) ?std.math.IntFittingRange(0, registers.len - 1) {
416// inline for (tracked_registers) |cpreg, i| {
417// if (reg.id() == cpreg.id()) return i;
418// }
419// return null;
420// }
421
422// pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt {
423// return indexOfReg(tracked_registers, reg);
424// }
425
426// /// Returns true when this register is not tracked
427// pub fn isRegFree(self: Self, reg: Register) bool {
428// const index = indexOfRegIntoTracked(reg) orelse return true;
429// return self.free_registers.isSet(index);
430// }
431
432// /// Returns whether this register was allocated in the course
433// /// of this function.
434// ///
435// /// Returns false when this register is not tracked
436// pub fn isRegAllocated(self: Self, reg: Register) bool {
437// const index = indexOfRegIntoTracked(reg) orelse return false;
438// return self.allocated_registers.isSet(index);
439// }
440
441// /// Returns whether this register is locked
442// ///
443// /// Returns false when this register is not tracked
444// pub fn isRegLocked(self: Self, reg: Register) bool {
445// const index = indexOfRegIntoTracked(reg) orelse return false;
446// return self.locked_registers.isSet(index);
447// }
448
449// pub const RegisterLock = struct {
450// register: Register,
451// };
452
453// /// Prevents the register from being allocated until they are
454// /// unlocked again.
455// /// Returns `RegisterLock` if the register was not already
456// /// locked, or `null` otherwise.
457// /// Only the owner of the `RegisterLock` can unlock the
458// /// register later.
459// pub fn lockReg(self: *Self, reg: Register) ?RegisterLock {
460// log.debug("locking {}", .{reg});
461// if (self.isRegLocked(reg)) {
462// log.debug(" register already locked", .{});
463// return null;
464// }
465// const index = indexOfRegIntoTracked(reg) orelse return null;
466// self.locked_registers.set(index);
467// return RegisterLock{ .register = reg };
468// }
469
470// /// Like `lockReg` but asserts the register was unused always
471// /// returning a valid lock.
472// pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
473// log.debug("locking asserting free {}", .{reg});
474// assert(!self.isRegLocked(reg));
475// const index = indexOfRegIntoTracked(reg) orelse unreachable;
476// self.locked_registers.set(index);
477// return RegisterLock{ .register = reg };
478// }
479
480// /// Like `lockRegAssumeUnused` but locks multiple registers.
481// pub fn lockRegsAssumeUnused(
482// self: *Self,
483// comptime count: comptime_int,
484// regs: [count]Register,
485// ) [count]RegisterLock {
486// var buf: [count]RegisterLock = undefined;
487// for (regs) |reg, i| {
488// buf[i] = self.lockRegAssumeUnused(reg);
489// }
490// return buf;
491// }
492
493// /// Unlocks the register allowing its re-allocation and re-use.
494// /// Requires `RegisterLock` to unlock a register.
495// /// Call `lockReg` to obtain the lock first.
496// pub fn unlockReg(self: *Self, lock: RegisterLock) void {
497// log.debug("unlocking {}", .{lock.register});
498// const index = indexOfRegIntoTracked(lock.register) orelse return;
499// self.locked_registers.unset(index);
500// }
501
502// /// Returns true when at least one register is locked
503// pub fn lockedRegsExist(self: Self) bool {
504// return self.locked_registers.count() > 0;
505// }
506
507// /// Allocates a specified number of registers, optionally
508// /// tracking them. Returns `null` if not enough registers are
509// /// free.
510// pub fn tryAllocRegs(
511// self: *Self,
512// comptime count: comptime_int,
513// insts: [count]?Air.Inst.Index,
514// register_class: RegisterBitSet,
515// ) ?[count]Register {
516// comptime assert(count > 0 and count <= tracked_registers.len);
517
518// var free_and_not_locked_registers = self.free_registers;
519// free_and_not_locked_registers.setIntersection(register_class);
520
521// var unlocked_registers = self.locked_registers;
522// unlocked_registers.toggleAll();
523
524// free_and_not_locked_registers.setIntersection(unlocked_registers);
525
526// if (free_and_not_locked_registers.count() < count) return null;
527
528// var regs: [count]Register = undefined;
529// var i: usize = 0;
530// for (tracked_registers) |reg| {
531// if (i >= count) break;
532// if (excludeRegister(reg, register_class)) continue;
533// if (self.isRegLocked(reg)) continue;
534// if (!self.isRegFree(reg)) continue;
535
536// regs[i] = reg;
537// i += 1;
538// }
539// assert(i == count);
540
541// for (regs) |reg, j| {
542// self.markRegAllocated(reg);
543
544// if (insts[j]) |inst| {
545// // Track the register
546// const index = indexOfRegIntoTracked(reg).?; // indexOfReg() on a callee-preserved reg should never return null
547// self.registers[index] = inst;
548// self.markRegUsed(reg);
549// }
550// }
551
552// return regs;
553// }
554
555// /// Allocates a register and optionally tracks it with a
556// /// corresponding instruction. Returns `null` if all registers
557// /// are allocated.
558// pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, register_class: RegisterBitSet) ?Register {
559// return if (tryAllocRegs(self, 1, .{inst}, register_class)) |regs| regs[0] else null;
560// }
561
562// /// Allocates a specified number of registers, optionally
563// /// tracking them. Asserts that count is not
564// /// larger than the total number of registers available.
565// pub fn allocRegs(
566// self: *Self,
567// comptime count: comptime_int,
568// insts: [count]?Air.Inst.Index,
569// register_class: RegisterBitSet,
570// ) AllocateRegistersError![count]Register {
571// comptime assert(count > 0 and count <= tracked_registers.len);
572
573// var locked_registers = self.locked_registers;
574// locked_registers.setIntersection(register_class);
575
576// if (count > register_class.count() - locked_registers.count()) return error.OutOfRegisters;
577
578// const result = self.tryAllocRegs(count, insts, register_class) orelse blk: {
579// // We'll take over the first count registers. Spill
580// // the instructions that were previously there to a
581// // stack allocations.
582// var regs: [count]Register = undefined;
583// var i: usize = 0;
584// for (tracked_registers) |reg| {
585// if (i >= count) break;
586// if (excludeRegister(reg, register_class)) break;
587// if (self.isRegLocked(reg)) continue;
588
589// regs[i] = reg;
590// self.markRegAllocated(reg);
591// const index = indexOfRegIntoTracked(reg).?; // indexOfReg() on a callee-preserved reg should never return null
592// if (insts[i]) |inst| {
593// // Track the register
594// if (self.isRegFree(reg)) {
595// self.markRegUsed(reg);
596// } else {
597// const spilled_inst = self.registers[index];
598// try self.getFunction().spillInstruction(reg, spilled_inst);
599// }
600// self.registers[index] = inst;
601// } else {
602// // Don't track the register
603// if (!self.isRegFree(reg)) {
604// const spilled_inst = self.registers[index];
605// try self.getFunction().spillInstruction(reg, spilled_inst);
606// self.freeReg(reg);
607// }
608// }
609
610// i += 1;
611// }
612
613// break :blk regs;
614// };
615
616// log.debug("allocated registers {any} for insts {any}", .{ result, insts });
617// return result;
618// }
619
620// /// Allocates a register and optionally tracks it with a
621// /// corresponding instruction.
622// pub fn allocReg(
623// self: *Self,
624// inst: ?Air.Inst.Index,
625// register_class: RegisterBitSet,
626// ) AllocateRegistersError!Register {
627// return (try self.allocRegs(1, .{inst}, register_class))[0];
628// }
629
630// /// Spills the register if it is currently allocated. If a
631// /// corresponding instruction is passed, will also track this
632// /// register.
633// pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) AllocateRegistersError!void {
634// const index = indexOfRegIntoTracked(reg) orelse return;
635// log.debug("getReg {} for inst {}", .{ reg, inst });
636// self.markRegAllocated(reg);
637
638// if (inst) |tracked_inst|
639// if (!self.isRegFree(reg)) {
640// // Move the instruction that was previously there to a
641// // stack allocation.
642// const spilled_inst = self.registers[index];
643// self.registers[index] = tracked_inst;
644// try self.getFunction().spillInstruction(reg, spilled_inst);
645// } else {
646// self.getRegAssumeFree(reg, tracked_inst);
647// }
648// else {
649// if (!self.isRegFree(reg)) {
650// // Move the instruction that was previously there to a
651// // stack allocation.
652// const spilled_inst = self.registers[index];
653// try self.getFunction().spillInstruction(reg, spilled_inst);
654// self.freeReg(reg);
655// }
656// }
657// }
658
659// /// Allocates the specified register with the specified
660// /// instruction. Asserts that the register is free and no
661// /// spilling is necessary.
662// pub fn getRegAssumeFree(self: *Self, reg: Register, inst: Air.Inst.Index) void {
663// const index = indexOfRegIntoTracked(reg) orelse return;
664// log.debug("getRegAssumeFree {} for inst {}", .{ reg, inst });
665// self.markRegAllocated(reg);
666
667// assert(self.isRegFree(reg));
668// self.registers[index] = inst;
669// self.markRegUsed(reg);
670// }
671
672// /// Marks the specified register as free
673// pub fn freeReg(self: *Self, reg: Register) void {
674// const index = indexOfRegIntoTracked(reg) orelse return;
675// log.debug("freeing register {}", .{reg});
676
677// self.registers[index] = undefined;
678// self.markRegFree(reg);
679// }
680// };
681//}
682
683351const MockRegister1 = enum(u2) {
684352 r0,
685353 r1,
......@@ -698,7 +366,14 @@ const MockRegister1 = enum(u2) {
698366 &MockRegister1.allocatable_registers,
699367 );
700368
701 const gp: RM.RegisterBitSet = std.math.maxInt(RM.RegisterBitSet);
369 const gp: RM.RegisterBitSet = blk: {
370 var set = RM.RegisterBitSet.initEmpty();
371 set.setRangeValue(.{
372 .start = 0,
373 .end = allocatable_registers.len,
374 }, true);
375 break :blk set;
376 };
702377};
703378
704379const MockRegister2 = enum(u2) {
......@@ -719,7 +394,14 @@ const MockRegister2 = enum(u2) {
719394 &MockRegister2.allocatable_registers,
720395 );
721396
722 const gp: RM.RegisterBitSet = std.math.maxInt(RM.RegisterBitSet);
397 const gp: RM.RegisterBitSet = blk: {
398 var set = RM.RegisterBitSet.initEmpty();
399 set.setRangeValue(.{
400 .start = 0,
401 .end = allocatable_registers.len,
402 }, true);
403 break :blk set;
404 };
723405};
724406
725407const MockRegister3 = enum(u3) {
......@@ -753,11 +435,22 @@ const MockRegister3 = enum(u3) {
753435 &MockRegister3.allocatable_registers,
754436 );
755437
756 const gp: RM.RegisterBitSet = @as(RM.RegisterBitSet, std.math.maxInt(std.meta.Int(
757 .unsigned,
758 gp_regs.len,
759 )));
760 const ext: RM.RegisterBitSet = std.math.maxInt(RM.RegisterBitSet) - gp;
438 const gp: RM.RegisterBitSet = blk: {
439 var set = RM.RegisterBitSet.initEmpty();
440 set.setRangeValue(.{
441 .start = 0,
442 .end = gp_regs.len,
443 }, true);
444 break :blk set;
445 };
446 const ext: RM.RegisterBitSet = blk: {
447 var set = RM.RegisterBitSet.initEmpty();
448 set.setRangeValue(.{
449 .start = gp_regs.len,
450 .end = allocatable_registers.len,
451 }, true);
452 break :blk set;
453 };
761454};
762455
763456fn MockFunction(comptime Register: type) type {