authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-02 23:20:53-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:42:08-05:00
log3c74a478a41d2f806f3b9b2bb86fffbc40e100c3
tree8ff4dc5ff57130b2a33c5189363187a38cc0236f
parent7f22c41e09741de8cd7d87b938c0b15a9b4bd32e

x86_64: fix unnecessary register saving


3 files changed, 23 insertions(+), 31 deletions(-)

src/arch/x86_64/CodeGen.zig+17-26
......@@ -9731,7 +9731,7 @@ fn computeFrameLayout(self: *CodeGen, cc: std.builtin.CallingConvention) !FrameL
97319731
97329732 // Create list of registers to save in the prologue.
97339733 // TODO handle register classes
9734 var save_reg_list = Mir.RegisterList{};
9734 var save_reg_list: Mir.RegisterList = .empty;
97359735 const callee_preserved_regs =
97369736 abi.getCalleePreservedRegs(abi.resolveCallingConvention(cc, self.target.*));
97379737 for (callee_preserved_regs) |reg| {
......@@ -9972,43 +9972,34 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
99729972 reg_locks.deinit();
99739973 };
99749974
9975 for (0..state.registers.len) |index| {
9976 const current_maybe_inst = if (self.register_manager.free_registers.isSet(index))
9977 null
9978 else
9979 self.register_manager.registers[index];
9980 const target_maybe_inst = if (state.free_registers.isSet(index))
9981 null
9982 else
9983 state.registers[index];
9975 for (
9976 0..,
9977 self.register_manager.registers,
9978 state.registers,
9979 state.reg_tracking,
9980 ) |reg_i, current_slot, target_slot, reg_tracking| {
9981 const reg_index: RegisterManager.TrackedIndex = @intCast(reg_i);
9982 const current_maybe_inst = if (self.register_manager.isRegIndexFree(reg_index)) null else current_slot;
9983 const target_maybe_inst = if (state.free_registers.isSet(reg_index)) null else target_slot;
99849984 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|
99859985 assert(self.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);
99869986 if (opts.emit_instructions) {
9987 if (current_maybe_inst) |current_inst| {
9987 if (current_maybe_inst) |current_inst|
99889988 try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);
9989 }
9990 if (target_maybe_inst) |target_inst| {
9991 const target_tracking = self.inst_tracking.getPtr(target_inst).?;
9992 try target_tracking.materialize(self, target_inst, state.reg_tracking[index]);
9993 }
9989 if (target_maybe_inst) |target_inst|
9990 try self.inst_tracking.getPtr(target_inst).?.materialize(self, target_inst, reg_tracking);
99949991 }
99959992 if (opts.update_tracking) {
99969993 if (current_maybe_inst) |current_inst| {
99979994 try self.inst_tracking.getPtr(current_inst).?.trackSpill(self, current_inst);
9998 }
9999 {
10000 const reg = RegisterManager.regAtTrackedIndex(@intCast(index));
10001 self.register_manager.freeReg(reg);
10002 self.register_manager.getRegAssumeFree(reg, target_maybe_inst);
9995 self.register_manager.freeRegIndex(reg_index);
100039996 }
100049997 if (target_maybe_inst) |target_inst| {
10005 self.inst_tracking.getPtr(target_inst).?.trackMaterialize(
10006 target_inst,
10007 state.reg_tracking[index],
10008 );
9998 self.register_manager.getRegIndexAssumeFree(reg_index, target_maybe_inst);
9999 self.inst_tracking.getPtr(target_inst).?.trackMaterialize(target_inst, reg_tracking);
1000910000 }
1001010001 } else if (target_maybe_inst) |_|
10011 try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(@intCast(index)));
10002 try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(reg_index));
1001210003 }
1001310004 if (opts.emit_instructions) if (self.eflags_inst) |inst|
1001410005 try self.inst_tracking.getPtr(inst).?.spill(self, inst);
src/arch/x86_64/Mir.zig+3-1
......@@ -1168,11 +1168,13 @@ pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
11681168
11691169/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
11701170pub const RegisterList = struct {
1171 bitset: BitSet = BitSet.initEmpty(),
1171 bitset: BitSet,
11721172
11731173 const BitSet = IntegerBitSet(32);
11741174 const Self = @This();
11751175
1176 pub const empty: RegisterList = .{ .bitset = .initEmpty() };
1177
11761178 fn getIndexForReg(registers: []const Register, reg: Register) BitSet.MaskInt {
11771179 for (registers, 0..) |cpreg, i| {
11781180 if (reg.id() == cpreg.id()) return @intCast(i);
src/register_manager.zig+3-4
......@@ -99,8 +99,7 @@ pub fn RegisterManager(
9999 max_id = @max(elem_id, max_id);
100100 }
101101
102 const OptionalIndex = std.math.IntFittingRange(0, set.len);
103 comptime var map = [1]OptionalIndex{set.len} ** (max_id - min_id + 1);
102 comptime var map: [max_id - min_id + 1]std.math.IntFittingRange(0, set.len) = @splat(set.len);
104103 inline for (set, 0..) |elem, elem_index| map[comptime elem.id() - min_id] = elem_index;
105104
106105 const id_index = reg.id() -% min_id;
......@@ -384,7 +383,7 @@ pub fn RegisterManager(
384383 /// Allocates the specified register with the specified
385384 /// instruction. Asserts that the register is free and no
386385 /// spilling is necessary.
387 fn getRegIndexAssumeFree(
386 pub fn getRegIndexAssumeFree(
388387 self: *Self,
389388 tracked_index: TrackedIndex,
390389 inst: ?Air.Inst.Index,
......@@ -403,7 +402,7 @@ pub fn RegisterManager(
403402 }
404403
405404 /// Marks the specified register as free
406 fn freeRegIndex(self: *Self, tracked_index: TrackedIndex) void {
405 pub fn freeRegIndex(self: *Self, tracked_index: TrackedIndex) void {
407406 log.debug("freeing register {}", .{regAtTrackedIndex(tracked_index)});
408407 self.registers[tracked_index] = undefined;
409408 self.markRegIndexFree(tracked_index);