mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
x86_64: fix unnecessary register saving
This commit is contained in:
parent
7f22c41e09
commit
3c74a478a4
@ -9731,7 +9731,7 @@ fn computeFrameLayout(self: *CodeGen, cc: std.builtin.CallingConvention) !FrameL
|
||||
|
||||
// Create list of registers to save in the prologue.
|
||||
// TODO handle register classes
|
||||
var save_reg_list = Mir.RegisterList{};
|
||||
var save_reg_list: Mir.RegisterList = .empty;
|
||||
const callee_preserved_regs =
|
||||
abi.getCalleePreservedRegs(abi.resolveCallingConvention(cc, self.target.*));
|
||||
for (callee_preserved_regs) |reg| {
|
||||
@ -9972,43 +9972,34 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
|
||||
reg_locks.deinit();
|
||||
};
|
||||
|
||||
for (0..state.registers.len) |index| {
|
||||
const current_maybe_inst = if (self.register_manager.free_registers.isSet(index))
|
||||
null
|
||||
else
|
||||
self.register_manager.registers[index];
|
||||
const target_maybe_inst = if (state.free_registers.isSet(index))
|
||||
null
|
||||
else
|
||||
state.registers[index];
|
||||
for (
|
||||
0..,
|
||||
self.register_manager.registers,
|
||||
state.registers,
|
||||
state.reg_tracking,
|
||||
) |reg_i, current_slot, target_slot, reg_tracking| {
|
||||
const reg_index: RegisterManager.TrackedIndex = @intCast(reg_i);
|
||||
const current_maybe_inst = if (self.register_manager.isRegIndexFree(reg_index)) null else current_slot;
|
||||
const target_maybe_inst = if (state.free_registers.isSet(reg_index)) null else target_slot;
|
||||
if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|
|
||||
assert(self.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);
|
||||
if (opts.emit_instructions) {
|
||||
if (current_maybe_inst) |current_inst| {
|
||||
if (current_maybe_inst) |current_inst|
|
||||
try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);
|
||||
}
|
||||
if (target_maybe_inst) |target_inst| {
|
||||
const target_tracking = self.inst_tracking.getPtr(target_inst).?;
|
||||
try target_tracking.materialize(self, target_inst, state.reg_tracking[index]);
|
||||
}
|
||||
if (target_maybe_inst) |target_inst|
|
||||
try self.inst_tracking.getPtr(target_inst).?.materialize(self, target_inst, reg_tracking);
|
||||
}
|
||||
if (opts.update_tracking) {
|
||||
if (current_maybe_inst) |current_inst| {
|
||||
try self.inst_tracking.getPtr(current_inst).?.trackSpill(self, current_inst);
|
||||
}
|
||||
{
|
||||
const reg = RegisterManager.regAtTrackedIndex(@intCast(index));
|
||||
self.register_manager.freeReg(reg);
|
||||
self.register_manager.getRegAssumeFree(reg, target_maybe_inst);
|
||||
self.register_manager.freeRegIndex(reg_index);
|
||||
}
|
||||
if (target_maybe_inst) |target_inst| {
|
||||
self.inst_tracking.getPtr(target_inst).?.trackMaterialize(
|
||||
target_inst,
|
||||
state.reg_tracking[index],
|
||||
);
|
||||
self.register_manager.getRegIndexAssumeFree(reg_index, target_maybe_inst);
|
||||
self.inst_tracking.getPtr(target_inst).?.trackMaterialize(target_inst, reg_tracking);
|
||||
}
|
||||
} else if (target_maybe_inst) |_|
|
||||
try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(@intCast(index)));
|
||||
try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(reg_index));
|
||||
}
|
||||
if (opts.emit_instructions) if (self.eflags_inst) |inst|
|
||||
try self.inst_tracking.getPtr(inst).?.spill(self, inst);
|
||||
|
||||
@ -1168,11 +1168,13 @@ pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
|
||||
|
||||
/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
|
||||
pub const RegisterList = struct {
|
||||
bitset: BitSet = BitSet.initEmpty(),
|
||||
bitset: BitSet,
|
||||
|
||||
const BitSet = IntegerBitSet(32);
|
||||
const Self = @This();
|
||||
|
||||
pub const empty: RegisterList = .{ .bitset = .initEmpty() };
|
||||
|
||||
fn getIndexForReg(registers: []const Register, reg: Register) BitSet.MaskInt {
|
||||
for (registers, 0..) |cpreg, i| {
|
||||
if (reg.id() == cpreg.id()) return @intCast(i);
|
||||
|
||||
@ -99,8 +99,7 @@ pub fn RegisterManager(
|
||||
max_id = @max(elem_id, max_id);
|
||||
}
|
||||
|
||||
const OptionalIndex = std.math.IntFittingRange(0, set.len);
|
||||
comptime var map = [1]OptionalIndex{set.len} ** (max_id - min_id + 1);
|
||||
comptime var map: [max_id - min_id + 1]std.math.IntFittingRange(0, set.len) = @splat(set.len);
|
||||
inline for (set, 0..) |elem, elem_index| map[comptime elem.id() - min_id] = elem_index;
|
||||
|
||||
const id_index = reg.id() -% min_id;
|
||||
@ -384,7 +383,7 @@ pub fn RegisterManager(
|
||||
/// Allocates the specified register with the specified
|
||||
/// instruction. Asserts that the register is free and no
|
||||
/// spilling is necessary.
|
||||
fn getRegIndexAssumeFree(
|
||||
pub fn getRegIndexAssumeFree(
|
||||
self: *Self,
|
||||
tracked_index: TrackedIndex,
|
||||
inst: ?Air.Inst.Index,
|
||||
@ -403,7 +402,7 @@ pub fn RegisterManager(
|
||||
}
|
||||
|
||||
/// Marks the specified register as free
|
||||
fn freeRegIndex(self: *Self, tracked_index: TrackedIndex) void {
|
||||
pub fn freeRegIndex(self: *Self, tracked_index: TrackedIndex) void {
|
||||
log.debug("freeing register {}", .{regAtTrackedIndex(tracked_index)});
|
||||
self.registers[tracked_index] = undefined;
|
||||
self.markRegIndexFree(tracked_index);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user