mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 22:33:08 +00:00
x86_64: fix block result value tracking
This commit is contained in:
parent
12c07fcf20
commit
c604111e22
@ -1085,6 +1085,17 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {
|
||||||
|
const reg = switch (value) {
|
||||||
|
.register => |reg| reg,
|
||||||
|
.register_overflow => |ro| ro.reg,
|
||||||
|
else => return,
|
||||||
|
};
|
||||||
|
if (self.register_manager.isRegFree(reg)) {
|
||||||
|
self.register_manager.getRegAssumeFree(reg, inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn freeValue(self: *Self, value: MCValue) void {
|
fn freeValue(self: *Self, value: MCValue) void {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
.register => |reg| {
|
.register => |reg| {
|
||||||
@ -1136,25 +1147,10 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
|
|||||||
log.debug("%{d} => {}", .{ inst, result });
|
log.debug("%{d} => {}", .{ inst, result });
|
||||||
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
||||||
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
|
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
|
||||||
|
// In some cases, an operand may be reused as the result.
|
||||||
// In some cases (such as bitcast), an operand
|
// If that operand died and was a register, it was freed by
|
||||||
// may be the same MCValue as the result. If
|
// processDeath, so we have to "re-allocate" the register.
|
||||||
// that operand died and was a register, it
|
self.getValue(result, inst);
|
||||||
// was freed by processDeath. We have to
|
|
||||||
// "re-allocate" the register.
|
|
||||||
switch (result) {
|
|
||||||
.register => |reg| {
|
|
||||||
if (self.register_manager.isRegFree(reg)) {
|
|
||||||
self.register_manager.getRegAssumeFree(reg, inst);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.register_overflow => |ro| {
|
|
||||||
if (self.register_manager.isRegFree(ro.reg)) {
|
|
||||||
self.register_manager.getRegAssumeFree(ro.reg, inst);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
} else switch (result) {
|
} else switch (result) {
|
||||||
.none, .dead, .unreach => {},
|
.none, .dead, .unreach => {},
|
||||||
else => unreachable, // Why didn't the result die?
|
else => unreachable, // Why didn't the result die?
|
||||||
@ -5609,14 +5605,14 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
});
|
});
|
||||||
defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);
|
defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);
|
||||||
|
|
||||||
|
const ty = self.air.typeOfIndex(inst);
|
||||||
|
const unused = !ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(inst);
|
||||||
{
|
{
|
||||||
// Here we use `.none` to represent a null value so that the first break
|
// Here we use `.none` to represent a null value so that the first break
|
||||||
// instruction will choose a MCValue for the block result and overwrite
|
// instruction will choose a MCValue for the block result and overwrite
|
||||||
// this field. Following break instructions will use that MCValue to put
|
// this field. Following break instructions will use that MCValue to put
|
||||||
// their block results.
|
// their block results.
|
||||||
const ty = self.air.typeOfIndex(inst);
|
const result: MCValue = if (unused) .dead else .none;
|
||||||
const result: MCValue =
|
|
||||||
if (!ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(inst)) .dead else .none;
|
|
||||||
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
||||||
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
|
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
|
||||||
}
|
}
|
||||||
@ -5627,6 +5623,9 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
try self.genBody(body);
|
try self.genBody(body);
|
||||||
|
|
||||||
for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc);
|
for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc);
|
||||||
|
|
||||||
|
const result = if (unused) .dead else self.getResolvedInstValue(inst).?.*;
|
||||||
|
self.getValue(result, inst);
|
||||||
self.finishAirBookkeeping();
|
self.finishAirBookkeeping();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5837,25 +5836,14 @@ fn br(self: *Self, inst: Air.Inst.Index, block: Air.Inst.Index, operand: Air.Ins
|
|||||||
switch (dst_mcv.*) {
|
switch (dst_mcv.*) {
|
||||||
.none => {
|
.none => {
|
||||||
const result = result: {
|
const result = result: {
|
||||||
if (!self.reuseOperand(inst, operand, 0, src_mcv)) {
|
if (self.reuseOperand(inst, operand, 0, src_mcv)) break :result src_mcv;
|
||||||
const new_mcv = try self.allocRegOrMem(block, true);
|
|
||||||
try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, src_mcv);
|
|
||||||
break :result new_mcv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the value is actually tracked with block, not inst
|
const new_mcv = try self.allocRegOrMem(block, true);
|
||||||
switch (src_mcv) {
|
try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, src_mcv);
|
||||||
.register => |reg| if (!self.register_manager.isRegFree(reg)) {
|
break :result new_mcv;
|
||||||
if (RegisterManager.indexOfRegIntoTracked(reg)) |index| {
|
|
||||||
self.register_manager.registers[index] = block;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.stack_offset => {},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
break :result src_mcv;
|
|
||||||
};
|
};
|
||||||
dst_mcv.* = result;
|
dst_mcv.* = result;
|
||||||
|
self.freeValue(result);
|
||||||
},
|
},
|
||||||
else => try self.setRegOrMem(self.air.typeOfIndex(block), dst_mcv.*, src_mcv),
|
else => try self.setRegOrMem(self.air.typeOfIndex(block), dst_mcv.*, src_mcv),
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user