aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-05-26 09:06:42 +0200
committerJakub Konka <kubkon@jakubkonka.com>2022-05-26 12:05:51 +0200
commit0e0b00fd48ea680f2d69207297e877f54dd9ec89 (patch)
tree9baa6bd9110641ce42d4e02bbd1d054f6a70dde2 /src
parentab88165326abfd81c5046e8c064bd6603198ed94 (diff)
downloadzig-0e0b00fd48ea680f2d69207297e877f54dd9ec89.tar.gz
zig-0e0b00fd48ea680f2d69207297e877f54dd9ec89.zip
regalloc: use StaticBitSet internally
Diffstat (limited to 'src')
-rw-r--r--src/arch/aarch64/abi.zig18
-rw-r--r--src/arch/arm/abi.zig18
-rw-r--r--src/arch/riscv64/abi.zig18
-rw-r--r--src/arch/sparc64/abi.zig18
-rw-r--r--src/arch/x86_64/abi.zig38
-rw-r--r--src/register_manager.zig453
6 files changed, 121 insertions, 442 deletions
diff --git a/src/arch/aarch64/abi.zig b/src/arch/aarch64/abi.zig
index 89a3a6c21d..cb28b1fffa 100644
--- a/src/arch/aarch64/abi.zig
+++ b/src/arch/aarch64/abi.zig
@@ -27,14 +27,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
// Register classes
const RegisterBitSet = RegisterManager.RegisterBitSet;
pub const RegisterClass = struct {
- pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
- // TODO uncomment once #11680 is fixed.
- // pub const gp: RegisterBitSet = blk: {
- // var set = RegisterBitSet.initEmpty();
- // set.setRangeValue(.{
- // .start = 0,
- // .end = callee_preserved_regs.len,
- // }, true);
- // break :blk set;
- // };
+ pub const gp: RegisterBitSet = blk: {
+ var set = RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = callee_preserved_regs.len,
+ }, true);
+ break :blk set;
+ };
};
diff --git a/src/arch/arm/abi.zig b/src/arch/arm/abi.zig
index c76c3b0ea0..3fcfb0e561 100644
--- a/src/arch/arm/abi.zig
+++ b/src/arch/arm/abi.zig
@@ -15,14 +15,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
// Register classes
const RegisterBitSet = RegisterManager.RegisterBitSet;
pub const RegisterClass = struct {
- pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
- // TODO uncomment once #11680 is fixed.
- // pub const gp: RegisterBitSet = blk: {
- // var set = RegisterBitSet.initEmpty();
- // set.setRangeValue(.{
- // .start = 0,
- // .end = caller_preserved_regs.len + callee_preserved_regs.len,
- // }, true);
- // break :blk set;
- // };
+ pub const gp: RegisterBitSet = blk: {
+ var set = RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = caller_preserved_regs.len + callee_preserved_regs.len,
+ }, true);
+ break :blk set;
+ };
};
diff --git a/src/arch/riscv64/abi.zig b/src/arch/riscv64/abi.zig
index 30d3719a46..3792c4ab18 100644
--- a/src/arch/riscv64/abi.zig
+++ b/src/arch/riscv64/abi.zig
@@ -13,14 +13,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
// Register classes
const RegisterBitSet = RegisterManager.RegisterBitSet;
pub const RegisterClass = struct {
- pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
- // TODO uncomment once #11680 is fixed.
- // pub const gp: RegisterBitSet = blk: {
- // var set = RegisterBitSet.initEmpty();
- // set.setRangeValue(.{
- // .start = 0,
- // .end = callee_preserved_regs.len,
- // }, true);
- // break :blk set;
- // };
+ pub const gp: RegisterBitSet = blk: {
+ var set = RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = callee_preserved_regs.len,
+ }, true);
+ break :blk set;
+ };
};
diff --git a/src/arch/sparc64/abi.zig b/src/arch/sparc64/abi.zig
index 1c6d40941f..a18262f62b 100644
--- a/src/arch/sparc64/abi.zig
+++ b/src/arch/sparc64/abi.zig
@@ -43,14 +43,12 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
// Register classes
const RegisterBitSet = RegisterManager.RegisterBitSet;
pub const RegisterClass = struct {
- pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet);
- // TODO uncomment once #11680 is fixed.
- // pub const gp: RegisterBitSet = blk: {
- // var set = RegisterBitSet.initEmpty();
- // set.setRangeValue(.{
- // .start = 0,
- // .end = allocatable_regs.len,
- // }, true);
- // break :blk set;
- // };
+ pub const gp: RegisterBitSet = blk: {
+ var set = RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = allocatable_regs.len,
+ }, true);
+ break :blk set;
+ };
};
diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig
index 77f28c11f4..7e2025a23d 100644
--- a/src/arch/x86_64/abi.zig
+++ b/src/arch/x86_64/abi.zig
@@ -393,26 +393,20 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register,
// Register classes
const RegisterBitSet = RegisterManager.RegisterBitSet;
pub const RegisterClass = struct {
- pub const gp: RegisterBitSet = @as(RegisterBitSet, std.math.maxInt(std.meta.Int(
- .unsigned,
- caller_preserved_regs.len + callee_preserved_regs.len,
- )));
- pub const sse: RegisterBitSet = std.math.maxInt(RegisterBitSet) - gp;
- // TODO uncomment once #11680 is fixed.
- // pub const gp: RegisterBitSet = blk: {
- // var set = RegisterBitSet.initEmpty();
- // set.setRangeValue(.{
- // .start = 0,
- // .end = caller_preserved_regs.len + callee_preserved_regs.len,
- // }, true);
- // break :blk set;
- // };
- // pub const sse: RegisterBitSet = blk: {
- // var set = RegisterBitSet.initEmpty();
- // set.setRangeValue(.{
- // .start = caller_preserved_regs.len + callee_preserved_regs.len,
- // .end = allocatable_registers.len,
- // }, true);
- // break :blk set;
- // };
+ pub const gp: RegisterBitSet = blk: {
+ var set = RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = caller_preserved_regs.len + callee_preserved_regs.len,
+ }, true);
+ break :blk set;
+ };
+ pub const sse: RegisterBitSet = blk: {
+ var set = RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = caller_preserved_regs.len + callee_preserved_regs.len,
+ .end = allocatable_registers.len,
+ }, true);
+ break :blk set;
+ };
};
diff --git a/src/register_manager.zig b/src/register_manager.zig
index 98ee8c9ab3..64f6609a9b 100644
--- a/src/register_manager.zig
+++ b/src/register_manager.zig
@@ -4,6 +4,7 @@ const mem = std.mem;
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const Air = @import("Air.zig");
+const StaticBitSet = std.bit_set.StaticBitSet;
const Type = @import("type.zig").Type;
const Module = @import("Module.zig");
const expect = std.testing.expect;
@@ -41,49 +42,39 @@ pub fn RegisterManager(
registers: [tracked_registers.len]Air.Inst.Index = undefined,
/// Tracks which registers are free (in which case the
/// corresponding bit is set to 1)
- free_registers: RegisterBitSet = math.maxInt(RegisterBitSet),
+ free_registers: RegisterBitSet = RegisterBitSet.initFull(),
/// Tracks all registers allocated in the course of this
/// function
- allocated_registers: RegisterBitSet = 0,
+ allocated_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
/// Tracks registers which are locked from being allocated
- locked_registers: RegisterBitSet = 0,
+ locked_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
const Self = @This();
- /// An integer whose bits represent all the registers and
- /// whether they are free.
- pub const RegisterBitSet = std.meta.Int(.unsigned, tracked_registers.len);
- const ShiftInt = math.Log2Int(RegisterBitSet);
+ pub const RegisterBitSet = StaticBitSet(tracked_registers.len);
fn getFunction(self: *Self) *Function {
return @fieldParentPtr(Function, "register_manager", self);
}
fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool {
- const mask = getRegisterMask(reg) orelse return true;
- return mask & register_class == 0;
- }
-
- fn getRegisterMask(reg: Register) ?RegisterBitSet {
- const index = indexOfRegIntoTracked(reg) orelse return null;
- const shift = @intCast(ShiftInt, index);
- const mask = @as(RegisterBitSet, 1) << shift;
- return mask;
+ const index = indexOfRegIntoTracked(reg) orelse return true;
+ return !register_class.isSet(index);
}
fn markRegAllocated(self: *Self, reg: Register) void {
- const mask = getRegisterMask(reg) orelse return;
- self.allocated_registers |= mask;
+ const index = indexOfRegIntoTracked(reg) orelse return;
+ self.allocated_registers.set(index);
}
fn markRegUsed(self: *Self, reg: Register) void {
- const mask = getRegisterMask(reg) orelse return;
- self.free_registers &= ~mask;
+ const index = indexOfRegIntoTracked(reg) orelse return;
+ self.free_registers.unset(index);
}
fn markRegFree(self: *Self, reg: Register) void {
- const mask = getRegisterMask(reg) orelse return;
- self.free_registers |= mask;
+ const index = indexOfRegIntoTracked(reg) orelse return;
+ self.free_registers.set(index);
}
pub fn indexOfReg(
@@ -96,14 +87,14 @@ pub fn RegisterManager(
return null;
}
- pub fn indexOfRegIntoTracked(reg: Register) ?ShiftInt {
+ pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt {
return indexOfReg(tracked_registers, reg);
}
/// Returns true when this register is not tracked
pub fn isRegFree(self: Self, reg: Register) bool {
- const mask = getRegisterMask(reg) orelse return true;
- return self.free_registers & mask != 0;
+ const index = indexOfRegIntoTracked(reg) orelse return true;
+ return self.free_registers.isSet(index);
}
/// Returns whether this register was allocated in the course
@@ -111,16 +102,16 @@ pub fn RegisterManager(
///
/// Returns false when this register is not tracked
pub fn isRegAllocated(self: Self, reg: Register) bool {
- const mask = getRegisterMask(reg) orelse return false;
- return self.allocated_registers & mask != 0;
+ const index = indexOfRegIntoTracked(reg) orelse return false;
+ return self.allocated_registers.isSet(index);
}
/// Returns whether this register is locked
///
/// Returns false when this register is not tracked
pub fn isRegLocked(self: Self, reg: Register) bool {
- const mask = getRegisterMask(reg) orelse return false;
- return self.locked_registers & mask != 0;
+ const index = indexOfRegIntoTracked(reg) orelse return false;
+ return self.locked_registers.isSet(index);
}
pub const RegisterLock = struct {
@@ -139,8 +130,8 @@ pub fn RegisterManager(
log.debug(" register already locked", .{});
return null;
}
- const mask = getRegisterMask(reg) orelse return null;
- self.locked_registers |= mask;
+ const index = indexOfRegIntoTracked(reg) orelse return null;
+ self.locked_registers.set(index);
return RegisterLock{ .register = reg };
}
@@ -149,8 +140,8 @@ pub fn RegisterManager(
pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
log.debug("locking asserting free {}", .{reg});
assert(!self.isRegLocked(reg));
- const mask = getRegisterMask(reg) orelse unreachable;
- self.locked_registers |= mask;
+ const index = indexOfRegIntoTracked(reg) orelse unreachable;
+ self.locked_registers.set(index);
return RegisterLock{ .register = reg };
}
@@ -172,13 +163,13 @@ pub fn RegisterManager(
/// Call `lockReg` to obtain the lock first.
pub fn unlockReg(self: *Self, lock: RegisterLock) void {
log.debug("unlocking {}", .{lock.register});
- const mask = getRegisterMask(lock.register) orelse return;
- self.locked_registers &= ~mask;
+ const index = indexOfRegIntoTracked(lock.register) orelse return;
+ self.locked_registers.unset(index);
}
/// Returns true when at least one register is locked
pub fn lockedRegsExist(self: Self) bool {
- return self.locked_registers != 0;
+ return self.locked_registers.count() > 0;
}
/// Allocates a specified number of registers, optionally
@@ -192,10 +183,15 @@ pub fn RegisterManager(
) ?[count]Register {
comptime assert(count > 0 and count <= tracked_registers.len);
- const free_registers = self.free_registers & register_class;
- const free_and_not_locked_registers = free_registers & ~self.locked_registers;
- const free_and_not_locked_registers_count = @popCount(RegisterBitSet, free_and_not_locked_registers);
- if (free_and_not_locked_registers_count < count) return null;
+ var free_and_not_locked_registers = self.free_registers;
+ free_and_not_locked_registers.setIntersection(register_class);
+
+ var unlocked_registers = self.locked_registers;
+ unlocked_registers.toggleAll();
+
+ free_and_not_locked_registers.setIntersection(unlocked_registers);
+
+ if (free_and_not_locked_registers.count() < count) return null;
var regs: [count]Register = undefined;
var i: usize = 0;
@@ -242,10 +238,10 @@ pub fn RegisterManager(
) AllocateRegistersError![count]Register {
comptime assert(count > 0 and count <= tracked_registers.len);
- const available_registers_count = @popCount(RegisterBitSet, register_class);
- const locked_registers = self.locked_registers & register_class;
- const locked_registers_count = @popCount(RegisterBitSet, locked_registers);
- if (count > available_registers_count - locked_registers_count) return error.OutOfRegisters;
+ var locked_registers = self.locked_registers;
+ locked_registers.setIntersection(register_class);
+
+ if (count > register_class.count() - locked_registers.count()) return error.OutOfRegisters;
const result = self.tryAllocRegs(count, insts, register_class) orelse blk: {
// We'll take over the first count registers. Spill
@@ -255,7 +251,7 @@ pub fn RegisterManager(
var i: usize = 0;
for (tracked_registers) |reg| {
if (i >= count) break;
- if (excludeRegister(reg, register_class)) continue;
+ if (excludeRegister(reg, register_class)) break;
if (self.isRegLocked(reg)) continue;
regs[i] = reg;
@@ -352,334 +348,6 @@ pub fn RegisterManager(
};
}
-// TODO delete current implementation of RegisterManager above, and uncomment the one
-// below once #11680 is fixed:
-// https://github.com/ziglang/zig/issues/11680
-
-//pub fn RegisterManager(
-// comptime Function: type,
-// comptime Register: type,
-// comptime tracked_registers: []const Register,
-//) type {
-// // architectures which do not have a concept of registers should
-// // refrain from using RegisterManager
-// assert(tracked_registers.len > 0); // see note above
-
-// return struct {
-// /// Tracks the AIR instruction allocated to every register. If
-// /// no instruction is allocated to a register (i.e. the
-// /// register is free), the value in that slot is undefined.
-// ///
-// /// The key must be canonical register.
-// registers: [tracked_registers.len]Air.Inst.Index = undefined,
-// /// Tracks which registers are free (in which case the
-// /// corresponding bit is set to 1)
-// free_registers: RegisterBitSet = RegisterBitSet.initFull(),
-// /// Tracks all registers allocated in the course of this
-// /// function
-// allocated_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
-// /// Tracks registers which are locked from being allocated
-// locked_registers: RegisterBitSet = RegisterBitSet.initEmpty(),
-
-// const Self = @This();
-
-// pub const RegisterBitSet = StaticBitSet(tracked_registers.len);
-
-// fn getFunction(self: *Self) *Function {
-// return @fieldParentPtr(Function, "register_manager", self);
-// }
-
-// fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool {
-// const index = indexOfRegIntoTracked(reg) orelse return true;
-// return !register_class.isSet(index);
-// }
-
-// fn markRegAllocated(self: *Self, reg: Register) void {
-// const index = indexOfRegIntoTracked(reg) orelse return;
-// self.allocated_registers.set(index);
-// }
-
-// fn markRegUsed(self: *Self, reg: Register) void {
-// const index = indexOfRegIntoTracked(reg) orelse return;
-// self.free_registers.unset(index);
-// }
-
-// fn markRegFree(self: *Self, reg: Register) void {
-// const index = indexOfRegIntoTracked(reg) orelse return;
-// self.free_registers.set(index);
-// }
-
-// pub fn indexOfReg(
-// comptime registers: []const Register,
-// reg: Register,
-// ) ?std.math.IntFittingRange(0, registers.len - 1) {
-// inline for (tracked_registers) |cpreg, i| {
-// if (reg.id() == cpreg.id()) return i;
-// }
-// return null;
-// }
-
-// pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt {
-// return indexOfReg(tracked_registers, reg);
-// }
-
-// /// Returns true when this register is not tracked
-// pub fn isRegFree(self: Self, reg: Register) bool {
-// const index = indexOfRegIntoTracked(reg) orelse return true;
-// return self.free_registers.isSet(index);
-// }
-
-// /// Returns whether this register was allocated in the course
-// /// of this function.
-// ///
-// /// Returns false when this register is not tracked
-// pub fn isRegAllocated(self: Self, reg: Register) bool {
-// const index = indexOfRegIntoTracked(reg) orelse return false;
-// return self.allocated_registers.isSet(index);
-// }
-
-// /// Returns whether this register is locked
-// ///
-// /// Returns false when this register is not tracked
-// pub fn isRegLocked(self: Self, reg: Register) bool {
-// const index = indexOfRegIntoTracked(reg) orelse return false;
-// return self.locked_registers.isSet(index);
-// }
-
-// pub const RegisterLock = struct {
-// register: Register,
-// };
-
-// /// Prevents the register from being allocated until they are
-// /// unlocked again.
-// /// Returns `RegisterLock` if the register was not already
-// /// locked, or `null` otherwise.
-// /// Only the owner of the `RegisterLock` can unlock the
-// /// register later.
-// pub fn lockReg(self: *Self, reg: Register) ?RegisterLock {
-// log.debug("locking {}", .{reg});
-// if (self.isRegLocked(reg)) {
-// log.debug(" register already locked", .{});
-// return null;
-// }
-// const index = indexOfRegIntoTracked(reg) orelse return null;
-// self.locked_registers.set(index);
-// return RegisterLock{ .register = reg };
-// }
-
-// /// Like `lockReg` but asserts the register was unused always
-// /// returning a valid lock.
-// pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
-// log.debug("locking asserting free {}", .{reg});
-// assert(!self.isRegLocked(reg));
-// const index = indexOfRegIntoTracked(reg) orelse unreachable;
-// self.locked_registers.set(index);
-// return RegisterLock{ .register = reg };
-// }
-
-// /// Like `lockRegAssumeUnused` but locks multiple registers.
-// pub fn lockRegsAssumeUnused(
-// self: *Self,
-// comptime count: comptime_int,
-// regs: [count]Register,
-// ) [count]RegisterLock {
-// var buf: [count]RegisterLock = undefined;
-// for (regs) |reg, i| {
-// buf[i] = self.lockRegAssumeUnused(reg);
-// }
-// return buf;
-// }
-
-// /// Unlocks the register allowing its re-allocation and re-use.
-// /// Requires `RegisterLock` to unlock a register.
-// /// Call `lockReg` to obtain the lock first.
-// pub fn unlockReg(self: *Self, lock: RegisterLock) void {
-// log.debug("unlocking {}", .{lock.register});
-// const index = indexOfRegIntoTracked(lock.register) orelse return;
-// self.locked_registers.unset(index);
-// }
-
-// /// Returns true when at least one register is locked
-// pub fn lockedRegsExist(self: Self) bool {
-// return self.locked_registers.count() > 0;
-// }
-
-// /// Allocates a specified number of registers, optionally
-// /// tracking them. Returns `null` if not enough registers are
-// /// free.
-// pub fn tryAllocRegs(
-// self: *Self,
-// comptime count: comptime_int,
-// insts: [count]?Air.Inst.Index,
-// register_class: RegisterBitSet,
-// ) ?[count]Register {
-// comptime assert(count > 0 and count <= tracked_registers.len);
-
-// var free_and_not_locked_registers = self.free_registers;
-// free_and_not_locked_registers.setIntersection(register_class);
-
-// var unlocked_registers = self.locked_registers;
-// unlocked_registers.toggleAll();
-
-// free_and_not_locked_registers.setIntersection(unlocked_registers);
-
-// if (free_and_not_locked_registers.count() < count) return null;
-
-// var regs: [count]Register = undefined;
-// var i: usize = 0;
-// for (tracked_registers) |reg| {
-// if (i >= count) break;
-// if (excludeRegister(reg, register_class)) continue;
-// if (self.isRegLocked(reg)) continue;
-// if (!self.isRegFree(reg)) continue;
-
-// regs[i] = reg;
-// i += 1;
-// }
-// assert(i == count);
-
-// for (regs) |reg, j| {
-// self.markRegAllocated(reg);
-
-// if (insts[j]) |inst| {
-// // Track the register
-// const index = indexOfRegIntoTracked(reg).?; // indexOfReg() on a callee-preserved reg should never return null
-// self.registers[index] = inst;
-// self.markRegUsed(reg);
-// }
-// }
-
-// return regs;
-// }
-
-// /// Allocates a register and optionally tracks it with a
-// /// corresponding instruction. Returns `null` if all registers
-// /// are allocated.
-// pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, register_class: RegisterBitSet) ?Register {
-// return if (tryAllocRegs(self, 1, .{inst}, register_class)) |regs| regs[0] else null;
-// }
-
-// /// Allocates a specified number of registers, optionally
-// /// tracking them. Asserts that count is not
-// /// larger than the total number of registers available.
-// pub fn allocRegs(
-// self: *Self,
-// comptime count: comptime_int,
-// insts: [count]?Air.Inst.Index,
-// register_class: RegisterBitSet,
-// ) AllocateRegistersError![count]Register {
-// comptime assert(count > 0 and count <= tracked_registers.len);
-
-// var locked_registers = self.locked_registers;
-// locked_registers.setIntersection(register_class);
-
-// if (count > register_class.count() - locked_registers.count()) return error.OutOfRegisters;
-
-// const result = self.tryAllocRegs(count, insts, register_class) orelse blk: {
-// // We'll take over the first count registers. Spill
-// // the instructions that were previously there to a
-// // stack allocations.
-// var regs: [count]Register = undefined;
-// var i: usize = 0;
-// for (tracked_registers) |reg| {
-// if (i >= count) break;
-// if (excludeRegister(reg, register_class)) break;
-// if (self.isRegLocked(reg)) continue;
-
-// regs[i] = reg;
-// self.markRegAllocated(reg);
-// const index = indexOfRegIntoTracked(reg).?; // indexOfReg() on a callee-preserved reg should never return null
-// if (insts[i]) |inst| {
-// // Track the register
-// if (self.isRegFree(reg)) {
-// self.markRegUsed(reg);
-// } else {
-// const spilled_inst = self.registers[index];
-// try self.getFunction().spillInstruction(reg, spilled_inst);
-// }
-// self.registers[index] = inst;
-// } else {
-// // Don't track the register
-// if (!self.isRegFree(reg)) {
-// const spilled_inst = self.registers[index];
-// try self.getFunction().spillInstruction(reg, spilled_inst);
-// self.freeReg(reg);
-// }
-// }
-
-// i += 1;
-// }
-
-// break :blk regs;
-// };
-
-// log.debug("allocated registers {any} for insts {any}", .{ result, insts });
-// return result;
-// }
-
-// /// Allocates a register and optionally tracks it with a
-// /// corresponding instruction.
-// pub fn allocReg(
-// self: *Self,
-// inst: ?Air.Inst.Index,
-// register_class: RegisterBitSet,
-// ) AllocateRegistersError!Register {
-// return (try self.allocRegs(1, .{inst}, register_class))[0];
-// }
-
-// /// Spills the register if it is currently allocated. If a
-// /// corresponding instruction is passed, will also track this
-// /// register.
-// pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) AllocateRegistersError!void {
-// const index = indexOfRegIntoTracked(reg) orelse return;
-// log.debug("getReg {} for inst {}", .{ reg, inst });
-// self.markRegAllocated(reg);
-
-// if (inst) |tracked_inst|
-// if (!self.isRegFree(reg)) {
-// // Move the instruction that was previously there to a
-// // stack allocation.
-// const spilled_inst = self.registers[index];
-// self.registers[index] = tracked_inst;
-// try self.getFunction().spillInstruction(reg, spilled_inst);
-// } else {
-// self.getRegAssumeFree(reg, tracked_inst);
-// }
-// else {
-// if (!self.isRegFree(reg)) {
-// // Move the instruction that was previously there to a
-// // stack allocation.
-// const spilled_inst = self.registers[index];
-// try self.getFunction().spillInstruction(reg, spilled_inst);
-// self.freeReg(reg);
-// }
-// }
-// }
-
-// /// Allocates the specified register with the specified
-// /// instruction. Asserts that the register is free and no
-// /// spilling is necessary.
-// pub fn getRegAssumeFree(self: *Self, reg: Register, inst: Air.Inst.Index) void {
-// const index = indexOfRegIntoTracked(reg) orelse return;
-// log.debug("getRegAssumeFree {} for inst {}", .{ reg, inst });
-// self.markRegAllocated(reg);
-
-// assert(self.isRegFree(reg));
-// self.registers[index] = inst;
-// self.markRegUsed(reg);
-// }
-
-// /// Marks the specified register as free
-// pub fn freeReg(self: *Self, reg: Register) void {
-// const index = indexOfRegIntoTracked(reg) orelse return;
-// log.debug("freeing register {}", .{reg});
-
-// self.registers[index] = undefined;
-// self.markRegFree(reg);
-// }
-// };
-//}
-
const MockRegister1 = enum(u2) {
r0,
r1,
@@ -698,7 +366,14 @@ const MockRegister1 = enum(u2) {
&MockRegister1.allocatable_registers,
);
- const gp: RM.RegisterBitSet = std.math.maxInt(RM.RegisterBitSet);
+ const gp: RM.RegisterBitSet = blk: {
+ var set = RM.RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = allocatable_registers.len,
+ }, true);
+ break :blk set;
+ };
};
const MockRegister2 = enum(u2) {
@@ -719,7 +394,14 @@ const MockRegister2 = enum(u2) {
&MockRegister2.allocatable_registers,
);
- const gp: RM.RegisterBitSet = std.math.maxInt(RM.RegisterBitSet);
+ const gp: RM.RegisterBitSet = blk: {
+ var set = RM.RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = allocatable_registers.len,
+ }, true);
+ break :blk set;
+ };
};
const MockRegister3 = enum(u3) {
@@ -753,11 +435,22 @@ const MockRegister3 = enum(u3) {
&MockRegister3.allocatable_registers,
);
- const gp: RM.RegisterBitSet = @as(RM.RegisterBitSet, std.math.maxInt(std.meta.Int(
- .unsigned,
- gp_regs.len,
- )));
- const ext: RM.RegisterBitSet = std.math.maxInt(RM.RegisterBitSet) - gp;
+ const gp: RM.RegisterBitSet = blk: {
+ var set = RM.RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = 0,
+ .end = gp_regs.len,
+ }, true);
+ break :blk set;
+ };
+ const ext: RM.RegisterBitSet = blk: {
+ var set = RM.RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = gp_regs.len,
+ .end = allocatable_registers.len,
+ }, true);
+ break :blk set;
+ };
};
fn MockFunction(comptime Register: type) type {