mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2: codegen: fix reuseOperand not doing death bookkeeping
This commit is contained in:
parent
237d9a105d
commit
0c5faa61ae
@ -632,6 +632,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
/// Asserts there is already capacity to insert into top branch inst_table.
|
||||
fn processDeath(self: *Self, inst: *ir.Inst) void {
|
||||
if (inst.tag == .constant) return; // Constants are immortal.
|
||||
// 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);
|
||||
@ -951,6 +952,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
// Prevent the operand deaths processing code from deallocating it.
|
||||
inst.clearOperandDeath(op_index);
|
||||
|
||||
// That makes us responsible for doing the rest of the stuff that processDeath would have done.
|
||||
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
||||
branch.inst_table.putAssumeCapacity(inst.getOperand(op_index).?, .dead);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1666,7 +1671,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
// The instruction is only overridden in the else branch.
|
||||
var i: usize = self.branch_stack.items.len - 2;
|
||||
while (true) {
|
||||
i -= 1;
|
||||
i -= 1; // If this overflows, the question is: why wasn't the instruction marked dead?
|
||||
if (self.branch_stack.items[i].inst_table.get(else_entry.key)) |mcv| {
|
||||
assert(mcv != .dead);
|
||||
break :blk mcv;
|
||||
|
||||
@ -954,6 +954,7 @@ pub const Module = struct {
|
||||
|
||||
pub const MetaData = struct {
|
||||
deaths: ir.Inst.DeathsInt,
|
||||
addr: usize,
|
||||
};
|
||||
|
||||
pub const BodyMetaData = struct {
|
||||
@ -1152,6 +1153,12 @@ const Writer = struct {
|
||||
try self.writeInstToStream(stream, inst);
|
||||
if (self.module.metadata.get(inst)) |metadata| {
|
||||
try stream.print(" ; deaths=0b{b}", .{metadata.deaths});
|
||||
// This is conditionally compiled in because addresses mess up the tests due
|
||||
// to Address Space Layout Randomization. It's super useful when debugging
|
||||
// codegen.zig though.
|
||||
if (!std.builtin.is_test) {
|
||||
try stream.print(" 0x{x}", .{metadata.addr});
|
||||
}
|
||||
}
|
||||
self.indent -= 2;
|
||||
try stream.writeByte('\n');
|
||||
@ -2417,7 +2424,10 @@ const EmitZIR = struct {
|
||||
|
||||
.varptr => @panic("TODO"),
|
||||
};
|
||||
try self.metadata.put(new_inst, .{ .deaths = inst.deaths });
|
||||
try self.metadata.put(new_inst, .{
|
||||
.deaths = inst.deaths,
|
||||
.addr = @ptrToInt(inst),
|
||||
});
|
||||
try instructions.append(new_inst);
|
||||
try inst_table.put(inst, new_inst);
|
||||
}
|
||||
|
||||
@ -694,6 +694,68 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
"",
|
||||
);
|
||||
|
||||
// Reusing the registers of dead operands playing nicely with conditional branching.
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
\\ assert(add(3, 4) == 791);
|
||||
\\ assert(add(4, 3) == 79);
|
||||
\\
|
||||
\\ exit();
|
||||
\\}
|
||||
\\
|
||||
\\fn add(a: u32, b: u32) u32 {
|
||||
\\ const x: u32 = if (a < b) blk: {
|
||||
\\ const c = a + b; // 7
|
||||
\\ const d = a + c; // 10
|
||||
\\ const e = d + b; // 14
|
||||
\\ const f = d + e; // 24
|
||||
\\ const g = e + f; // 38
|
||||
\\ const h = f + g; // 62
|
||||
\\ const i = g + h; // 100
|
||||
\\ const j = i + d; // 110
|
||||
\\ const k = i + j; // 210
|
||||
\\ const l = k + c; // 217
|
||||
\\ const m = l + d; // 227
|
||||
\\ const n = m + e; // 241
|
||||
\\ const o = n + f; // 265
|
||||
\\ const p = o + g; // 303
|
||||
\\ const q = p + h; // 365
|
||||
\\ const r = q + i; // 465
|
||||
\\ const s = r + j; // 575
|
||||
\\ const t = s + k; // 785
|
||||
\\ break :blk t;
|
||||
\\ } else blk: {
|
||||
\\ const t = b + b + a; // 10
|
||||
\\ const c = a + t; // 14
|
||||
\\ const d = c + t; // 24
|
||||
\\ const e = d + t; // 34
|
||||
\\ const f = e + t; // 44
|
||||
\\ const g = f + t; // 54
|
||||
\\ const h = c + g; // 68
|
||||
\\ break :blk h + b; // 71
|
||||
\\ };
|
||||
\\ const y = x + a; // 788, 75
|
||||
\\ const z = y + a; // 791, 79
|
||||
\\ return z;
|
||||
\\}
|
||||
\\
|
||||
\\pub fn assert(ok: bool) void {
|
||||
\\ if (!ok) unreachable; // assertion failure
|
||||
\\}
|
||||
\\
|
||||
\\fn exit() noreturn {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (231),
|
||||
\\ [arg1] "{rdi}" (0)
|
||||
\\ : "rcx", "r11", "memory"
|
||||
\\ );
|
||||
\\ unreachable;
|
||||
\\}
|
||||
,
|
||||
"",
|
||||
);
|
||||
|
||||
// Character literals and multiline strings.
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user