| ... | @@ -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 | } |
| 1087 | | 1087 | |
| | 1088 | fn 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 | |
| 1088 | fn freeValue(self: *Self, value: MCValue) void { | 1099 | fn 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); |
| 1139 | | 1150 | // In some cases, an operand may be reused as the result. |
| 1140 | // In some cases (such as bitcast), an operand | 1151 | // If that operand died and was a register, it was freed by |
| 1141 | // may be the same MCValue as the result. If | 1152 | // processDeath, so we have to "re-allocate" the register. |
| 1142 | // that operand died and was a register, it | 1153 | 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); |
| 5611 | | 5607 | |
| | 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 break | 5611 | // 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 overwrite | 5612 | // instruction will choose a MCValue for the block result and overwrite |
| 5615 | // this field. Following break instructions will use that MCValue to put | 5613 | // 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); |
| 5628 | | 5624 | |
| 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 | } |
| 5632 | | 5631 | |
| ... | @@ -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 | } | | |
| 5845 | | 5840 | |
| 5846 | // the value is actually tracked with block, not inst | 5841 | 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 | } |