authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-18 11:15:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-19 19:39:32+02:00
log549174f743d3b56544e2d3d6993f4d43bba1e7fd
tree90be8877e03f93fd30a95120fd8db774e53b4898
parent9e5c8cb008f75c2e570a0e48d5d014e936c103ca

regalloc: allow for optional selector mask when allocating


6 files changed, 113 insertions(+), 106 deletions(-)

src/arch/aarch64/CodeGen.zig+28-28
......@@ -888,7 +888,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
888888 if (reg_ok) {
889889 // Make sure the type can fit in a register before we try to allocate one.
890890 if (abi_size <= 8) {
891 if (self.register_manager.tryAllocReg(inst)) |reg| {
891 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
892892 return MCValue{ .register = registerAlias(reg, abi_size) };
893893 }
894894 }
......@@ -951,7 +951,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
951951/// allocated. A second call to `copyToTmpRegister` may return the same register.
952952/// This can have a side effect of spilling instructions to the stack to free up a register.
953953fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
954 const raw_reg = try self.register_manager.allocReg(null);
954 const raw_reg = try self.register_manager.allocReg(null, .{});
955955 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
956956 try self.genSetReg(ty, reg, mcv);
957957 return reg;
......@@ -961,7 +961,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
961961/// `reg_owner` is the instruction that gets associated with the register in the register table.
962962/// This can have a side effect of spilling instructions to the stack to free up a register.
963963fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
964 const raw_reg = try self.register_manager.allocReg(reg_owner);
964 const raw_reg = try self.register_manager.allocReg(reg_owner, .{});
965965 const ty = self.air.typeOfIndex(reg_owner);
966966 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
967967 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
......@@ -1074,11 +1074,11 @@ fn trunc(
10741074 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
10751075 break :blk registerAlias(operand_reg, dest_ty.abiSize(self.target.*));
10761076 } else {
1077 const raw_reg = try self.register_manager.allocReg(inst);
1077 const raw_reg = try self.register_manager.allocReg(inst, .{});
10781078 break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));
10791079 }
10801080 } else blk: {
1081 const raw_reg = try self.register_manager.allocReg(null);
1081 const raw_reg = try self.register_manager.allocReg(null, .{});
10821082 break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));
10831083 };
10841084
......@@ -1160,7 +1160,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
11601160 break :blk op_reg;
11611161 }
11621162
1163 const raw_reg = try self.register_manager.allocReg(null);
1163 const raw_reg = try self.register_manager.allocReg(null, .{});
11641164 break :blk raw_reg.to32();
11651165 };
11661166
......@@ -1193,7 +1193,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
11931193 break :blk op_reg;
11941194 }
11951195
1196 const raw_reg = try self.register_manager.allocReg(null);
1196 const raw_reg = try self.register_manager.allocReg(null, .{});
11971197 break :blk registerAlias(raw_reg, operand_ty.abiSize(self.target.*));
11981198 };
11991199
......@@ -1293,7 +1293,7 @@ fn binOpRegister(
12931293 break :inst Air.refToIndex(md.lhs).?;
12941294 } else null;
12951295
1296 const raw_reg = try self.register_manager.allocReg(track_inst);
1296 const raw_reg = try self.register_manager.allocReg(track_inst, .{});
12971297 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
12981298
12991299 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
......@@ -1308,7 +1308,7 @@ fn binOpRegister(
13081308 break :inst Air.refToIndex(md.rhs).?;
13091309 } else null;
13101310
1311 const raw_reg = try self.register_manager.allocReg(track_inst);
1311 const raw_reg = try self.register_manager.allocReg(track_inst, .{});
13121312 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
13131313
13141314 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
......@@ -1326,11 +1326,11 @@ fn binOpRegister(
13261326 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
13271327 break :blk rhs_reg;
13281328 } else {
1329 const raw_reg = try self.register_manager.allocReg(md.inst);
1329 const raw_reg = try self.register_manager.allocReg(md.inst, .{});
13301330 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
13311331 }
13321332 } else blk: {
1333 const raw_reg = try self.register_manager.allocReg(null);
1333 const raw_reg = try self.register_manager.allocReg(null, .{});
13341334 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
13351335 },
13361336 };
......@@ -1431,7 +1431,7 @@ fn binOpImmediate(
14311431 ).?;
14321432 } else null;
14331433
1434 const raw_reg = try self.register_manager.allocReg(track_inst);
1434 const raw_reg = try self.register_manager.allocReg(track_inst, .{});
14351435 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
14361436
14371437 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
......@@ -1452,11 +1452,11 @@ fn binOpImmediate(
14521452 )) {
14531453 break :blk lhs_reg;
14541454 } else {
1455 const raw_reg = try self.register_manager.allocReg(md.inst);
1455 const raw_reg = try self.register_manager.allocReg(md.inst, .{});
14561456 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
14571457 }
14581458 } else blk: {
1459 const raw_reg = try self.register_manager.allocReg(null);
1459 const raw_reg = try self.register_manager.allocReg(null, .{});
14601460 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
14611461 },
14621462 };
......@@ -1872,7 +1872,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
18721872 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
18731873 defer self.register_manager.unlockReg(dest_reg_lock);
18741874
1875 const raw_truncated_reg = try self.register_manager.allocReg(null);
1875 const raw_truncated_reg = try self.register_manager.allocReg(null, .{});
18761876 const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*));
18771877 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
18781878 defer self.register_manager.unlockReg(truncated_reg_lock);
......@@ -1983,7 +1983,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
19831983 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
19841984 defer self.register_manager.unlockReg(dest_reg_lock);
19851985
1986 const truncated_reg = try self.register_manager.allocReg(null);
1986 const truncated_reg = try self.register_manager.allocReg(null, .{});
19871987 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
19881988 defer self.register_manager.unlockReg(truncated_reg_lock);
19891989
......@@ -2048,7 +2048,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
20482048 defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
20492049
20502050 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
2051 const raw_reg = try self.register_manager.allocReg(null);
2051 const raw_reg = try self.register_manager.allocReg(null, .{});
20522052 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
20532053 break :blk reg;
20542054 };
......@@ -2056,7 +2056,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
20562056 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
20572057
20582058 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
2059 const raw_reg = try self.register_manager.allocReg(null);
2059 const raw_reg = try self.register_manager.allocReg(null, .{});
20602060 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
20612061 break :blk reg;
20622062 };
......@@ -2067,7 +2067,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
20672067 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
20682068
20692069 const dest_reg = blk: {
2070 const raw_reg = try self.register_manager.allocReg(null);
2070 const raw_reg = try self.register_manager.allocReg(null, .{});
20712071 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
20722072 break :blk reg;
20732073 };
......@@ -2086,7 +2086,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
20862086 } },
20872087 });
20882088
2089 const dest_high_reg = try self.register_manager.allocReg(null);
2089 const dest_high_reg = try self.register_manager.allocReg(null, .{});
20902090 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
20912091 defer self.register_manager.unlockReg(dest_high_reg_lock);
20922092
......@@ -2136,7 +2136,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
21362136 }
21372137 },
21382138 .unsigned => {
2139 const dest_high_reg = try self.register_manager.allocReg(null);
2139 const dest_high_reg = try self.register_manager.allocReg(null, .{});
21402140 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
21412141 defer self.register_manager.unlockReg(dest_high_reg_lock);
21422142
......@@ -2192,7 +2192,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
21922192 },
21932193 }
21942194
2195 const truncated_reg = try self.register_manager.allocReg(null);
2195 const truncated_reg = try self.register_manager.allocReg(null, .{});
21962196 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
21972197 defer self.register_manager.unlockReg(truncated_reg_lock);
21982198
......@@ -2663,7 +2663,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
26632663 },
26642664 .stack_offset => |off| {
26652665 if (elem_size <= 8) {
2666 const raw_tmp_reg = try self.register_manager.allocReg(null);
2666 const raw_tmp_reg = try self.register_manager.allocReg(null, .{});
26672667 const tmp_reg = registerAlias(raw_tmp_reg, elem_size);
26682668 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
26692669 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
26722672 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
26732673 } else {
26742674 // TODO optimize the register allocation
2675 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
2675 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
26762676 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
26772677 defer for (regs_locks) |reg| {
26782678 self.register_manager.unlockReg(reg);
......@@ -2887,7 +2887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28872887 },
28882888 else => {
28892889 if (abi_size <= 8) {
2890 const raw_tmp_reg = try self.register_manager.allocReg(null);
2890 const raw_tmp_reg = try self.register_manager.allocReg(null, .{});
28912891 const tmp_reg = registerAlias(raw_tmp_reg, abi_size);
28922892 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
28932893 defer self.register_manager.unlockReg(tmp_reg_lock);
......@@ -3002,7 +3002,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
30023002 // TODO return special MCValue condition flags
30033003 // get overflow bit: set register to C flag
30043004 // resp. V flag
3005 const raw_dest_reg = try self.register_manager.allocReg(null);
3005 const raw_dest_reg = try self.register_manager.allocReg(null, .{});
30063006 const dest_reg = raw_dest_reg.to32();
30073007
30083008 // C flag: cset reg, cs
......@@ -4065,7 +4065,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
40654065
40664066 const overflow_bit_ty = ty.structFieldType(1);
40674067 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
4068 const raw_cond_reg = try self.register_manager.allocReg(null);
4068 const raw_cond_reg = try self.register_manager.allocReg(null, .{});
40694069 const cond_reg = registerAlias(
40704070 raw_cond_reg,
40714071 @intCast(u32, overflow_bit_ty.abiSize(self.target.*)),
......@@ -4113,7 +4113,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
41134113 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
41144114
41154115 // TODO call extern memcpy
4116 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
4116 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
41174117 const regs_locks = self.register_manager.lockRegsAssumeUnused(5, regs);
41184118 defer for (regs_locks) |reg| {
41194119 self.register_manager.unlockReg(reg);
src/arch/arm/CodeGen.zig+32-32
......@@ -874,7 +874,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
874874 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
875875 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
876876 if (abi_size <= ptr_bytes) {
877 if (self.register_manager.tryAllocReg(inst)) |reg| {
877 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
878878 return MCValue{ .register = reg };
879879 }
880880 }
......@@ -939,7 +939,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
939939/// allocated. A second call to `copyToTmpRegister` may return the same register.
940940/// This can have a side effect of spilling instructions to the stack to free up a register.
941941fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
942 const reg = try self.register_manager.allocReg(null);
942 const reg = try self.register_manager.allocReg(null, .{});
943943 try self.genSetReg(ty, reg, mcv);
944944 return reg;
945945}
......@@ -948,7 +948,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
948948/// `reg_owner` is the instruction that gets associated with the register in the register table.
949949/// This can have a side effect of spilling instructions to the stack to free up a register.
950950fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
951 const reg = try self.register_manager.allocReg(reg_owner);
951 const reg = try self.register_manager.allocReg(reg_owner, .{});
952952 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
953953 return MCValue{ .register = reg };
954954}
......@@ -1065,9 +1065,9 @@ fn trunc(
10651065 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
10661066 break :blk operand_reg;
10671067 } else {
1068 break :blk try self.register_manager.allocReg(inst);
1068 break :blk try self.register_manager.allocReg(inst, .{});
10691069 }
1070 } else try self.register_manager.allocReg(null);
1070 } else try self.register_manager.allocReg(null, .{});
10711071
10721072 switch (info_b.bits) {
10731073 32 => {
......@@ -1153,7 +1153,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
11531153 break :blk op_reg;
11541154 }
11551155
1156 break :blk try self.register_manager.allocReg(null);
1156 break :blk try self.register_manager.allocReg(null, .{});
11571157 };
11581158
11591159 _ = try self.addInst(.{
......@@ -1183,7 +1183,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
11831183 break :blk op_reg;
11841184 }
11851185
1186 break :blk try self.register_manager.allocReg(null);
1186 break :blk try self.register_manager.allocReg(null, .{});
11871187 };
11881188
11891189 _ = try self.addInst(.{
......@@ -1254,9 +1254,9 @@ fn minMax(
12541254 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
12551255 break :blk rhs_reg;
12561256 } else {
1257 break :blk try self.register_manager.allocReg(inst);
1257 break :blk try self.register_manager.allocReg(inst, .{});
12581258 }
1259 } else try self.register_manager.allocReg(null);
1259 } else try self.register_manager.allocReg(null, .{});
12601260
12611261 // lhs == reg should have been checked by airMinMax
12621262 //
......@@ -1438,7 +1438,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
14381438 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
14391439 defer self.register_manager.unlockReg(dest_reg_lock);
14401440
1441 const truncated_reg = try self.register_manager.allocReg(null);
1441 const truncated_reg = try self.register_manager.allocReg(null, .{});
14421442 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
14431443 defer self.register_manager.unlockReg(truncated_reg_lock);
14441444
......@@ -1543,7 +1543,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
15431543 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
15441544 defer self.register_manager.unlockReg(dest_reg_lock);
15451545
1546 const truncated_reg = try self.register_manager.allocReg(null);
1546 const truncated_reg = try self.register_manager.allocReg(null, .{});
15471547 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
15481548 defer self.register_manager.unlockReg(truncated_reg_lock);
15491549
......@@ -1582,18 +1582,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
15821582 const lhs_reg = if (lhs_is_register)
15831583 lhs.register
15841584 else
1585 try self.register_manager.allocReg(null);
1585 try self.register_manager.allocReg(null, .{});
15861586 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
15871587 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
15881588
15891589 const rhs_reg = if (rhs_is_register)
15901590 rhs.register
15911591 else
1592 try self.register_manager.allocReg(null);
1592 try self.register_manager.allocReg(null, .{});
15931593 const new_rhs_lock = self.register_manager.lockReg(rhs_reg);
15941594 defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
15951595
1596 const dest_regs = try self.register_manager.allocRegs(2, .{ null, null });
1596 const dest_regs = try self.register_manager.allocRegs(2, .{ null, null }, .{});
15971597 const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs);
15981598 defer for (dest_regs_locks) |reg| {
15991599 self.register_manager.unlockReg(reg);
......@@ -1604,7 +1604,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
16041604 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
16051605 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
16061606
1607 const truncated_reg = try self.register_manager.allocReg(null);
1607 const truncated_reg = try self.register_manager.allocReg(null, .{});
16081608 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
16091609 defer self.register_manager.unlockReg(truncated_reg_lock);
16101610
......@@ -2026,7 +2026,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
20262026 const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg);
20272027 defer self.register_manager.unlockReg(base_reg_lock);
20282028
2029 const dst_reg = try self.register_manager.allocReg(inst);
2029 const dst_reg = try self.register_manager.allocReg(inst, .{});
20302030 const dst_mcv = MCValue{ .register = dst_reg };
20312031 const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
20322032 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
22342234 },
22352235 .stack_offset => |off| {
22362236 if (elem_size <= 4) {
2237 const tmp_reg = try self.register_manager.allocReg(null);
2237 const tmp_reg = try self.register_manager.allocReg(null, .{});
22382238 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
22392239 defer self.register_manager.unlockReg(tmp_reg_lock);
22402240
......@@ -2242,7 +2242,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
22422242 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
22432243 } else {
22442244 // TODO optimize the register allocation
2245 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
2245 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
22462246 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
22472247 defer for (regs_locks) |reg_locked| {
22482248 self.register_manager.unlockReg(reg_locked);
......@@ -2271,7 +2271,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
22712271 .stack_offset,
22722272 .stack_argument_offset,
22732273 => {
2274 const reg = try self.register_manager.allocReg(null);
2274 const reg = try self.register_manager.allocReg(null, .{});
22752275 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
22762276 defer self.register_manager.unlockReg(reg_lock);
22772277
......@@ -2338,14 +2338,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
23382338 },
23392339 else => {
23402340 if (elem_size <= 4) {
2341 const tmp_reg = try self.register_manager.allocReg(null);
2341 const tmp_reg = try self.register_manager.allocReg(null, .{});
23422342 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
23432343 defer self.register_manager.unlockReg(tmp_reg_lock);
23442344
23452345 try self.genSetReg(value_ty, tmp_reg, value);
23462346 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
23472347 } else {
2348 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
2348 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
23492349 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
23502350 defer for (regs_locks) |reg| {
23512351 self.register_manager.unlockReg(reg);
......@@ -2487,7 +2487,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
24872487 1 => {
24882488 // get overflow bit: set register to C flag
24892489 // resp. V flag
2490 const dest_reg = try self.register_manager.allocReg(null);
2490 const dest_reg = try self.register_manager.allocReg(null, .{});
24912491
24922492 // mov reg, #0
24932493 _ = try self.addInst(.{
......@@ -2567,7 +2567,7 @@ fn binOpRegister(
25672567 break :inst Air.refToIndex(md.lhs).?;
25682568 } else null;
25692569
2570 const reg = try self.register_manager.allocReg(track_inst);
2570 const reg = try self.register_manager.allocReg(track_inst, .{});
25712571
25722572 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
25732573
......@@ -2581,7 +2581,7 @@ fn binOpRegister(
25812581 break :inst Air.refToIndex(md.rhs).?;
25822582 } else null;
25832583
2584 const reg = try self.register_manager.allocReg(track_inst);
2584 const reg = try self.register_manager.allocReg(track_inst, .{});
25852585
25862586 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
25872587
......@@ -2598,9 +2598,9 @@ fn binOpRegister(
25982598 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
25992599 break :blk rhs_reg;
26002600 } else {
2601 break :blk try self.register_manager.allocReg(md.inst);
2601 break :blk try self.register_manager.allocReg(md.inst, .{});
26022602 }
2603 } else try self.register_manager.allocReg(null),
2603 } else try self.register_manager.allocReg(null, .{}),
26042604 };
26052605
26062606 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
......@@ -2684,7 +2684,7 @@ fn binOpImmediate(
26842684 ).?;
26852685 } else null;
26862686
2687 const reg = try self.register_manager.allocReg(track_inst);
2687 const reg = try self.register_manager.allocReg(track_inst, .{});
26882688
26892689 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
26902690
......@@ -2704,9 +2704,9 @@ fn binOpImmediate(
27042704 )) {
27052705 break :blk lhs_reg;
27062706 } else {
2707 break :blk try self.register_manager.allocReg(md.inst);
2707 break :blk try self.register_manager.allocReg(md.inst, .{});
27082708 }
2709 } else try self.register_manager.allocReg(null),
2709 } else try self.register_manager.allocReg(null, .{}),
27102710 };
27112711
27122712 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
43634363
43644364 const overflow_bit_ty = ty.structFieldType(1);
43654365 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
4366 const cond_reg = try self.register_manager.allocReg(null);
4366 const cond_reg = try self.register_manager.allocReg(null, .{});
43674367
43684368 // C flag: movcs reg, #1
43694369 // V flag: movvs reg, #1
......@@ -4408,7 +4408,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
44084408 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
44094409
44104410 // TODO call extern memcpy
4411 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
4411 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
44124412 const src_reg = regs[0];
44134413 const dst_reg = regs[1];
44144414 const len_reg = regs[2];
......@@ -4782,7 +4782,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
47824782 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
47834783
47844784 // TODO call extern memcpy
4785 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
4785 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
47864786 const src_reg = regs[0];
47874787 const dst_reg = regs[1];
47884788 const len_reg = regs[2];
src/arch/riscv64/CodeGen.zig+8-8
......@@ -803,7 +803,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
803803 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
804804 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
805805 if (abi_size <= ptr_bytes) {
806 if (self.register_manager.tryAllocReg(inst)) |reg| {
806 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
807807 return MCValue{ .register = reg };
808808 }
809809 }
......@@ -826,7 +826,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
826826/// allocated. A second call to `copyToTmpRegister` may return the same register.
827827/// This can have a side effect of spilling instructions to the stack to free up a register.
828828fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
829 const reg = try self.register_manager.allocReg(null);
829 const reg = try self.register_manager.allocReg(null, .{});
830830 try self.genSetReg(ty, reg, mcv);
831831 return reg;
832832}
......@@ -835,7 +835,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
835835/// `reg_owner` is the instruction that gets associated with the register in the register table.
836836/// This can have a side effect of spilling instructions to the stack to free up a register.
837837fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
838 const reg = try self.register_manager.allocReg(reg_owner);
838 const reg = try self.register_manager.allocReg(reg_owner, .{});
839839 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
840840 return MCValue{ .register = reg };
841841}
......@@ -958,7 +958,7 @@ fn binOpRegister(
958958 break :inst Air.refToIndex(bin_op.lhs).?;
959959 } else null;
960960
961 const reg = try self.register_manager.allocReg(track_inst);
961 const reg = try self.register_manager.allocReg(track_inst, .{});
962962
963963 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
964964
......@@ -973,7 +973,7 @@ fn binOpRegister(
973973 break :inst Air.refToIndex(bin_op.rhs).?;
974974 } else null;
975975
976 const reg = try self.register_manager.allocReg(track_inst);
976 const reg = try self.register_manager.allocReg(track_inst, .{});
977977
978978 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
979979
......@@ -990,9 +990,9 @@ fn binOpRegister(
990990 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
991991 break :blk rhs_reg;
992992 } else {
993 break :blk try self.register_manager.allocReg(inst);
993 break :blk try self.register_manager.allocReg(inst, .{});
994994 }
995 } else try self.register_manager.allocReg(null);
995 } else try self.register_manager.allocReg(null, .{});
996996
997997 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
998998 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
14821482 .memory,
14831483 .stack_offset,
14841484 => {
1485 const reg = try self.register_manager.allocReg(null);
1485 const reg = try self.register_manager.allocReg(null, .{});
14861486 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
14871487 defer self.register_manager.unlockReg(reg_lock);
14881488
src/arch/sparc64/CodeGen.zig+13-13
......@@ -1613,7 +1613,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
16131613 if (reg_ok) {
16141614 // Make sure the type can fit in a register before we try to allocate one.
16151615 if (abi_size <= 8) {
1616 if (self.register_manager.tryAllocReg(inst)) |reg| {
1616 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
16171617 return MCValue{ .register = reg };
16181618 }
16191619 }
......@@ -1854,7 +1854,7 @@ fn binOpImmediate(
18541854 ).?;
18551855 } else null;
18561856
1857 const reg = try self.register_manager.allocReg(track_inst);
1857 const reg = try self.register_manager.allocReg(track_inst, .{});
18581858
18591859 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
18601860
......@@ -1873,10 +1873,10 @@ fn binOpImmediate(
18731873 )) {
18741874 break :blk lhs_reg;
18751875 } else {
1876 break :blk try self.register_manager.allocReg(md.inst);
1876 break :blk try self.register_manager.allocReg(md.inst, .{});
18771877 }
18781878 } else blk: {
1879 break :blk try self.register_manager.allocReg(null);
1879 break :blk try self.register_manager.allocReg(null, .{});
18801880 },
18811881 };
18821882
......@@ -1953,7 +1953,7 @@ fn binOpRegister(
19531953 break :inst Air.refToIndex(md.lhs).?;
19541954 } else null;
19551955
1956 const reg = try self.register_manager.allocReg(track_inst);
1956 const reg = try self.register_manager.allocReg(track_inst, .{});
19571957 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
19581958
19591959 break :blk reg;
......@@ -1966,7 +1966,7 @@ fn binOpRegister(
19661966 break :inst Air.refToIndex(md.rhs).?;
19671967 } else null;
19681968
1969 const reg = try self.register_manager.allocReg(track_inst);
1969 const reg = try self.register_manager.allocReg(track_inst, .{});
19701970 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
19711971
19721972 break :blk reg;
......@@ -1981,10 +1981,10 @@ fn binOpRegister(
19811981 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
19821982 break :blk rhs_reg;
19831983 } else {
1984 break :blk try self.register_manager.allocReg(md.inst);
1984 break :blk try self.register_manager.allocReg(md.inst, .{});
19851985 }
19861986 } else blk: {
1987 break :blk try self.register_manager.allocReg(null);
1987 break :blk try self.register_manager.allocReg(null, .{});
19881988 },
19891989 };
19901990
......@@ -2077,7 +2077,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void {
20772077/// allocated. A second call to `copyToTmpRegister` may return the same register.
20782078/// This can have a side effect of spilling instructions to the stack to free up a register.
20792079fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
2080 const reg = try self.register_manager.allocReg(null);
2080 const reg = try self.register_manager.allocReg(null, .{});
20812081 try self.genSetReg(ty, reg, mcv);
20822082 return reg;
20832083}
......@@ -2364,7 +2364,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
23642364 });
23652365 } else {
23662366 // Need to allocate a temporary register to load 64-bit immediates.
2367 const tmp_reg = try self.register_manager.allocReg(null);
2367 const tmp_reg = try self.register_manager.allocReg(null, .{});
23682368
23692369 try self.genSetReg(ty, tmp_reg, .{ .immediate = @truncate(u32, x) });
23702370 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
24782478 };
24792479 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
24802480
2481 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
2481 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
24822482 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
24832483 defer for (regs_locks) |reg| {
24842484 self.register_manager.unlockReg(reg);
......@@ -2717,14 +2717,14 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
27172717 },
27182718 .stack_offset => |off| {
27192719 if (elem_size <= 8) {
2720 const tmp_reg = try self.register_manager.allocReg(null);
2720 const tmp_reg = try self.register_manager.allocReg(null, .{});
27212721 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
27222722 defer self.register_manager.unlockReg(tmp_reg_lock);
27232723
27242724 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
27252725 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
27262726 } else {
2727 const regs = try self.register_manager.allocRegs(3, .{ null, null, null });
2727 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{});
27282728 const regs_locks = self.register_manager.lockRegsAssumeUnused(3, regs);
27292729 defer for (regs_locks) |reg| {
27302730 self.register_manager.unlockReg(reg);
src/arch/x86_64/CodeGen.zig+20-20
......@@ -882,7 +882,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
882882 // TODO check if AVX available
883883 const ptr_bytes: u64 = 32;
884884 if (abi_size <= ptr_bytes) {
885 if (self.register_manager.tryAllocReg(inst)) |reg| {
885 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
886886 return MCValue{ .register = registerAlias(reg, abi_size) };
887887 }
888888 }
......@@ -892,7 +892,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
892892 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
893893 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
894894 if (abi_size <= ptr_bytes) {
895 if (self.register_manager.tryAllocReg(inst)) |reg| {
895 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
896896 return MCValue{ .register = registerAlias(reg, abi_size) };
897897 }
898898 }
......@@ -963,7 +963,7 @@ pub fn spillRegisters(self: *Self, comptime count: comptime_int, registers: [cou
963963/// allocated. A second call to `copyToTmpRegister` may return the same register.
964964/// This can have a side effect of spilling instructions to the stack to free up a register.
965965fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
966 const reg = try self.register_manager.allocReg(null);
966 const reg = try self.register_manager.allocReg(null, .{});
967967 try self.genSetReg(ty, reg, mcv);
968968 return reg;
969969}
......@@ -973,7 +973,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
973973/// This can have a side effect of spilling instructions to the stack to free up a register.
974974/// WARNING make sure that the allocated register matches the returned MCValue from an instruction!
975975fn copyToRegisterWithInstTracking(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue {
976 const reg = try self.register_manager.allocReg(reg_owner);
976 const reg = try self.register_manager.allocReg(reg_owner, .{});
977977 try self.genSetReg(ty, reg, mcv);
978978 return MCValue{ .register = reg };
979979}
......@@ -1029,7 +1029,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
10291029 };
10301030 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
10311031
1032 const reg = try self.register_manager.allocReg(inst);
1032 const reg = try self.register_manager.allocReg(inst, .{});
10331033 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
10341034 try self.genSetReg(operand_ty, reg, operand);
10351035 break :blk MCValue{ .register = reg };
......@@ -1384,7 +1384,7 @@ fn genSetStackTruncatedOverflowCompare(
13841384 .unsigned => ty,
13851385 };
13861386
1387 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null });
1387 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{});
13881388 const temp_regs_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);
13891389 defer for (temp_regs_locks) |rreg| {
13901390 self.register_manager.unlockReg(rreg);
......@@ -2046,7 +2046,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
20462046 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
20472047 defer self.register_manager.unlockReg(offset_reg_lock);
20482048
2049 const addr_reg = try self.register_manager.allocReg(null);
2049 const addr_reg = try self.register_manager.allocReg(null, .{});
20502050 switch (slice_mcv) {
20512051 .stack_offset => |off| {
20522052 // mov reg, [rbp - 8]
......@@ -2125,7 +2125,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
21252125 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
21262126 defer self.register_manager.unlockReg(offset_reg_lock);
21272127
2128 const addr_reg = try self.register_manager.allocReg(null);
2128 const addr_reg = try self.register_manager.allocReg(null, .{});
21292129 switch (array) {
21302130 .register => {
21312131 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
24922492 },
24932493 .stack_offset => |off| {
24942494 if (abi_size <= 8) {
2495 const tmp_reg = try self.register_manager.allocReg(null);
2495 const tmp_reg = try self.register_manager.allocReg(null, .{});
24962496 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
24972497 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{});
24982498 }
......@@ -2693,7 +2693,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
26932693 };
26942694 defer if (value_lock) |lock| self.register_manager.unlockReg(lock);
26952695
2696 const addr_reg = try self.register_manager.allocReg(null);
2696 const addr_reg = try self.register_manager.allocReg(null, .{});
26972697 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
26982698 defer self.register_manager.unlockReg(addr_reg_lock);
26992699
......@@ -2765,7 +2765,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
27652765 .memory,
27662766 => {
27672767 if (abi_size <= 8) {
2768 const tmp_reg = try self.register_manager.allocReg(null);
2768 const tmp_reg = try self.register_manager.allocReg(null, .{});
27692769 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
27702770 defer self.register_manager.unlockReg(tmp_reg_lock);
27712771
......@@ -2883,7 +2883,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
28832883 if (can_reuse_operand) {
28842884 break :blk reg;
28852885 } else {
2886 const result_reg = try self.register_manager.allocReg(inst);
2886 const result_reg = try self.register_manager.allocReg(inst, .{});
28872887 try self.genSetReg(ptr_ty, result_reg, mcv);
28882888 break :blk result_reg;
28892889 }
......@@ -2984,7 +2984,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
29842984 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
29852985 defer self.register_manager.unlockReg(reg_lock);
29862986
2987 const dst_reg = try self.register_manager.allocReg(inst);
2987 const dst_reg = try self.register_manager.allocReg(inst, .{});
29882988 const flags: u2 = switch (mcv) {
29892989 .register_overflow_unsigned => 0b10,
29902990 .register_overflow_signed => 0b00,
......@@ -5362,7 +5362,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
53625362
53635363 const overflow_bit_ty = ty.structFieldType(1);
53645364 const overflow_bit_offset = ty.structFieldOffset(1, self.target.*);
5365 const tmp_reg = try self.register_manager.allocReg(null);
5365 const tmp_reg = try self.register_manager.allocReg(null, .{});
53665366 const flags: u2 = switch (mcv) {
53675367 .register_overflow_unsigned => 0b10,
53685368 .register_overflow_signed => 0b00,
......@@ -5580,7 +5580,7 @@ fn genInlineMemcpy(
55805580 null;
55815581 defer if (dsbase_lock) |lock| self.register_manager.unlockReg(lock);
55825582
5583 const dst_addr_reg = try self.register_manager.allocReg(null);
5583 const dst_addr_reg = try self.register_manager.allocReg(null, .{});
55845584 switch (dst_ptr) {
55855585 .memory,
55865586 .got_load,
......@@ -5615,7 +5615,7 @@ fn genInlineMemcpy(
56155615 const dst_addr_reg_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
56165616 defer self.register_manager.unlockReg(dst_addr_reg_lock);
56175617
5618 const src_addr_reg = try self.register_manager.allocReg(null);
5618 const src_addr_reg = try self.register_manager.allocReg(null, .{});
56195619 switch (src_ptr) {
56205620 .memory,
56215621 .got_load,
......@@ -5650,7 +5650,7 @@ fn genInlineMemcpy(
56505650 const src_addr_reg_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
56515651 defer self.register_manager.unlockReg(src_addr_reg_lock);
56525652
5653 const regs = try self.register_manager.allocRegs(2, .{ null, null });
5653 const regs = try self.register_manager.allocRegs(2, .{ null, null }, .{});
56545654 const count_reg = regs[0].to64();
56555655 const tmp_reg = regs[1].to8();
56565656
......@@ -5750,7 +5750,7 @@ fn genInlineMemset(
57505750 const rax_lock = self.register_manager.lockRegAssumeUnused(.rax);
57515751 defer self.register_manager.unlockReg(rax_lock);
57525752
5753 const addr_reg = try self.register_manager.allocReg(null);
5753 const addr_reg = try self.register_manager.allocReg(null, .{});
57545754 switch (dst_ptr) {
57555755 .memory,
57565756 .got_load,
......@@ -6018,7 +6018,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
60186018 switch (ty.tag()) {
60196019 .f32 => return self.fail("TODO genSetReg from memory for f32", .{}),
60206020 .f64 => {
6021 const base_reg = try self.register_manager.allocReg(null);
6021 const base_reg = try self.register_manager.allocReg(null, .{});
60226022 try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv);
60236023 _ = try self.addInst(.{
60246024 .tag = .mov_f64,
......@@ -6328,7 +6328,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
63286328 const src: MCValue = blk: {
63296329 switch (src_ptr) {
63306330 .got_load, .direct_load, .memory => {
6331 const reg = try self.register_manager.allocReg(null);
6331 const reg = try self.register_manager.allocReg(null, .{});
63326332 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);
63336333 _ = try self.addInst(.{
63346334 .tag = .mov,
src/register_manager.zig+12-5
......@@ -173,6 +173,10 @@ pub fn RegisterManager(
173173 return self.locked_registers != 0;
174174 }
175175
176 const AllocOpts = struct {
177 selector_mask: ?FreeRegInt = null,
178 };
179
176180 /// Allocates a specified number of registers, optionally
177181 /// tracking them. Returns `null` if not enough registers are
178182 /// free.
......@@ -180,7 +184,9 @@ pub fn RegisterManager(
180184 self: *Self,
181185 comptime count: comptime_int,
182186 insts: [count]?Air.Inst.Index,
187 opts: AllocOpts,
183188 ) ?[count]Register {
189 _ = opts;
184190 comptime assert(count > 0 and count <= tracked_registers.len);
185191
186192 const free_and_not_locked_registers = self.free_registers & ~self.locked_registers;
......@@ -216,8 +222,8 @@ pub fn RegisterManager(
216222 /// Allocates a register and optionally tracks it with a
217223 /// corresponding instruction. Returns `null` if all registers
218224 /// are allocated.
219 pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index) ?Register {
220 return if (tryAllocRegs(self, 1, .{inst})) |regs| regs[0] else null;
225 pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) ?Register {
226 return if (tryAllocRegs(self, 1, .{inst}, opts)) |regs| regs[0] else null;
221227 }
222228
223229 /// Allocates a specified number of registers, optionally
......@@ -227,12 +233,13 @@ pub fn RegisterManager(
227233 self: *Self,
228234 comptime count: comptime_int,
229235 insts: [count]?Air.Inst.Index,
236 opts: AllocOpts,
230237 ) AllocateRegistersError![count]Register {
231238 comptime assert(count > 0 and count <= tracked_registers.len);
232239 const locked_registers_count = @popCount(FreeRegInt, self.locked_registers);
233240 if (count > tracked_registers.len - locked_registers_count) return error.OutOfRegisters;
234241
235 const result = self.tryAllocRegs(count, insts) orelse blk: {
242 const result = self.tryAllocRegs(count, insts, opts) orelse blk: {
236243 // We'll take over the first count registers. Spill
237244 // the instructions that were previously there to a
238245 // stack allocations.
......@@ -275,8 +282,8 @@ pub fn RegisterManager(
275282
276283 /// Allocates a register and optionally tracks it with a
277284 /// corresponding instruction.
278 pub fn allocReg(self: *Self, inst: ?Air.Inst.Index) AllocateRegistersError!Register {
279 return (try self.allocRegs(1, .{inst}))[0];
285 pub fn allocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) AllocateRegistersError!Register {
286 return (try self.allocRegs(1, .{inst}, opts))[0];
280287 }
281288
282289 /// Spills the register if it is currently allocated. If a