| ... | ... | @@ -97980,16 +97980,150 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 97980 | 97980 | switch (pred_mcv) { |
| 97981 | 97981 | .register => |pred_reg| switch (pred_reg.class()) { |
| 97982 | 97982 | .general_purpose => {}, |
| 97983 | | .sse => if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) { |
| 97984 | | try self.register_manager.getKnownReg(.xmm0, null); |
| 97985 | | try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{}); |
| 97986 | | break :mask .xmm0; |
| 97987 | | } else break :mask if (has_blend) |
| 97988 | | pred_reg |
| 97983 | .sse => if (elem_ty.toIntern() == .bool_type) |
| 97984 | if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) { |
| 97985 | try self.register_manager.getKnownReg(.xmm0, null); |
| 97986 | try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{}); |
| 97987 | break :mask .xmm0; |
| 97988 | } else break :mask if (has_blend) |
| 97989 | pred_reg |
| 97990 | else |
| 97991 | try self.copyToTmpRegister(pred_ty, pred_mcv) |
| 97989 | 97992 | else |
| 97990 | | try self.copyToTmpRegister(pred_ty, pred_mcv), |
| 97993 | return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}), |
| 97991 | 97994 | else => unreachable, |
| 97992 | 97995 | }, |
| 97996 | .register_mask => |pred_reg_mask| { |
| 97997 | if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size) |
| 97998 | return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}); |
| 97999 | |
| 98000 | const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: { |
| 98001 | try self.register_manager.getKnownReg(.xmm0, null); |
| 98002 | try self.genSetReg(.xmm0, ty, .{ .register = pred_reg_mask.reg }, .{}); |
| 98003 | break :mask_reg .xmm0; |
| 98004 | } else pred_reg_mask.reg; |
| 98005 | const mask_alias = registerAlias(mask_reg, abi_size); |
| 98006 | const mask_lock = self.register_manager.lockRegAssumeUnused(mask_reg); |
| 98007 | defer self.register_manager.unlockReg(mask_lock); |
| 98008 | |
| 98009 | const lhs_mcv = try self.resolveInst(extra.lhs); |
| 98010 | const lhs_lock = switch (lhs_mcv) { |
| 98011 | .register => |lhs_reg| self.register_manager.lockRegAssumeUnused(lhs_reg), |
| 98012 | else => null, |
| 98013 | }; |
| 98014 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 98015 | |
| 98016 | const rhs_mcv = try self.resolveInst(extra.rhs); |
| 98017 | const rhs_lock = switch (rhs_mcv) { |
| 98018 | .register => |rhs_reg| self.register_manager.lockReg(rhs_reg), |
| 98019 | else => null, |
| 98020 | }; |
| 98021 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 98022 | |
| 98023 | const order = has_blend != pred_reg_mask.info.inverted; |
| 98024 | const reuse_mcv, const other_mcv = if (order) |
| 98025 | .{ rhs_mcv, lhs_mcv } |
| 98026 | else |
| 98027 | .{ lhs_mcv, rhs_mcv }; |
| 98028 | const dst_mcv: MCValue = if (reuse_mcv.isRegister() and self.reuseOperand( |
| 98029 | inst, |
| 98030 | if (order) extra.rhs else extra.lhs, |
| 98031 | @intFromBool(order), |
| 98032 | reuse_mcv, |
| 98033 | )) reuse_mcv else if (has_avx) |
| 98034 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) } |
| 98035 | else |
| 98036 | try self.copyToRegisterWithInstTracking(inst, ty, reuse_mcv); |
| 98037 | const dst_reg = dst_mcv.getReg().?; |
| 98038 | const dst_alias = registerAlias(dst_reg, abi_size); |
| 98039 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 98040 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 98041 | |
| 98042 | const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .all and |
| 98043 | elem_ty.toIntern() != .f32_type and elem_ty.toIntern() != .f64_type) or pred_reg_mask.info.scalar == .byte) |
| 98044 | if (has_avx) |
| 98045 | .{ .vp_b, .blendv } |
| 98046 | else if (has_blend) |
| 98047 | .{ .p_b, .blendv } |
| 98048 | else if (pred_reg_mask.info.kind == .all) |
| 98049 | .{ .p_, undefined } |
| 98050 | else |
| 98051 | null |
| 98052 | else if ((pred_reg_mask.info.kind == .all and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or |
| 98053 | pred_reg_mask.info.scalar == .dword) |
| 98054 | if (has_avx) |
| 98055 | .{ .v_ps, .blendv } |
| 98056 | else if (has_blend) |
| 98057 | .{ ._ps, .blendv } |
| 98058 | else if (pred_reg_mask.info.kind == .all) |
| 98059 | .{ ._ps, undefined } |
| 98060 | else |
| 98061 | null |
| 98062 | else if (pred_reg_mask.info.kind == .all or pred_reg_mask.info.scalar == .qword) |
| 98063 | if (has_avx) |
| 98064 | .{ .v_pd, .blendv } |
| 98065 | else if (has_blend) |
| 98066 | .{ ._pd, .blendv } |
| 98067 | else if (pred_reg_mask.info.kind == .all) |
| 98068 | .{ ._pd, undefined } |
| 98069 | else |
| 98070 | null |
| 98071 | else |
| 98072 | null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}); |
| 98073 | if (has_avx) { |
| 98074 | const rhs_alias = if (reuse_mcv.isRegister()) |
| 98075 | registerAlias(reuse_mcv.getReg().?, abi_size) |
| 98076 | else rhs: { |
| 98077 | try self.genSetReg(dst_reg, ty, reuse_mcv, .{}); |
| 98078 | break :rhs dst_alias; |
| 98079 | }; |
| 98080 | if (other_mcv.isBase()) try self.asmRegisterRegisterMemoryRegister( |
| 98081 | mir_tag, |
| 98082 | dst_alias, |
| 98083 | rhs_alias, |
| 98084 | try other_mcv.mem(self, .{ .size = self.memSize(ty) }), |
| 98085 | mask_alias, |
| 98086 | ) else try self.asmRegisterRegisterRegisterRegister( |
| 98087 | mir_tag, |
| 98088 | dst_alias, |
| 98089 | rhs_alias, |
| 98090 | registerAlias(if (other_mcv.isRegister()) |
| 98091 | other_mcv.getReg().? |
| 98092 | else |
| 98093 | try self.copyToTmpRegister(ty, other_mcv), abi_size), |
| 98094 | mask_alias, |
| 98095 | ); |
| 98096 | } else if (has_blend) if (other_mcv.isBase()) try self.asmRegisterMemoryRegister( |
| 98097 | mir_tag, |
| 98098 | dst_alias, |
| 98099 | try other_mcv.mem(self, .{ .size = self.memSize(ty) }), |
| 98100 | mask_alias, |
| 98101 | ) else try self.asmRegisterRegisterRegister( |
| 98102 | mir_tag, |
| 98103 | dst_alias, |
| 98104 | registerAlias(if (other_mcv.isRegister()) |
| 98105 | other_mcv.getReg().? |
| 98106 | else |
| 98107 | try self.copyToTmpRegister(ty, other_mcv), abi_size), |
| 98108 | mask_alias, |
| 98109 | ) else { |
| 98110 | try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias); |
| 98111 | if (other_mcv.isBase()) try self.asmRegisterMemory( |
| 98112 | .{ mir_tag[0], .andn }, |
| 98113 | mask_alias, |
| 98114 | try other_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 98115 | ) else try self.asmRegisterRegister( |
| 98116 | .{ mir_tag[0], .andn }, |
| 98117 | mask_alias, |
| 98118 | if (other_mcv.isRegister()) |
| 98119 | other_mcv.getReg().? |
| 98120 | else |
| 98121 | try self.copyToTmpRegister(ty, other_mcv), |
| 98122 | ); |
| 98123 | try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias); |
| 98124 | } |
| 98125 | break :result dst_mcv; |
| 98126 | }, |
| 97993 | 98127 | else => {}, |
| 97994 | 98128 | } |
| 97995 | 98129 | const mask_reg: Register = if (need_xmm0) mask_reg: { |
| ... | ... | @@ -98192,7 +98326,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 98192 | 98326 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 98193 | 98327 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 98194 | 98328 | |
| 98195 | | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.childType(zcu).zigTypeTag(zcu)) { |
| 98329 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (elem_ty.zigTypeTag(zcu)) { |
| 98196 | 98330 | else => null, |
| 98197 | 98331 | .int => switch (abi_size) { |
| 98198 | 98332 | 0 => unreachable, |
| ... | ... | @@ -98208,7 +98342,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 98208 | 98342 | null, |
| 98209 | 98343 | else => null, |
| 98210 | 98344 | }, |
| 98211 | | .float => switch (ty.childType(zcu).floatBits(self.target.*)) { |
| 98345 | .float => switch (elem_ty.floatBits(self.target.*)) { |
| 98212 | 98346 | else => unreachable, |
| 98213 | 98347 | 16, 80, 128 => null, |
| 98214 | 98348 | 32 => switch (vec_len) { |
| ... | ... | @@ -98262,30 +98396,20 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 98262 | 98396 | try self.copyToTmpRegister(ty, lhs_mcv), abi_size), |
| 98263 | 98397 | mask_alias, |
| 98264 | 98398 | ) else { |
| 98265 | | const mir_fixes = @as(?Mir.Inst.Fixes, switch (elem_ty.zigTypeTag(zcu)) { |
| 98266 | | else => null, |
| 98267 | | .int => .p_, |
| 98268 | | .float => switch (elem_ty.floatBits(self.target.*)) { |
| 98269 | | 32 => ._ps, |
| 98270 | | 64 => ._pd, |
| 98271 | | 16, 80, 128 => null, |
| 98272 | | else => unreachable, |
| 98273 | | }, |
| 98274 | | }) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}); |
| 98275 | | try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_alias, mask_alias); |
| 98399 | try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias); |
| 98276 | 98400 | if (rhs_mcv.isBase()) try self.asmRegisterMemory( |
| 98277 | | .{ mir_fixes, .andn }, |
| 98401 | .{ mir_tag[0], .andn }, |
| 98278 | 98402 | mask_alias, |
| 98279 | 98403 | try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 98280 | 98404 | ) else try self.asmRegisterRegister( |
| 98281 | | .{ mir_fixes, .andn }, |
| 98405 | .{ mir_tag[0], .andn }, |
| 98282 | 98406 | mask_alias, |
| 98283 | 98407 | if (rhs_mcv.isRegister()) |
| 98284 | 98408 | rhs_mcv.getReg().? |
| 98285 | 98409 | else |
| 98286 | 98410 | try self.copyToTmpRegister(ty, rhs_mcv), |
| 98287 | 98411 | ); |
| 98288 | | try self.asmRegisterRegister(.{ mir_fixes, .@"or" }, dst_alias, mask_alias); |
| 98412 | try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias); |
| 98289 | 98413 | } |
| 98290 | 98414 | break :result dst_mcv; |
| 98291 | 98415 | }; |