authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-24 00:03:39-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-24 17:57:58-04:00
logc604111e22cb2f41e3151b1062e19035f35a6dec
treed72837dacfcce0379dc020b77786f0d8f3a04a2a
parent12c07fcf20aba9e986b5b2131515b33e3d27176a

x86_64: fix block result value tracking


1 files changed, 26 insertions(+), 38 deletions(-)

src/arch/x86_64/CodeGen.zig+26-38
......@@ -1085,6 +1085,17 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
10851085 }
10861086}
10871087
1088fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {
1089 const reg = switch (value) {
1090 .register => |reg| reg,
1091 .register_overflow => |ro| ro.reg,
1092 else => return,
1093 };
1094 if (self.register_manager.isRegFree(reg)) {
1095 self.register_manager.getRegAssumeFree(reg, inst);
1096 }
1097}
1098
10881099fn freeValue(self: *Self, value: MCValue) void {
10891100 switch (value) {
10901101 .register => |reg| {
......@@ -1136,25 +1147,10 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
11361147 log.debug("%{d} => {}", .{ inst, result });
11371148 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
11381149 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
1139
1140 // In some cases (such as bitcast), an operand
1141 // may be the same MCValue as the result. If
1142 // that operand died and was a register, it
1143 // was freed by processDeath. We have to
1144 // "re-allocate" the register.
1145 switch (result) {
1146 .register => |reg| {
1147 if (self.register_manager.isRegFree(reg)) {
1148 self.register_manager.getRegAssumeFree(reg, inst);
1149 }
1150 },
1151 .register_overflow => |ro| {
1152 if (self.register_manager.isRegFree(ro.reg)) {
1153 self.register_manager.getRegAssumeFree(ro.reg, inst);
1154 }
1155 },
1156 else => {},
1157 }
1150 // In some cases, an operand may be reused as the result.
1151 // If that operand died and was a register, it was freed by
1152 // processDeath, so we have to "re-allocate" the register.
1153 self.getValue(result, inst);
11581154 } else switch (result) {
11591155 .none, .dead, .unreach => {},
11601156 else => unreachable, // Why didn't the result die?
......@@ -5609,14 +5605,14 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
56095605 });
56105606 defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);
56115607
5608 const ty = self.air.typeOfIndex(inst);
5609 const unused = !ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(inst);
56125610 {
56135611 // Here we use `.none` to represent a null value so that the first break
56145612 // instruction will choose a MCValue for the block result and overwrite
56155613 // this field. Following break instructions will use that MCValue to put
56165614 // their block results.
5617 const ty = self.air.typeOfIndex(inst);
5618 const result: MCValue =
5619 if (!ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(inst)) .dead else .none;
5615 const result: MCValue = if (unused) .dead else .none;
56205616 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
56215617 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
56225618 }
......@@ -5627,6 +5623,9 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
56275623 try self.genBody(body);
56285624
56295625 for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc);
5626
5627 const result = if (unused) .dead else self.getResolvedInstValue(inst).?.*;
5628 self.getValue(result, inst);
56305629 self.finishAirBookkeeping();
56315630}
56325631
......@@ -5837,25 +5836,14 @@ fn br(self: *Self, inst: Air.Inst.Index, block: Air.Inst.Index, operand: Air.Ins
58375836 switch (dst_mcv.*) {
58385837 .none => {
58395838 const result = result: {
5840 if (!self.reuseOperand(inst, operand, 0, src_mcv)) {
5841 const new_mcv = try self.allocRegOrMem(block, true);
5842 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, src_mcv);
5843 break :result new_mcv;
5844 }
5839 if (self.reuseOperand(inst, operand, 0, src_mcv)) break :result src_mcv;
58455840
5846 // the value is actually tracked with block, not inst
5847 switch (src_mcv) {
5848 .register => |reg| if (!self.register_manager.isRegFree(reg)) {
5849 if (RegisterManager.indexOfRegIntoTracked(reg)) |index| {
5850 self.register_manager.registers[index] = block;
5851 }
5852 },
5853 .stack_offset => {},
5854 else => unreachable,
5855 }
5856 break :result src_mcv;
5841 const new_mcv = try self.allocRegOrMem(block, true);
5842 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, src_mcv);
5843 break :result new_mcv;
58575844 };
58585845 dst_mcv.* = result;
5846 self.freeValue(result);
58595847 },
58605848 else => try self.setRegOrMem(self.air.typeOfIndex(block), dst_mcv.*, src_mcv),
58615849 }