authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-14 22:32:00-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-15 01:04:21-04:00
log05b12e677939effa9da147008071908a2a93fe35
treea69dba305e556a4e469a247a514964503f98440d
parent238615984064f52b6ff31b5750824a9c764fdb15

x86_64: handle duplicate prong deaths


4 files changed, 6 insertions(+), 11 deletions(-)

src/arch/x86_64/CodeGen.zig+6-7
...@@ -1037,9 +1037,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1037,9 +1037,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1037fn processDeath(self: *Self, inst: Air.Inst.Index) void {1037fn processDeath(self: *Self, inst: Air.Inst.Index) void {
1038 const air_tags = self.air.instructions.items(.tag);1038 const air_tags = self.air.instructions.items(.tag);
1039 if (air_tags[inst] == .constant) return; // Constants are immortal.1039 if (air_tags[inst] == .constant) return; // Constants are immortal.
1040 const prev_value = self.getResolvedInstValue(inst) orelse return;
1040 log.debug("%{d} => {}", .{ inst, MCValue.dead });1041 log.debug("%{d} => {}", .{ inst, MCValue.dead });
1041 // When editing this function, note that the logic must synchronize with `reuseOperand`.1042 // When editing this function, note that the logic must synchronize with `reuseOperand`.
1042 const prev_value = self.getResolvedInstValue(inst);
1043 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1043 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1044 branch.inst_table.putAssumeCapacity(inst, .dead);1044 branch.inst_table.putAssumeCapacity(inst, .dead);
1045 switch (prev_value) {1045 switch (prev_value) {
...@@ -1225,7 +1225,7 @@ fn revertState(self: *Self, state: State) void {...@@ -1225,7 +1225,7 @@ fn revertState(self: *Self, state: State) void {
1225pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {1225pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
1226 const stack_mcv = try self.allocRegOrMem(inst, false);1226 const stack_mcv = try self.allocRegOrMem(inst, false);
1227 log.debug("spilling %{d} to stack mcv {any}", .{ inst, stack_mcv });1227 log.debug("spilling %{d} to stack mcv {any}", .{ inst, stack_mcv });
1228 const reg_mcv = self.getResolvedInstValue(inst);1228 const reg_mcv = self.getResolvedInstValue(inst).?;
1229 switch (reg_mcv) {1229 switch (reg_mcv) {
1230 .register => |other| {1230 .register => |other| {
1231 assert(reg.to64() == other.to64());1231 assert(reg.to64() == other.to64());
...@@ -1242,7 +1242,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -1242,7 +1242,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
12421242
1243pub fn spillEflagsIfOccupied(self: *Self) !void {1243pub fn spillEflagsIfOccupied(self: *Self) !void {
1244 if (self.eflags_inst) |inst_to_save| {1244 if (self.eflags_inst) |inst_to_save| {
1245 const mcv = self.getResolvedInstValue(inst_to_save);1245 const mcv = self.getResolvedInstValue(inst_to_save).?;
1246 const new_mcv = switch (mcv) {1246 const new_mcv = switch (mcv) {
1247 .register_overflow => try self.allocRegOrMem(inst_to_save, false),1247 .register_overflow => try self.allocRegOrMem(inst_to_save, false),
1248 .eflags => try self.allocRegOrMem(inst_to_save, true),1248 .eflags => try self.allocRegOrMem(inst_to_save, true),
...@@ -6315,18 +6315,17 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -6315,18 +6315,17 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6315 return gop.value_ptr.*;6315 return gop.value_ptr.*;
6316 },6316 },
6317 .const_ty => unreachable,6317 .const_ty => unreachable,
6318 else => return self.getResolvedInstValue(inst_index),6318 else => return self.getResolvedInstValue(inst_index).?,
6319 }6319 }
6320}6320}
63216321
6322fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {6322fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) ?MCValue {
6323 // Treat each stack item as a "layer" on top of the previous one.6323 // Treat each stack item as a "layer" on top of the previous one.
6324 var i: usize = self.branch_stack.items.len;6324 var i: usize = self.branch_stack.items.len;
6325 while (true) {6325 while (true) {
6326 i -= 1;6326 i -= 1;
6327 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {6327 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {
6328 assert(mcv != .dead);6328 return if (mcv != .dead) mcv else null;
6329 return mcv;
6330 }6329 }
6331 }6330 }
6332}6331}
test/behavior/inline_switch.zig-1
...@@ -46,7 +46,6 @@ const U = union(E) { a: void, b: u2, c: u3, d: u4 };...@@ -46,7 +46,6 @@ const U = union(E) { a: void, b: u2, c: u3, d: u4 };
46test "inline switch unions" {46test "inline switch unions" {
47 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
49 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5150
52 var x: U = .a;51 var x: U = .a;
test/behavior/union.zig-2
...@@ -214,7 +214,6 @@ const Payload = union(Letter) {...@@ -214,7 +214,6 @@ const Payload = union(Letter) {
214};214};
215215
216test "union with specified enum tag" {216test "union with specified enum tag" {
217 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
218 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;217 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;218 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
220 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO219 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -224,7 +223,6 @@ test "union with specified enum tag" {...@@ -224,7 +223,6 @@ test "union with specified enum tag" {
224}223}
225224
226test "packed union generates correctly aligned type" {225test "packed union generates correctly aligned type" {
227 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
228 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;226 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;227 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/union_with_members.zig-1
...@@ -18,7 +18,6 @@ const ET = union(enum) {...@@ -18,7 +18,6 @@ const ET = union(enum) {
1818
19test "enum with members" {19test "enum with members" {
20 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO