aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-05-18 11:15:04 +0200
committerJakub Konka <kubkon@jakubkonka.com>2022-05-19 19:39:32 +0200
commit549174f743d3b56544e2d3d6993f4d43bba1e7fd (patch)
tree90be8877e03f93fd30a95120fd8db774e53b4898 /src
parent9e5c8cb008f75c2e570a0e48d5d014e936c103ca (diff)
downloadzig-549174f743d3b56544e2d3d6993f4d43bba1e7fd.tar.gz
zig-549174f743d3b56544e2d3d6993f4d43bba1e7fd.zip
regalloc: allow for optional selector mask when allocating
Diffstat (limited to 'src')
-rw-r--r--src/arch/aarch64/CodeGen.zig56
-rw-r--r--src/arch/arm/CodeGen.zig64
-rw-r--r--src/arch/riscv64/CodeGen.zig16
-rw-r--r--src/arch/sparc64/CodeGen.zig26
-rw-r--r--src/arch/x86_64/CodeGen.zig40
-rw-r--r--src/register_manager.zig17
6 files changed, 113 insertions, 106 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index 0993d352d7..a3116587d4 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -888,7 +888,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
if (reg_ok) {
// Make sure the type can fit in a register before we try to allocate one.
if (abi_size <= 8) {
- if (self.register_manager.tryAllocReg(inst)) |reg| {
+ if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
return MCValue{ .register = registerAlias(reg, abi_size) };
}
}
@@ -951,7 +951,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
/// allocated. A second call to `copyToTmpRegister` may return the same register.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
try self.genSetReg(ty, reg, mcv);
return reg;
@@ -961,7 +961,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
/// `reg_owner` is the instruction that gets associated with the register in the register table.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
- const raw_reg = try self.register_manager.allocReg(reg_owner);
+ const raw_reg = try self.register_manager.allocReg(reg_owner, .{});
const ty = self.air.typeOfIndex(reg_owner);
const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
@@ -1074,11 +1074,11 @@ fn trunc(
if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
break :blk registerAlias(operand_reg, dest_ty.abiSize(self.target.*));
} else {
- const raw_reg = try self.register_manager.allocReg(inst);
+ const raw_reg = try self.register_manager.allocReg(inst, .{});
break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));
}
} else blk: {
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));
};
@@ -1160,7 +1160,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
break :blk op_reg;
}
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
break :blk raw_reg.to32();
};
@@ -1193,7 +1193,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
break :blk op_reg;
}
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
break :blk registerAlias(raw_reg, operand_ty.abiSize(self.target.*));
};
@@ -1293,7 +1293,7 @@ fn binOpRegister(
break :inst Air.refToIndex(md.lhs).?;
} else null;
- const raw_reg = try self.register_manager.allocReg(track_inst);
+ const raw_reg = try self.register_manager.allocReg(track_inst, .{});
const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -1308,7 +1308,7 @@ fn binOpRegister(
break :inst Air.refToIndex(md.rhs).?;
} else null;
- const raw_reg = try self.register_manager.allocReg(track_inst);
+ const raw_reg = try self.register_manager.allocReg(track_inst, .{});
const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -1326,11 +1326,11 @@ fn binOpRegister(
} else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
break :blk rhs_reg;
} else {
- const raw_reg = try self.register_manager.allocReg(md.inst);
+ const raw_reg = try self.register_manager.allocReg(md.inst, .{});
break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
}
} else blk: {
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
},
};
@@ -1431,7 +1431,7 @@ fn binOpImmediate(
).?;
} else null;
- const raw_reg = try self.register_manager.allocReg(track_inst);
+ const raw_reg = try self.register_manager.allocReg(track_inst, .{});
const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -1452,11 +1452,11 @@ fn binOpImmediate(
)) {
break :blk lhs_reg;
} else {
- const raw_reg = try self.register_manager.allocReg(md.inst);
+ const raw_reg = try self.register_manager.allocReg(md.inst, .{});
break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
}
} else blk: {
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
},
};
@@ -1872,7 +1872,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
defer self.register_manager.unlockReg(dest_reg_lock);
- const raw_truncated_reg = try self.register_manager.allocReg(null);
+ const raw_truncated_reg = try self.register_manager.allocReg(null, .{});
const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*));
const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
defer self.register_manager.unlockReg(truncated_reg_lock);
@@ -1983,7 +1983,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
defer self.register_manager.unlockReg(dest_reg_lock);
- const truncated_reg = try self.register_manager.allocReg(null);
+ const truncated_reg = try self.register_manager.allocReg(null, .{});
const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
defer self.register_manager.unlockReg(truncated_reg_lock);
@@ -2048,7 +2048,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
const lhs_reg = if (lhs_is_register) lhs.register else blk: {
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
break :blk reg;
};
@@ -2056,7 +2056,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
const rhs_reg = if (rhs_is_register) rhs.register else blk: {
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
break :blk reg;
};
@@ -2067,7 +2067,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
const dest_reg = blk: {
- const raw_reg = try self.register_manager.allocReg(null);
+ const raw_reg = try self.register_manager.allocReg(null, .{});
const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
break :blk reg;
};
@@ -2086,7 +2086,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
} },
});
- const dest_high_reg = try self.register_manager.allocReg(null);
+ const dest_high_reg = try self.register_manager.allocReg(null, .{});
const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
defer self.register_manager.unlockReg(dest_high_reg_lock);
@@ -2136,7 +2136,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
}
},
.unsigned => {
- const dest_high_reg = try self.register_manager.allocReg(null);
+ const dest_high_reg = try self.register_manager.allocReg(null, .{});
const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
defer self.register_manager.unlockReg(dest_high_reg_lock);
@@ -2192,7 +2192,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
},
}
- const truncated_reg = try self.register_manager.allocReg(null);
+ const truncated_reg = try self.register_manager.allocReg(null, .{});
const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
defer self.register_manager.unlockReg(truncated_reg_lock);
@@ -2663,7 +2663,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
},
.stack_offset => |off| {
if (elem_size <= 8) {
- const raw_tmp_reg = try self.register_manager.allocReg(null);
+ const raw_tmp_reg = try self.register_manager.allocReg(null, .{});
const tmp_reg = registerAlias(raw_tmp_reg, elem_size);
const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_reg_lock);
@@ -2672,7 +2672,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
} else {
// TODO optimize the register allocation
- const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
+ const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
defer for (regs_locks) |reg| {
self.register_manager.unlockReg(reg);
@@ -2887,7 +2887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
},
else => {
if (abi_size <= 8) {
- const raw_tmp_reg = try self.register_manager.allocReg(null);
+ const raw_tmp_reg = try self.register_manager.allocReg(null, .{});
const tmp_reg = registerAlias(raw_tmp_reg, abi_size);
const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_reg_lock);
@@ -3002,7 +3002,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
// TODO return special MCValue condition flags
// get overflow bit: set register to C flag
// resp. V flag
- const raw_dest_reg = try self.register_manager.allocReg(null);
+ const raw_dest_reg = try self.register_manager.allocReg(null, .{});
const dest_reg = raw_dest_reg.to32();
// C flag: cset reg, cs
@@ -4065,7 +4065,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
const overflow_bit_ty = ty.structFieldType(1);
const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
- const raw_cond_reg = try self.register_manager.allocReg(null);
+ const raw_cond_reg = try self.register_manager.allocReg(null, .{});
const cond_reg = registerAlias(
raw_cond_reg,
@intCast(u32, overflow_bit_ty.abiSize(self.target.*)),
@@ -4113,7 +4113,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
// TODO call extern memcpy
- const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
+ const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
const regs_locks = self.register_manager.lockRegsAssumeUnused(5, regs);
defer for (regs_locks) |reg| {
self.register_manager.unlockReg(reg);
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index bfc7f687fa..c792615c79 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -874,7 +874,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
if (abi_size <= ptr_bytes) {
- if (self.register_manager.tryAllocReg(inst)) |reg| {
+ if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
return MCValue{ .register = reg };
}
}
@@ -939,7 +939,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
/// allocated. A second call to `copyToTmpRegister` may return the same register.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
- const reg = try self.register_manager.allocReg(null);
+ const reg = try self.register_manager.allocReg(null, .{});
try self.genSetReg(ty, reg, mcv);
return reg;
}
@@ -948,7 +948,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
/// `reg_owner` is the instruction that gets associated with the register in the register table.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
- const reg = try self.register_manager.allocReg(reg_owner);
+ const reg = try self.register_manager.allocReg(reg_owner, .{});
try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
return MCValue{ .register = reg };
}
@@ -1065,9 +1065,9 @@ fn trunc(
if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
break :blk operand_reg;
} else {
- break :blk try self.register_manager.allocReg(inst);
+ break :blk try self.register_manager.allocReg(inst, .{});
}
- } else try self.register_manager.allocReg(null);
+ } else try self.register_manager.allocReg(null, .{});
switch (info_b.bits) {
32 => {
@@ -1153,7 +1153,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
break :blk op_reg;
}
- break :blk try self.register_manager.allocReg(null);
+ break :blk try self.register_manager.allocReg(null, .{});
};
_ = try self.addInst(.{
@@ -1183,7 +1183,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
break :blk op_reg;
}
- break :blk try self.register_manager.allocReg(null);
+ break :blk try self.register_manager.allocReg(null, .{});
};
_ = try self.addInst(.{
@@ -1254,9 +1254,9 @@ fn minMax(
} else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
break :blk rhs_reg;
} else {
- break :blk try self.register_manager.allocReg(inst);
+ break :blk try self.register_manager.allocReg(inst, .{});
}
- } else try self.register_manager.allocReg(null);
+ } else try self.register_manager.allocReg(null, .{});
// lhs == reg should have been checked by airMinMax
//
@@ -1438,7 +1438,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
defer self.register_manager.unlockReg(dest_reg_lock);
- const truncated_reg = try self.register_manager.allocReg(null);
+ const truncated_reg = try self.register_manager.allocReg(null, .{});
const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
defer self.register_manager.unlockReg(truncated_reg_lock);
@@ -1543,7 +1543,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
defer self.register_manager.unlockReg(dest_reg_lock);
- const truncated_reg = try self.register_manager.allocReg(null);
+ const truncated_reg = try self.register_manager.allocReg(null, .{});
const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
defer self.register_manager.unlockReg(truncated_reg_lock);
@@ -1582,18 +1582,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
const lhs_reg = if (lhs_is_register)
lhs.register
else
- try self.register_manager.allocReg(null);
+ try self.register_manager.allocReg(null, .{});
const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
const rhs_reg = if (rhs_is_register)
rhs.register
else
- try self.register_manager.allocReg(null);
+ try self.register_manager.allocReg(null, .{});
const new_rhs_lock = self.register_manager.lockReg(rhs_reg);
defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
- const dest_regs = try self.register_manager.allocRegs(2, .{ null, null });
+ const dest_regs = try self.register_manager.allocRegs(2, .{ null, null }, .{});
const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs);
defer for (dest_regs_locks) |reg| {
self.register_manager.unlockReg(reg);
@@ -1604,7 +1604,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
- const truncated_reg = try self.register_manager.allocReg(null);
+ const truncated_reg = try self.register_manager.allocReg(null, .{});
const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
defer self.register_manager.unlockReg(truncated_reg_lock);
@@ -2026,7 +2026,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg);
defer self.register_manager.unlockReg(base_reg_lock);
- const dst_reg = try self.register_manager.allocReg(inst);
+ const dst_reg = try self.register_manager.allocReg(inst, .{});
const dst_mcv = MCValue{ .register = dst_reg };
const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
defer self.register_manager.unlockReg(dst_reg_lock);
@@ -2234,7 +2234,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
},
.stack_offset => |off| {
if (elem_size <= 4) {
- const tmp_reg = try self.register_manager.allocReg(null);
+ const tmp_reg = try self.register_manager.allocReg(null, .{});
const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_reg_lock);
@@ -2242,7 +2242,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
} else {
// TODO optimize the register allocation
- const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
+ const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
defer for (regs_locks) |reg_locked| {
self.register_manager.unlockReg(reg_locked);
@@ -2271,7 +2271,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
.stack_offset,
.stack_argument_offset,
=> {
- const reg = try self.register_manager.allocReg(null);
+ const reg = try self.register_manager.allocReg(null, .{});
const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
defer self.register_manager.unlockReg(reg_lock);
@@ -2338,14 +2338,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
},
else => {
if (elem_size <= 4) {
- const tmp_reg = try self.register_manager.allocReg(null);
+ const tmp_reg = try self.register_manager.allocReg(null, .{});
const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_reg_lock);
try self.genSetReg(value_ty, tmp_reg, value);
try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
} else {
- const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
+ const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
defer for (regs_locks) |reg| {
self.register_manager.unlockReg(reg);
@@ -2487,7 +2487,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1 => {
// get overflow bit: set register to C flag
// resp. V flag
- const dest_reg = try self.register_manager.allocReg(null);
+ const dest_reg = try self.register_manager.allocReg(null, .{});
// mov reg, #0
_ = try self.addInst(.{
@@ -2567,7 +2567,7 @@ fn binOpRegister(
break :inst Air.refToIndex(md.lhs).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -2581,7 +2581,7 @@ fn binOpRegister(
break :inst Air.refToIndex(md.rhs).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -2598,9 +2598,9 @@ fn binOpRegister(
} else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
break :blk rhs_reg;
} else {
- break :blk try self.register_manager.allocReg(md.inst);
+ break :blk try self.register_manager.allocReg(md.inst, .{});
}
- } else try self.register_manager.allocReg(null),
+ } else try self.register_manager.allocReg(null, .{}),
};
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
@@ -2684,7 +2684,7 @@ fn binOpImmediate(
).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -2704,9 +2704,9 @@ fn binOpImmediate(
)) {
break :blk lhs_reg;
} else {
- break :blk try self.register_manager.allocReg(md.inst);
+ break :blk try self.register_manager.allocReg(md.inst, .{});
}
- } else try self.register_manager.allocReg(null),
+ } else try self.register_manager.allocReg(null, .{}),
};
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
@@ -4363,7 +4363,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
const overflow_bit_ty = ty.structFieldType(1);
const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
- const cond_reg = try self.register_manager.allocReg(null);
+ const cond_reg = try self.register_manager.allocReg(null, .{});
// C flag: movcs reg, #1
// V flag: movvs reg, #1
@@ -4408,7 +4408,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
// TODO call extern memcpy
- const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
+ const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
const src_reg = regs[0];
const dst_reg = regs[1];
const len_reg = regs[2];
@@ -4782,7 +4782,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
// TODO call extern memcpy
- const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
+ const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
const src_reg = regs[0];
const dst_reg = regs[1];
const len_reg = regs[2];
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index c2f9b2e36d..79bedb30d8 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -803,7 +803,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
if (abi_size <= ptr_bytes) {
- if (self.register_manager.tryAllocReg(inst)) |reg| {
+ if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
return MCValue{ .register = reg };
}
}
@@ -826,7 +826,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
/// allocated. A second call to `copyToTmpRegister` may return the same register.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
- const reg = try self.register_manager.allocReg(null);
+ const reg = try self.register_manager.allocReg(null, .{});
try self.genSetReg(ty, reg, mcv);
return reg;
}
@@ -835,7 +835,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
/// `reg_owner` is the instruction that gets associated with the register in the register table.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
- const reg = try self.register_manager.allocReg(reg_owner);
+ const reg = try self.register_manager.allocReg(reg_owner, .{});
try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
return MCValue{ .register = reg };
}
@@ -958,7 +958,7 @@ fn binOpRegister(
break :inst Air.refToIndex(bin_op.lhs).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -973,7 +973,7 @@ fn binOpRegister(
break :inst Air.refToIndex(bin_op.rhs).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -990,9 +990,9 @@ fn binOpRegister(
} else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
break :blk rhs_reg;
} else {
- break :blk try self.register_manager.allocReg(inst);
+ break :blk try self.register_manager.allocReg(inst, .{});
}
- } else try self.register_manager.allocReg(null);
+ } else try self.register_manager.allocReg(null, .{});
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
@@ -1482,7 +1482,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
.memory,
.stack_offset,
=> {
- const reg = try self.register_manager.allocReg(null);
+ const reg = try self.register_manager.allocReg(null, .{});
const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
defer self.register_manager.unlockReg(reg_lock);
diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig
index aa679cac6d..e8cb5d3100 100644
--- a/src/arch/sparc64/CodeGen.zig
+++ b/src/arch/sparc64/CodeGen.zig
@@ -1613,7 +1613,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
if (reg_ok) {
// Make sure the type can fit in a register before we try to allocate one.
if (abi_size <= 8) {
- if (self.register_manager.tryAllocReg(inst)) |reg| {
+ if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
return MCValue{ .register = reg };
}
}
@@ -1854,7 +1854,7 @@ fn binOpImmediate(
).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
@@ -1873,10 +1873,10 @@ fn binOpImmediate(
)) {
break :blk lhs_reg;
} else {
- break :blk try self.register_manager.allocReg(md.inst);
+ break :blk try self.register_manager.allocReg(md.inst, .{});
}
} else blk: {
- break :blk try self.register_manager.allocReg(null);
+ break :blk try self.register_manager.allocReg(null, .{});
},
};
@@ -1953,7 +1953,7 @@ fn binOpRegister(
break :inst Air.refToIndex(md.lhs).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
break :blk reg;
@@ -1966,7 +1966,7 @@ fn binOpRegister(
break :inst Air.refToIndex(md.rhs).?;
} else null;
- const reg = try self.register_manager.allocReg(track_inst);
+ const reg = try self.register_manager.allocReg(track_inst, .{});
if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
break :blk reg;
@@ -1981,10 +1981,10 @@ fn binOpRegister(
} else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
break :blk rhs_reg;
} else {
- break :blk try self.register_manager.allocReg(md.inst);
+ break :blk try self.register_manager.allocReg(md.inst, .{});
}
} else blk: {
- break :blk try self.register_manager.allocReg(null);
+ break :blk try self.register_manager.allocReg(null, .{});
},
};
@@ -2077,7 +2077,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void {
/// allocated. A second call to `copyToTmpRegister` may return the same register.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
- const reg = try self.register_manager.allocReg(null);
+ const reg = try self.register_manager.allocReg(null, .{});
try self.genSetReg(ty, reg, mcv);
return reg;
}
@@ -2364,7 +2364,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
});
} else {
// Need to allocate a temporary register to load 64-bit immediates.
- const tmp_reg = try self.register_manager.allocReg(null);
+ const tmp_reg = try self.register_manager.allocReg(null, .{});
try self.genSetReg(ty, tmp_reg, .{ .immediate = @truncate(u32, x) });
try self.genSetReg(ty, reg, .{ .immediate = @truncate(u32, x >> 32) });
@@ -2478,7 +2478,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
};
const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
- const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
+ const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
defer for (regs_locks) |reg| {
self.register_manager.unlockReg(reg);
@@ -2717,14 +2717,14 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
},
.stack_offset => |off| {
if (elem_size <= 8) {
- const tmp_reg = try self.register_manager.allocReg(null);
+ const tmp_reg = try self.register_manager.allocReg(null, .{});
const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_reg_lock);
try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
} else {
- const regs = try self.register_manager.allocRegs(3, .{ null, null, null });
+ const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{});
const regs_locks = self.register_manager.lockRegsAssumeUnused(3, regs);
defer for (regs_locks) |reg| {
self.register_manager.unlockReg(reg);
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index aa6d04d5d9..aebbc03e46 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -882,7 +882,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
// TODO check if AVX available
const ptr_bytes: u64 = 32;
if (abi_size <= ptr_bytes) {
- if (self.register_manager.tryAllocReg(inst)) |reg| {
+ if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
return MCValue{ .register = registerAlias(reg, abi_size) };
}
}
@@ -892,7 +892,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
if (abi_size <= ptr_bytes) {
- if (self.register_manager.tryAllocReg(inst)) |reg| {
+ if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
return MCValue{ .register = registerAlias(reg, abi_size) };
}
}
@@ -963,7 +963,7 @@ pub fn spillRegisters(self: *Self, comptime count: comptime_int, registers: [cou
/// allocated. A second call to `copyToTmpRegister` may return the same register.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
- const reg = try self.register_manager.allocReg(null);
+ const reg = try self.register_manager.allocReg(null, .{});
try self.genSetReg(ty, reg, mcv);
return reg;
}
@@ -973,7 +973,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
/// This can have a side effect of spilling instructions to the stack to free up a register.
/// WARNING make sure that the allocated register matches the returned MCValue from an instruction!
fn copyToRegisterWithInstTracking(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue {
- const reg = try self.register_manager.allocReg(reg_owner);
+ const reg = try self.register_manager.allocReg(reg_owner, .{});
try self.genSetReg(ty, reg, mcv);
return MCValue{ .register = reg };
}
@@ -1029,7 +1029,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
};
defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
- const reg = try self.register_manager.allocReg(inst);
+ const reg = try self.register_manager.allocReg(inst, .{});
try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
try self.genSetReg(operand_ty, reg, operand);
break :blk MCValue{ .register = reg };
@@ -1384,7 +1384,7 @@ fn genSetStackTruncatedOverflowCompare(
.unsigned => ty,
};
- const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null });
+ const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{});
const temp_regs_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);
defer for (temp_regs_locks) |rreg| {
self.register_manager.unlockReg(rreg);
@@ -2046,7 +2046,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
defer self.register_manager.unlockReg(offset_reg_lock);
- const addr_reg = try self.register_manager.allocReg(null);
+ const addr_reg = try self.register_manager.allocReg(null, .{});
switch (slice_mcv) {
.stack_offset => |off| {
// mov reg, [rbp - 8]
@@ -2125,7 +2125,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
defer self.register_manager.unlockReg(offset_reg_lock);
- const addr_reg = try self.register_manager.allocReg(null);
+ const addr_reg = try self.register_manager.allocReg(null, .{});
switch (array) {
.register => {
const off = @intCast(i32, try self.allocMem(
@@ -2492,7 +2492,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
},
.stack_offset => |off| {
if (abi_size <= 8) {
- const tmp_reg = try self.register_manager.allocReg(null);
+ const tmp_reg = try self.register_manager.allocReg(null, .{});
try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{});
}
@@ -2693,7 +2693,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
};
defer if (value_lock) |lock| self.register_manager.unlockReg(lock);
- const addr_reg = try self.register_manager.allocReg(null);
+ const addr_reg = try self.register_manager.allocReg(null, .{});
const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
defer self.register_manager.unlockReg(addr_reg_lock);
@@ -2765,7 +2765,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
.memory,
=> {
if (abi_size <= 8) {
- const tmp_reg = try self.register_manager.allocReg(null);
+ const tmp_reg = try self.register_manager.allocReg(null, .{});
const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
defer self.register_manager.unlockReg(tmp_reg_lock);
@@ -2883,7 +2883,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
if (can_reuse_operand) {
break :blk reg;
} else {
- const result_reg = try self.register_manager.allocReg(inst);
+ const result_reg = try self.register_manager.allocReg(inst, .{});
try self.genSetReg(ptr_ty, result_reg, mcv);
break :blk result_reg;
}
@@ -2984,7 +2984,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
defer self.register_manager.unlockReg(reg_lock);
- const dst_reg = try self.register_manager.allocReg(inst);
+ const dst_reg = try self.register_manager.allocReg(inst, .{});
const flags: u2 = switch (mcv) {
.register_overflow_unsigned => 0b10,
.register_overflow_signed => 0b00,
@@ -5362,7 +5362,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
const overflow_bit_ty = ty.structFieldType(1);
const overflow_bit_offset = ty.structFieldOffset(1, self.target.*);
- const tmp_reg = try self.register_manager.allocReg(null);
+ const tmp_reg = try self.register_manager.allocReg(null, .{});
const flags: u2 = switch (mcv) {
.register_overflow_unsigned => 0b10,
.register_overflow_signed => 0b00,
@@ -5580,7 +5580,7 @@ fn genInlineMemcpy(
null;
defer if (dsbase_lock) |lock| self.register_manager.unlockReg(lock);
- const dst_addr_reg = try self.register_manager.allocReg(null);
+ const dst_addr_reg = try self.register_manager.allocReg(null, .{});
switch (dst_ptr) {
.memory,
.got_load,
@@ -5615,7 +5615,7 @@ fn genInlineMemcpy(
const dst_addr_reg_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
defer self.register_manager.unlockReg(dst_addr_reg_lock);
- const src_addr_reg = try self.register_manager.allocReg(null);
+ const src_addr_reg = try self.register_manager.allocReg(null, .{});
switch (src_ptr) {
.memory,
.got_load,
@@ -5650,7 +5650,7 @@ fn genInlineMemcpy(
const src_addr_reg_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
defer self.register_manager.unlockReg(src_addr_reg_lock);
- const regs = try self.register_manager.allocRegs(2, .{ null, null });
+ const regs = try self.register_manager.allocRegs(2, .{ null, null }, .{});
const count_reg = regs[0].to64();
const tmp_reg = regs[1].to8();
@@ -5750,7 +5750,7 @@ fn genInlineMemset(
const rax_lock = self.register_manager.lockRegAssumeUnused(.rax);
defer self.register_manager.unlockReg(rax_lock);
- const addr_reg = try self.register_manager.allocReg(null);
+ const addr_reg = try self.register_manager.allocReg(null, .{});
switch (dst_ptr) {
.memory,
.got_load,
@@ -6018,7 +6018,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
switch (ty.tag()) {
.f32 => return self.fail("TODO genSetReg from memory for f32", .{}),
.f64 => {
- const base_reg = try self.register_manager.allocReg(null);
+ const base_reg = try self.register_manager.allocReg(null, .{});
try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv);
_ = try self.addInst(.{
.tag = .mov_f64,
@@ -6328,7 +6328,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
const src: MCValue = blk: {
switch (src_ptr) {
.got_load, .direct_load, .memory => {
- const reg = try self.register_manager.allocReg(null);
+ const reg = try self.register_manager.allocReg(null, .{});
try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);
_ = try self.addInst(.{
.tag = .mov,
diff --git a/src/register_manager.zig b/src/register_manager.zig
index 2c0502e867..25d8ef8675 100644
--- a/src/register_manager.zig
+++ b/src/register_manager.zig
@@ -173,6 +173,10 @@ pub fn RegisterManager(
return self.locked_registers != 0;
}
+ const AllocOpts = struct {
+ selector_mask: ?FreeRegInt = null,
+ };
+
/// Allocates a specified number of registers, optionally
/// tracking them. Returns `null` if not enough registers are
/// free.
@@ -180,7 +184,9 @@ pub fn RegisterManager(
self: *Self,
comptime count: comptime_int,
insts: [count]?Air.Inst.Index,
+ opts: AllocOpts,
) ?[count]Register {
+ _ = opts;
comptime assert(count > 0 and count <= tracked_registers.len);
const free_and_not_locked_registers = self.free_registers & ~self.locked_registers;
@@ -216,8 +222,8 @@ pub fn RegisterManager(
/// 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 {
- return if (tryAllocRegs(self, 1, .{inst})) |regs| regs[0] else null;
+ pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) ?Register {
+ return if (tryAllocRegs(self, 1, .{inst}, opts)) |regs| regs[0] else null;
}
/// Allocates a specified number of registers, optionally
@@ -227,12 +233,13 @@ pub fn RegisterManager(
self: *Self,
comptime count: comptime_int,
insts: [count]?Air.Inst.Index,
+ opts: AllocOpts,
) AllocateRegistersError![count]Register {
comptime assert(count > 0 and count <= tracked_registers.len);
const locked_registers_count = @popCount(FreeRegInt, self.locked_registers);
if (count > tracked_registers.len - locked_registers_count) return error.OutOfRegisters;
- const result = self.tryAllocRegs(count, insts) orelse blk: {
+ const result = self.tryAllocRegs(count, insts, opts) orelse blk: {
// We'll take over the first count registers. Spill
// the instructions that were previously there to a
// stack allocations.
@@ -275,8 +282,8 @@ pub fn RegisterManager(
/// Allocates a register and optionally tracks it with a
/// corresponding instruction.
- pub fn allocReg(self: *Self, inst: ?Air.Inst.Index) AllocateRegistersError!Register {
- return (try self.allocRegs(1, .{inst}))[0];
+ pub fn allocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) AllocateRegistersError!Register {
+ return (try self.allocRegs(1, .{inst}, opts))[0];
}
/// Spills the register if it is currently allocated. If a