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 {...@@ -1085,6 +1085,17 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1085 }1085 }
1086}1086}
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
1088fn freeValue(self: *Self, value: MCValue) void {1099fn freeValue(self: *Self, value: MCValue) void {
1089 switch (value) {1100 switch (value) {
1090 .register => |reg| {1101 .register => |reg| {
...@@ -1136,25 +1147,10 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -1136,25 +1147,10 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
1136 log.debug("%{d} => {}", .{ inst, result });1147 log.debug("%{d} => {}", .{ inst, result });
1137 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1148 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1138 branch.inst_table.putAssumeCapacityNoClobber(inst, result);1149 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
11391150 // In some cases, an operand may be reused as the result.
1140 // In some cases (such as bitcast), an operand1151 // If that operand died and was a register, it was freed by
1141 // may be the same MCValue as the result. If1152 // processDeath, so we have to "re-allocate" the register.
1142 // that operand died and was a register, it1153 self.getValue(result, inst);
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 }
1158 } else switch (result) {1154 } else switch (result) {
1159 .none, .dead, .unreach => {},1155 .none, .dead, .unreach => {},
1160 else => unreachable, // Why didn't the result die?1156 else => unreachable, // Why didn't the result die?
...@@ -5609,14 +5605,14 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -5609,14 +5605,14 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
5609 });5605 });
5610 defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);5606 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);
5612 {5610 {
5613 // Here we use `.none` to represent a null value so that the first break5611 // Here we use `.none` to represent a null value so that the first break
5614 // instruction will choose a MCValue for the block result and overwrite5612 // instruction will choose a MCValue for the block result and overwrite
5615 // this field. Following break instructions will use that MCValue to put5613 // this field. Following break instructions will use that MCValue to put
5616 // their block results.5614 // their block results.
5617 const ty = self.air.typeOfIndex(inst);5615 const result: MCValue = if (unused) .dead else .none;
5618 const result: MCValue =
5619 if (!ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(inst)) .dead else .none;
5620 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];5616 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
5621 branch.inst_table.putAssumeCapacityNoClobber(inst, result);5617 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
5622 }5618 }
...@@ -5627,6 +5623,9 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -5627,6 +5623,9 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
5627 try self.genBody(body);5623 try self.genBody(body);
56285624
5629 for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc);5625 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);
5630 self.finishAirBookkeeping();5629 self.finishAirBookkeeping();
5631}5630}
56325631
...@@ -5837,25 +5836,14 @@ fn br(self: *Self, inst: Air.Inst.Index, block: Air.Inst.Index, operand: Air.Ins...@@ -5837,25 +5836,14 @@ fn br(self: *Self, inst: Air.Inst.Index, block: Air.Inst.Index, operand: Air.Ins
5837 switch (dst_mcv.*) {5836 switch (dst_mcv.*) {
5838 .none => {5837 .none => {
5839 const result = result: {5838 const result = result: {
5840 if (!self.reuseOperand(inst, operand, 0, src_mcv)) {5839 if (self.reuseOperand(inst, operand, 0, src_mcv)) 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;
5844 }
58455840
5846 // the value is actually tracked with block, not inst5841 const new_mcv = try self.allocRegOrMem(block, true);
5847 switch (src_mcv) {5842 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, src_mcv);
5848 .register => |reg| if (!self.register_manager.isRegFree(reg)) {5843 break :result new_mcv;
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;
5857 };5844 };
5858 dst_mcv.* = result;5845 dst_mcv.* = result;
5846 self.freeValue(result);
5859 },5847 },
5860 else => try self.setRegOrMem(self.air.typeOfIndex(block), dst_mcv.*, src_mcv),5848 else => try self.setRegOrMem(self.air.typeOfIndex(block), dst_mcv.*, src_mcv),
5861 }5849 }