Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 159 additions & 45 deletions src/arch/x86_64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -97980,16 +97980,150 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
switch (pred_mcv) {
.register => |pred_reg| switch (pred_reg.class()) {
.general_purpose => {},
.sse => if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {
try self.register_manager.getKnownReg(.xmm0, null);
try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});
break :mask .xmm0;
} else break :mask if (has_blend)
pred_reg
.sse => if (elem_ty.toIntern() == .bool_type)
if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {
try self.register_manager.getKnownReg(.xmm0, null);
try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});
break :mask .xmm0;
} else break :mask if (has_blend)
pred_reg
else
try self.copyToTmpRegister(pred_ty, pred_mcv)
else
try self.copyToTmpRegister(pred_ty, pred_mcv),
return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}),
else => unreachable,
},
.register_mask => |pred_reg_mask| {
if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)
return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});

const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {
try self.register_manager.getKnownReg(.xmm0, null);
try self.genSetReg(.xmm0, ty, .{ .register = pred_reg_mask.reg }, .{});
break :mask_reg .xmm0;
} else pred_reg_mask.reg;
const mask_alias = registerAlias(mask_reg, abi_size);
const mask_lock = self.register_manager.lockRegAssumeUnused(mask_reg);
defer self.register_manager.unlockReg(mask_lock);

const lhs_mcv = try self.resolveInst(extra.lhs);
const lhs_lock = switch (lhs_mcv) {
.register => |lhs_reg| self.register_manager.lockRegAssumeUnused(lhs_reg),
else => null,
};
defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);

const rhs_mcv = try self.resolveInst(extra.rhs);
const rhs_lock = switch (rhs_mcv) {
.register => |rhs_reg| self.register_manager.lockReg(rhs_reg),
else => null,
};
defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);

const order = has_blend != pred_reg_mask.info.inverted;
const reuse_mcv, const other_mcv = if (order)
.{ rhs_mcv, lhs_mcv }
else
.{ lhs_mcv, rhs_mcv };
const dst_mcv: MCValue = if (reuse_mcv.isRegister() and self.reuseOperand(
inst,
if (order) extra.rhs else extra.lhs,
@intFromBool(order),
reuse_mcv,
)) reuse_mcv else if (has_avx)
.{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) }
else
try self.copyToRegisterWithInstTracking(inst, ty, reuse_mcv);
const dst_reg = dst_mcv.getReg().?;
const dst_alias = registerAlias(dst_reg, abi_size);
const dst_lock = self.register_manager.lockReg(dst_reg);
defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);

const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .all and
elem_ty.toIntern() != .f32_type and elem_ty.toIntern() != .f64_type) or pred_reg_mask.info.scalar == .byte)
if (has_avx)
.{ .vp_b, .blendv }
else if (has_blend)
.{ .p_b, .blendv }
else if (pred_reg_mask.info.kind == .all)
.{ .p_, undefined }
else
null
else if ((pred_reg_mask.info.kind == .all and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or
pred_reg_mask.info.scalar == .dword)
if (has_avx)
.{ .v_ps, .blendv }
else if (has_blend)
.{ ._ps, .blendv }
else if (pred_reg_mask.info.kind == .all)
.{ ._ps, undefined }
else
null
else if (pred_reg_mask.info.kind == .all or pred_reg_mask.info.scalar == .qword)
if (has_avx)
.{ .v_pd, .blendv }
else if (has_blend)
.{ ._pd, .blendv }
else if (pred_reg_mask.info.kind == .all)
.{ ._pd, undefined }
else
null
else
null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
if (has_avx) {
const rhs_alias = if (reuse_mcv.isRegister())
registerAlias(reuse_mcv.getReg().?, abi_size)
else rhs: {
try self.genSetReg(dst_reg, ty, reuse_mcv, .{});
break :rhs dst_alias;
};
if (other_mcv.isBase()) try self.asmRegisterRegisterMemoryRegister(
mir_tag,
dst_alias,
rhs_alias,
try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
mask_alias,
) else try self.asmRegisterRegisterRegisterRegister(
mir_tag,
dst_alias,
rhs_alias,
registerAlias(if (other_mcv.isRegister())
other_mcv.getReg().?
else
try self.copyToTmpRegister(ty, other_mcv), abi_size),
mask_alias,
);
} else if (has_blend) if (other_mcv.isBase()) try self.asmRegisterMemoryRegister(
mir_tag,
dst_alias,
try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
mask_alias,
) else try self.asmRegisterRegisterRegister(
mir_tag,
dst_alias,
registerAlias(if (other_mcv.isRegister())
other_mcv.getReg().?
else
try self.copyToTmpRegister(ty, other_mcv), abi_size),
mask_alias,
) else {
try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
if (other_mcv.isBase()) try self.asmRegisterMemory(
.{ mir_tag[0], .andn },
mask_alias,
try other_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
) else try self.asmRegisterRegister(
.{ mir_tag[0], .andn },
mask_alias,
if (other_mcv.isRegister())
other_mcv.getReg().?
else
try self.copyToTmpRegister(ty, other_mcv),
);
try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
}
break :result dst_mcv;
},
else => {},
}
const mask_reg: Register = if (need_xmm0) mask_reg: {
Expand Down Expand Up @@ -98192,7 +98326,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
const dst_lock = self.register_manager.lockReg(dst_reg);
defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);

