authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-08 06:38:27-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:47:30-05:00
log5069f574f43f1c9fe7ced12f9fd5f05bdedf6abb
tree38e692c671b7b9a9e377a2794c4294f61c39b4ef
parent3240adfa16cd09d6664223975776c80990cb55cc

x86_64: remove pointless jump to epilogue


1 files changed, 34 insertions(+), 34 deletions(-)

src/arch/x86_64/CodeGen.zig+34-34
...@@ -73,7 +73,7 @@ end_di_column: u32,...@@ -73,7 +73,7 @@ end_di_column: u32,
73/// The value is an offset into the `Function` `code` from the beginning.73/// The value is an offset into the `Function` `code` from the beginning.
74/// To perform the reloc, write 32-bit signed little-endian integer74/// To perform the reloc, write 32-bit signed little-endian integer
75/// which is a relative jump, based on the address following the reloc.75/// which is a relative jump, based on the address following the reloc.
76exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,76epilogue_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,
7777
78reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,78reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
79const_tracking: ConstTrackingMap = .empty,79const_tracking: ConstTrackingMap = .empty,
...@@ -928,7 +928,7 @@ pub fn generate(...@@ -928,7 +928,7 @@ pub fn generate(
928 function.blocks.deinit(gpa);928 function.blocks.deinit(gpa);
929 function.inst_tracking.deinit(gpa);929 function.inst_tracking.deinit(gpa);
930 function.const_tracking.deinit(gpa);930 function.const_tracking.deinit(gpa);
931 function.exitlude_jump_relocs.deinit(gpa);931 function.epilogue_relocs.deinit(gpa);
932 function.mir_instructions.deinit(gpa);932 function.mir_instructions.deinit(gpa);
933 function.mir_extra.deinit(gpa);933 function.mir_extra.deinit(gpa);
934 function.mir_table.deinit(gpa);934 function.mir_table.deinit(gpa);
...@@ -2193,24 +2193,24 @@ fn gen(self: *CodeGen) InnerError!void {...@@ -2193,24 +2193,24 @@ fn gen(self: *CodeGen) InnerError!void {
21932193
2194 try self.genBody(self.air.getMainBody());2194 try self.genBody(self.air.getMainBody());
21952195
2196 // TODO can single exitlude jump reloc be elided? What if it is not at the end of the code?2196 const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {
2197 // Example:2197 const epilogue_relocs_last_index = self.epilogue_relocs.items.len - 1;
2198 // pub fn main() void {2198 for (if (self.epilogue_relocs.items[epilogue_relocs_last_index] == self.mir_instructions.len - 1) epilogue_relocs: {
2199 // maybeErr() catch return;2199 _ = self.mir_instructions.pop();
2200 // unreachable;2200 break :epilogue_relocs self.epilogue_relocs.items[0..epilogue_relocs_last_index];
2201 // }2201 } else self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc);
2202 // Eliding the reloc will cause a miscompilation in this case.2202
2203 for (self.exitlude_jump_relocs.items) |jmp_reloc| {2203 try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
2204 self.mir_instructions.items(.data)[jmp_reloc].inst.inst =2204 const backpatch_stack_dealloc = try self.asmPlaceholder();
2205 @intCast(self.mir_instructions.len);2205 const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
2206 }2206 try self.asmRegister(.{ ._, .pop }, .rbp);
22072207 try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, .s(8));
2208 try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);2208 try self.asmOpOnly(.{ ._, .ret });
2209 const backpatch_stack_dealloc = try self.asmPlaceholder();2209 break :epilogue .{
2210 const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();2210 .backpatch_stack_dealloc = backpatch_stack_dealloc,
2211 try self.asmRegister(.{ ._, .pop }, .rbp);2211 .backpatch_pop_callee_preserved_regs = backpatch_pop_callee_preserved_regs,
2212 try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, .s(8));2212 };
2213 try self.asmOpOnly(.{ ._, .ret });2213 } else null;
22142214
2215 const frame_layout = try self.computeFrameLayout(fn_info.cc);2215 const frame_layout = try self.computeFrameLayout(fn_info.cc);
2216 const need_frame_align = frame_layout.stack_mask != std.math.maxInt(u32);2216 const need_frame_align = frame_layout.stack_mask != std.math.maxInt(u32);
...@@ -2280,8 +2280,8 @@ fn gen(self: *CodeGen) InnerError!void {...@@ -2280,8 +2280,8 @@ fn gen(self: *CodeGen) InnerError!void {
2280 });2280 });
2281 }2281 }
2282 }2282 }
2283 if (need_frame_align or need_stack_adjust) {2283 if (epilogue) |e| if (need_frame_align or need_stack_adjust) {
2284 self.mir_instructions.set(backpatch_stack_dealloc, switch (-frame_layout.save_reg_list.size(self.target)) {2284 self.mir_instructions.set(e.backpatch_stack_dealloc, switch (-frame_layout.save_reg_list.size(self.target)) {
2285 0 => .{2285 0 => .{
2286 .tag = .mov,2286 .tag = .mov,
2287 .ops = .rr,2287 .ops = .rr,
...@@ -2305,14 +2305,14 @@ fn gen(self: *CodeGen) InnerError!void {...@@ -2305,14 +2305,14 @@ fn gen(self: *CodeGen) InnerError!void {
2305 } },2305 } },
2306 },2306 },
2307 });2307 });
2308 }2308 };
2309 if (need_save_reg) {2309 if (need_save_reg) {
2310 self.mir_instructions.set(backpatch_push_callee_preserved_regs, .{2310 self.mir_instructions.set(backpatch_push_callee_preserved_regs, .{
2311 .tag = .pseudo,2311 .tag = .pseudo,
2312 .ops = .pseudo_push_reg_list,2312 .ops = .pseudo_push_reg_list,
2313 .data = .{ .reg_list = frame_layout.save_reg_list },2313 .data = .{ .reg_list = frame_layout.save_reg_list },
2314 });2314 });
2315 self.mir_instructions.set(backpatch_pop_callee_preserved_regs, .{2315 if (epilogue) |e| self.mir_instructions.set(e.backpatch_pop_callee_preserved_regs, .{
2316 .tag = .pseudo,2316 .tag = .pseudo,
2317 .ops = .pseudo_pop_reg_list,2317 .ops = .pseudo_pop_reg_list,
2318 .data = .{ .reg_list = frame_layout.save_reg_list },2318 .data = .{ .reg_list = frame_layout.save_reg_list },
...@@ -10007,8 +10007,8 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -10007,8 +10007,8 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
10007 const ret_reg = param_regs[0];10007 const ret_reg = param_regs[0];
10008 const enum_mcv = MCValue{ .register = param_regs[1] };10008 const enum_mcv = MCValue{ .register = param_regs[1] };
1000910009
10010 const exitlude_jump_relocs = try self.gpa.alloc(Mir.Inst.Index, enum_ty.enumFieldCount(zcu));10010 const epilogue_relocs = try self.gpa.alloc(Mir.Inst.Index, enum_ty.enumFieldCount(zcu));
10011 defer self.gpa.free(exitlude_jump_relocs);10011 defer self.gpa.free(epilogue_relocs);
1001210012
10013 const data_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);10013 const data_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
10014 const data_lock = self.register_manager.lockRegAssumeUnused(data_reg);10014 const data_lock = self.register_manager.lockRegAssumeUnused(data_reg);
...@@ -10017,7 +10017,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -10017,7 +10017,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
1001710017
10018 var data_off: i32 = 0;10018 var data_off: i32 = 0;
10019 const tag_names = enum_ty.enumFields(zcu);10019 const tag_names = enum_ty.enumFields(zcu);
10020 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| {10020 for (epilogue_relocs, 0..) |*epilogue_reloc, tag_index| {
10021 const tag_name_len = tag_names.get(ip)[tag_index].length(ip);10021 const tag_name_len = tag_names.get(ip)[tag_index].length(ip);
10022 const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index));10022 const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index));
10023 const tag_mcv = try self.genTypedValue(tag_val);10023 const tag_mcv = try self.genTypedValue(tag_val);
...@@ -10033,7 +10033,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -10033,7 +10033,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
10033 );10033 );
10034 try self.genSetMem(.{ .reg = ret_reg }, 8, .usize, .{ .immediate = tag_name_len }, .{});10034 try self.genSetMem(.{ .reg = ret_reg }, 8, .usize, .{ .immediate = tag_name_len }, .{});
1003510035
10036 exitlude_jump_reloc.* = try self.asmJmpReloc(undefined);10036 epilogue_reloc.* = try self.asmJmpReloc(undefined);
10037 self.performReloc(skip_reloc);10037 self.performReloc(skip_reloc);
1003810038
10039 data_off += @intCast(tag_name_len + 1);10039 data_off += @intCast(tag_name_len + 1);
...@@ -10041,7 +10041,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {...@@ -10041,7 +10041,7 @@ fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
1004110041
10042 try self.asmOpOnly(.{ ._, .ud2 });10042 try self.asmOpOnly(.{ ._, .ud2 });
1004310043
10044 for (exitlude_jump_relocs) |reloc| self.performReloc(reloc);10044 for (epilogue_relocs) |reloc| self.performReloc(reloc);
10045 try self.asmOpOnly(.{ ._, .ret });10045 try self.asmOpOnly(.{ ._, .ret });
10046 },10046 },
10047 else => return self.fail(10047 else => return self.fail(
...@@ -20114,7 +20114,7 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -20114,7 +20114,7 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
20114 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction20114 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
20115 // which is available if the jump is 127 bytes or less forward.20115 // which is available if the jump is 127 bytes or less forward.
20116 const jmp_reloc = try self.asmJmpReloc(undefined);20116 const jmp_reloc = try self.asmJmpReloc(undefined);
20117 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);20117 try self.epilogue_relocs.append(self.gpa, jmp_reloc);
20118}20118}
2011920119
20120fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void {20120fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
...@@ -20134,7 +20134,7 @@ fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20134,7 +20134,7 @@ fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
20134 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction20134 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
20135 // which is available if the jump is 127 bytes or less forward.20135 // which is available if the jump is 127 bytes or less forward.
20136 const jmp_reloc = try self.asmJmpReloc(undefined);20136 const jmp_reloc = try self.asmJmpReloc(undefined);
20137 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);20137 try self.epilogue_relocs.append(self.gpa, jmp_reloc);
20138}20138}
2013920139
20140fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !void {20140fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !void {
...@@ -24486,7 +24486,7 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -24486,7 +24486,7 @@ fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
24486 self.register_manager.lockRegAssumeUnused(dst_regs[0]),24486 self.register_manager.lockRegAssumeUnused(dst_regs[0]),
24487 self.register_manager.lockRegAssumeUnused(dst_regs[1]),24487 self.register_manager.lockRegAssumeUnused(dst_regs[1]),
24488 },24488 },
24489 else => .{ null, null },24489 else => @splat(null),
24490 };24490 };
24491 for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);24491 for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2449224492
...@@ -24625,7 +24625,7 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -24625,7 +24625,7 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void {
24625 self.register_manager.lockRegAssumeUnused(dst_regs[0]),24625 self.register_manager.lockRegAssumeUnused(dst_regs[0]),
24626 self.register_manager.lockReg(dst_regs[1]),24626 self.register_manager.lockReg(dst_regs[1]),
24627 },24627 },
24628 else => .{ null, null },24628 else => @splat(null),
24629 };24629 };
24630 for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);24630 for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2463124631
...@@ -24636,7 +24636,7 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -24636,7 +24636,7 @@ fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void {
24636 self.register_manager.lockRegAssumeUnused(src_regs[0]),24636 self.register_manager.lockRegAssumeUnused(src_regs[0]),
24637 self.register_manager.lockRegAssumeUnused(src_regs[1]),24637 self.register_manager.lockRegAssumeUnused(src_regs[1]),
24638 },24638 },
24639 else => .{ null, null },24639 else => @splat(null),
24640 };24640 };
24641 for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock);24641 for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock);
2464224642