From 05b12e677939effa9da147008071908a2a93fe35 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Tue, 14 Mar 2023 22:32:00 -0400 Subject: [PATCH] x86_64: handle duplicate prong deaths --- src/arch/x86_64/CodeGen.zig | 13 ++++++------- test/behavior/inline_switch.zig | 1 - test/behavior/union.zig | 2 -- test/behavior/union_with_members.zig | 1 - 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 1be93accc7..bf1d9f0eb0 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1037,9 +1037,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { fn processDeath(self: *Self, inst: Air.Inst.Index) void { const air_tags = self.air.instructions.items(.tag); if (air_tags[inst] == .constant) return; // Constants are immortal. + const prev_value = self.getResolvedInstValue(inst) orelse return; log.debug("%{d} => {}", .{ inst, MCValue.dead }); // When editing this function, note that the logic must synchronize with `reuseOperand`. - const prev_value = self.getResolvedInstValue(inst); const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; branch.inst_table.putAssumeCapacity(inst, .dead); switch (prev_value) { @@ -1225,7 +1225,7 @@ fn revertState(self: *Self, state: State) void { pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { const stack_mcv = try self.allocRegOrMem(inst, false); log.debug("spilling %{d} to stack mcv {any}", .{ inst, stack_mcv }); - const reg_mcv = self.getResolvedInstValue(inst); + const reg_mcv = self.getResolvedInstValue(inst).?; switch (reg_mcv) { .register => |other| { assert(reg.to64() == other.to64()); @@ -1242,7 +1242,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void pub fn spillEflagsIfOccupied(self: *Self) !void { if (self.eflags_inst) |inst_to_save| { - const mcv = self.getResolvedInstValue(inst_to_save); + const mcv = self.getResolvedInstValue(inst_to_save).?; const new_mcv = switch (mcv) { .register_overflow => try self.allocRegOrMem(inst_to_save, false), .eflags => try self.allocRegOrMem(inst_to_save, true), @@ -6315,18 +6315,17 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { return gop.value_ptr.*; }, .const_ty => unreachable, - else => return self.getResolvedInstValue(inst_index), + else => return self.getResolvedInstValue(inst_index).?, } } -fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { +fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) ?MCValue { // Treat each stack item as a "layer" on top of the previous one. var i: usize = self.branch_stack.items.len; while (true) { i -= 1; if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| { - assert(mcv != .dead); - return mcv; + return if (mcv != .dead) mcv else null; } } } diff --git a/test/behavior/inline_switch.zig b/test/behavior/inline_switch.zig index 90e8b36284..dcd603c94f 100644 --- a/test/behavior/inline_switch.zig +++ b/test/behavior/inline_switch.zig @@ -46,7 +46,6 @@ const U = union(E) { a: void, b: u2, c: u3, d: u4 }; test "inline switch unions" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var x: U = .a; diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 03c47b09d6..9b49f8bf47 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -214,7 +214,6 @@ const Payload = union(Letter) { }; test "union with specified enum tag" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -224,7 +223,6 @@ test "union with specified enum tag" { } test "packed union generates correctly aligned type" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/union_with_members.zig b/test/behavior/union_with_members.zig index 0cb06a81ab..8e9c2db475 100644 --- a/test/behavior/union_with_members.zig +++ b/test/behavior/union_with_members.zig @@ -18,7 +18,6 @@ const ET = union(enum) { test "enum with members" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO