authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-20 00:04:56+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-20 07:36:15+02:00
log0e43d007c098837d1863f2dab80b99e95910e0aa
tree96afa09c9d18c96d2183591b3be7e0fb9688b422
parente95dfac03eea942b53bbdf6117a716aaeba5eb4b

regalloc: temporarily nerf back to raw ints until stage2 catches up


6 files changed, 439 insertions(+), 89 deletions(-)

src/arch/aarch64/abi.zig+11-8
......@@ -1,3 +1,4 @@
1const std = @import("std");
12const builtin = @import("builtin");
23const bits = @import("bits.zig");
34const Register = bits.Register;
......@@ -26,12 +27,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
2627// Register classes
2728const RegisterBitSet = RegisterManager.RegisterBitSet;
2829pub const RegisterClass = struct {
29 pub const gp: RegisterBitSet = blk: {
30 var set = RegisterBitSet.initEmpty();
31 set.setRangeValue(.{
32 .start = 0,
33 .end = callee_preserved_regs.len,
34 }, true);
35 break :blk set;
36 };
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 // };
3740};
src/arch/arm/abi.zig+11-8
......@@ -1,3 +1,4 @@
1const std = @import("std");
12const bits = @import("bits.zig");
23const Register = bits.Register;
34const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
......@@ -14,12 +15,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
1415// Register classes
1516const RegisterBitSet = RegisterManager.RegisterBitSet;
1617pub const RegisterClass = struct {
17 pub const gp: RegisterBitSet = blk: {
18 var set = RegisterBitSet.initEmpty();
19 set.setRangeValue(.{
20 .start = 0,
21 .end = caller_preserved_regs.len + callee_preserved_regs.len,
22 }, true);
23 break :blk set;
24 };
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 // };
2528};
src/arch/riscv64/abi.zig+11-8
......@@ -1,3 +1,4 @@
1const std = @import("std");
12const bits = @import("bits.zig");
23const Register = bits.Register;
34const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
......@@ -12,12 +13,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
1213// Register classes
1314const RegisterBitSet = RegisterManager.RegisterBitSet;
1415pub const RegisterClass = struct {
15 pub const gp: RegisterBitSet = blk: {
16 var set = RegisterBitSet.initEmpty();
17 set.setRangeValue(.{
18 .start = 0,
19 .end = callee_preserved_regs.len,
20 }, true);
21 break :blk set;
22 };
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 // };
2326};
src/arch/sparc64/abi.zig+11-8
......@@ -1,3 +1,4 @@
1const std = @import("std");
12const bits = @import("bits.zig");
23const Register = bits.Register;
34const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
......@@ -42,12 +43,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
4243// Register classes
4344const RegisterBitSet = RegisterManager.RegisterBitSet;
4445pub const RegisterClass = struct {
45 pub const gp: RegisterBitSet = blk: {
46 var set = RegisterBitSet.initEmpty();
47 set.setRangeValue(.{
48 .start = 0,
49 .end = allocatable_regs.len,
50 }, true);
51 break :blk set;
52 };
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 // };
5356};
src/arch/x86_64/abi.zig+22-16
......@@ -393,20 +393,26 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
393393// Register classes
394394const RegisterBitSet = RegisterManager.RegisterBitSet;
395395pub const RegisterClass = struct {
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 };
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 // };
412418};
src/register_manager.zig+373-41
......@@ -4,7 +4,6 @@ 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;
87const Type = @import("type.zig").Type;
98const Module = @import("Module.zig");
109const expect = std.testing.expect;
......@@ -42,39 +41,49 @@ pub fn RegisterManager(
4241 registers: [tracked_registers.len]Air.Inst.Index = undefined,
4342 /// Tracks which registers are free (in which case the
4443 /// corresponding bit is set to 1)
45 free_registers: RegisterBitSet = RegisterBitSet.initFull(),
44 free_registers: RegisterBitSet = math.maxInt(RegisterBitSet),
4645 /// Tracks all registers allocated in the course of this
4746 /// function
48 allocated_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
47 allocated_registers: RegisterBitSet = 0,
4948 /// Tracks registers which are locked from being allocated
50 locked_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
49 locked_registers: RegisterBitSet = 0,
5150
5251 const Self = @This();
5352
54 pub const RegisterBitSet = StaticBitSet(tracked_registers.len);
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);
5557
5658 fn getFunction(self: *Self) *Function {
5759 return @fieldParentPtr(Function, "register_manager", self);
5860 }
5961
6062 fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool {
61 const index = indexOfRegIntoTracked(reg) orelse return true;
62 return !register_class.isSet(index);
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;
6372 }
6473
6574 fn markRegAllocated(self: *Self, reg: Register) void {
66 const index = indexOfRegIntoTracked(reg) orelse return;
67 self.allocated_registers.set(index);
75 const mask = getRegisterMask(reg) orelse return;
76 self.allocated_registers |= mask;
6877 }
6978
7079 fn markRegUsed(self: *Self, reg: Register) void {
71 const index = indexOfRegIntoTracked(reg) orelse return;
72 self.free_registers.unset(index);
80 const mask = getRegisterMask(reg) orelse return;
81 self.free_registers &= ~mask;
7382 }
7483
7584 fn markRegFree(self: *Self, reg: Register) void {
76 const index = indexOfRegIntoTracked(reg) orelse return;
77 self.free_registers.set(index);
85 const mask = getRegisterMask(reg) orelse return;
86 self.free_registers |= mask;
7887 }
7988
8089 pub fn indexOfReg(
......@@ -87,14 +96,14 @@ pub fn RegisterManager(
8796 return null;
8897 }
8998
90 pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt {
99 pub fn indexOfRegIntoTracked(reg: Register) ?ShiftInt {
91100 return indexOfReg(tracked_registers, reg);
92101 }
93102
94103 /// Returns true when this register is not tracked
95104 pub fn isRegFree(self: Self, reg: Register) bool {
96 const index = indexOfRegIntoTracked(reg) orelse return true;
97 return self.free_registers.isSet(index);
105 const mask = getRegisterMask(reg) orelse return true;
106 return self.free_registers & mask != 0;
98107 }
99108
100109 /// Returns whether this register was allocated in the course
......@@ -102,16 +111,16 @@ pub fn RegisterManager(
102111 ///
103112 /// Returns false when this register is not tracked
104113 pub fn isRegAllocated(self: Self, reg: Register) bool {
105 const index = indexOfRegIntoTracked(reg) orelse return false;
106 return self.allocated_registers.isSet(index);
114 const mask = getRegisterMask(reg) orelse return false;
115 return self.allocated_registers & mask != 0;
107116 }
108117
109118 /// Returns whether this register is locked
110119 ///
111120 /// Returns false when this register is not tracked
112121 pub fn isRegLocked(self: Self, reg: Register) bool {
113 const index = indexOfRegIntoTracked(reg) orelse return false;
114 return self.locked_registers.isSet(index);
122 const mask = getRegisterMask(reg) orelse return false;
123 return self.locked_registers & mask != 0;
115124 }
116125
117126 pub const RegisterLock = struct {
......@@ -130,8 +139,8 @@ pub fn RegisterManager(
130139 log.debug(" register already locked", .{});
131140 return null;
132141 }
133 const index = indexOfRegIntoTracked(reg) orelse return null;
134 self.locked_registers.set(index);
142 const mask = getRegisterMask(reg) orelse return null;
143 self.locked_registers |= mask;
135144 return RegisterLock{ .register = reg };
136145 }
137146
......@@ -140,8 +149,8 @@ pub fn RegisterManager(
140149 pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
141150 log.debug("locking asserting free {}", .{reg});
142151 assert(!self.isRegLocked(reg));
143 const index = indexOfRegIntoTracked(reg) orelse unreachable;
144 self.locked_registers.set(index);
152 const mask = getRegisterMask(reg) orelse unreachable;
153 self.locked_registers |= mask;
145154 return RegisterLock{ .register = reg };
146155 }
147156
......@@ -163,13 +172,13 @@ pub fn RegisterManager(
163172 /// Call `lockReg` to obtain the lock first.
164173 pub fn unlockReg(self: *Self, lock: RegisterLock) void {
165174 log.debug("unlocking {}", .{lock.register});
166 const index = indexOfRegIntoTracked(lock.register) orelse return;
167 self.locked_registers.unset(index);
175 const mask = getRegisterMask(lock.register) orelse return;
176 self.locked_registers &= ~mask;
168177 }
169178
170179 /// Returns true when at least one register is locked
171180 pub fn lockedRegsExist(self: Self) bool {
172 return self.locked_registers.count() > 0;
181 return self.locked_registers != 0;
173182 }
174183
175184 /// Allocates a specified number of registers, optionally
......@@ -183,15 +192,10 @@ pub fn RegisterManager(
183192 ) ?[count]Register {
184193 comptime assert(count > 0 and count <= tracked_registers.len);
185194
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;
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;
195199
196200 var regs: [count]Register = undefined;
197201 var i: usize = 0;
......@@ -238,10 +242,10 @@ pub fn RegisterManager(
238242 ) AllocateRegistersError![count]Register {
239243 comptime assert(count > 0 and count <= tracked_registers.len);
240244
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;
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;
245249
246250 const result = self.tryAllocRegs(count, insts, register_class) orelse blk: {
247251 // We'll take over the first count registers. Spill
......@@ -348,6 +352,334 @@ pub fn RegisterManager(
348352 };
349353}
350354
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
351683const MockRegister1 = enum(u2) {
352684 r0,
353685 r1,
......@@ -384,7 +716,7 @@ fn MockFunction(comptime Register: type) type {
384716
385717 const RegisterManagerT = RegisterManager(Self, Register, &Register.allocatable_registers);
386718
387 pub const reg_class: RegisterManagerT.RegisterBitSet = RegisterManagerT.RegisterBitSet.initFull();
719 pub const reg_class: RegisterManagerT.RegisterBitSet = math.maxInt(RegisterManagerT.RegisterBitSet);
388720
389721 pub fn deinit(self: *Self) void {
390722 self.spilled.deinit(self.allocator);