const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.childType(zcu).zigTypeTag(zcu)) {
const mir_tag = @as(?Mir.Inst.FixedTag, switch (elem_ty.zigTypeTag(zcu)) {
else => null,
.int => switch (abi_size) {
0 => unreachable,
Expand All @@ -98208,7 +98342,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
null,
else => null,
},
.float => switch (ty.childType(zcu).floatBits(self.target.*)) {
.float => switch (elem_ty.floatBits(self.target.*)) {
else => unreachable,
16, 80, 128 => null,
32 => switch (vec_len) {
Expand Down Expand Up @@ -98262,30 +98396,20 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
try self.copyToTmpRegister(ty, lhs_mcv), abi_size),
mask_alias,
) else {
const mir_fixes = @as(?Mir.Inst.Fixes, switch (elem_ty.zigTypeTag(zcu)) {
else => null,
.int => .p_,
.float => switch (elem_ty.floatBits(self.target.*)) {
32 => ._ps,
64 => ._pd,
16, 80, 128 => null,
else => unreachable,
},
}) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_alias, mask_alias);
try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
if (rhs_mcv.isBase()) try self.asmRegisterMemory(
.{ mir_fixes, .andn },
.{ mir_tag[0], .andn },
mask_alias,
try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
) else try self.asmRegisterRegister(
.{ mir_fixes, .andn },
.{ mir_tag[0], .andn },
mask_alias,
if (rhs_mcv.isRegister())
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(ty, rhs_mcv),
);
try self.asmRegisterRegister(.{ mir_fixes, .@"or" }, dst_alias, mask_alias);
try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
}
break :result dst_mcv;
};
Expand Down Expand Up @@ -100824,45 +100948,34 @@ const Temp = struct {
const new_temp_index = cg.next_temp_index;
cg.temp_type[@intFromEnum(new_temp_index)] = .usize;
cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
switch (temp.tracking(cg).short) {
else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
const mcv = temp.tracking(cg).short;
switch (mcv) {
else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
.register => |reg| {
const new_reg =
try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
.base = .{ .reg = reg.to64() },
.mod = .{ .rm = .{ .disp = off } },
});
},
.register_offset => |reg_off| {
const new_reg =
try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
.base = .{ .reg = reg_off.reg.to64() },
.mod = .{ .rm = .{ .disp = reg_off.off + off } },
});
},
.load_symbol, .load_frame => {
const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ .reg = new_reg, .off = off } });
try cg.genSetReg(new_reg, .usize, mcv, .{});
},
.lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{
.sym_index = sym_off.sym_index,
.off = sym_off.off + off,
} }),
.load_frame => |frame_addr| {
const new_reg =
try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{
.reg = new_reg,
.off = off,
} });
try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
.base = .{ .frame = frame_addr.index },
.mod = .{ .rm = .{
.size = .qword,
.disp = frame_addr.off,
} },
});
},
.lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{
.index = frame_addr.index,
.off = frame_addr.off + off,
Expand Down Expand Up @@ -101179,7 +101292,8 @@ const Temp = struct {
=> return temp.toRegClass(true, .general_purpose, cg),
.lea_symbol => |sym_off| {
const off = sym_off.off;
if (off == 0) return false;
// hack around linker relocation bugs
if (false and off == 0) return false;
try temp.toOffset(-off, cg);
while (try temp.toRegClass(true, .general_purpose, cg)) {}
try temp.toOffset(off, cg);
Expand Down
Loading
Loading