diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2023-11-03 07:55:09 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2023-11-03 23:18:23 -0400 |
| commit | 46d3e5bb04393c6be196b10e262d122e008403aa (patch) | |
| tree | 295250ac18b7151352bd64cac40c2e97a278534f /src/arch | |
| parent | 509be7cf1f10c5d329d2b0524f2af6bfcabd52de (diff) | |
| download | zig-46d3e5bb04393c6be196b10e262d122e008403aa.tar.gz zig-46d3e5bb04393c6be196b10e262d122e008403aa.zip | |
x86_64: reduce `RegisterManager` performance regression
This reduces the regression from 0.11.0 by 95%.
Closes #17678
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 30 | ||||
| -rw-r--r-- | src/arch/x86_64/bits.zig | 2 |
2 files changed, 21 insertions, 11 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 9d0a9e05b9..989af5565c 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2608,8 +2608,17 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { } } -pub fn spillRegisters(self: *Self, registers: []const Register) !void { - for (registers) |reg| try self.register_manager.getReg(reg, null); +pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) !void { + switch (cc) { + inline .SysV, .Win64 => |known_cc| try self.spillRegisters( + comptime abi.getCallerPreservedRegs(known_cc), + ), + else => unreachable, + } +} + +pub fn spillRegisters(self: *Self, comptime registers: []const Register) !void { + inline for (registers) |reg| try self.register_manager.getKnownReg(reg, null); } /// Copies a value to a register without tracking the register. The register is not considered @@ -10639,30 +10648,30 @@ fn genCall(self: *Self, info: union(enum) { } try self.spillEflagsIfOccupied(); - try self.spillRegisters(abi.getCallerPreservedRegs(resolved_cc)); + try self.spillCallerPreservedRegs(resolved_cc); // set stack arguments first because this can clobber registers // also clobber spill arguments as we go switch (call_info.return_value.long) { .none, .unreach => {}, - .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}), + .indirect => |reg_off| try self.register_manager.getReg(reg_off.reg, null), else => unreachable, } for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, *frame_index| switch (dst_arg) { .none => {}, .register => |reg| { - try self.spillRegisters(&.{reg}); + try self.register_manager.getReg(reg, null); try reg_locks.append(self.register_manager.lockReg(reg)); }, .register_pair => |regs| { - try self.spillRegisters(®s); + for (regs) |reg| try self.register_manager.getReg(reg, null); try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs)); }, .indirect => |reg_off| { frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod)); try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg); - try self.spillRegisters(&.{reg_off.reg}); + try self.register_manager.getReg(reg_off.reg, null); try reg_locks.append(self.register_manager.lockReg(reg_off.reg)); }, .load_frame => { @@ -11990,8 +11999,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { var args = std.ArrayList(MCValue).init(self.gpa); try args.ensureTotalCapacity(outputs.len + inputs.len); defer { - for (args.items) |arg| if (arg.getReg()) |reg| - self.register_manager.unlockReg(.{ .register = reg }); + for (args.items) |arg| if (arg.getReg()) |reg| self.register_manager.unlockReg(.{ + .tracked_index = RegisterManager.indexOfRegIntoTracked(reg) orelse continue, + }); args.deinit(); } var arg_map = std.StringHashMap(u8).init(self.gpa); @@ -14557,7 +14567,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { } try self.spillEflagsIfOccupied(); - try self.spillRegisters(abi.getCallerPreservedRegs(resolved_cc)); + try self.spillCallerPreservedRegs(resolved_cc); const param_regs = abi.getCAbiIntParamRegs(resolved_cc); diff --git a/src/arch/x86_64/bits.zig b/src/arch/x86_64/bits.zig index 579934da8e..554f944054 100644 --- a/src/arch/x86_64/bits.zig +++ b/src/arch/x86_64/bits.zig @@ -222,7 +222,7 @@ pub const Register = enum(u7) { @intFromEnum(Register.eax) ... @intFromEnum(Register.r15d) => @intFromEnum(Register.eax), @intFromEnum(Register.ax) ... @intFromEnum(Register.r15w) => @intFromEnum(Register.ax), @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => @intFromEnum(Register.al), - @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah) - 4, + @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah), @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => @intFromEnum(Register.ymm0) - 16, @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => @intFromEnum(Register.xmm0) - 16, |
