| ... | ... | @@ -97909,16 +97909,150 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 97909 | 97909 | switch (pred_mcv) { |
| 97910 | 97910 | .register => |pred_reg| switch (pred_reg.class()) { |
| 97911 | 97911 | .general_purpose => {}, |
| 97912 | | .sse => if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) { |
| 97913 | | try self.register_manager.getKnownReg(.xmm0, null); |
| 97914 | | try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{}); |
| 97915 | | break :mask .xmm0; |
| 97916 | | } else break :mask if (has_blend) |
| 97917 | | pred_reg |
| 97912 | .sse => if (elem_ty.toIntern() == .bool_type) |
| 97913 | if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) { |
| 97914 | try self.register_manager.getKnownReg(.xmm0, null); |
| 97915 | try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{}); |
| 97916 | break :mask .xmm0; |
| 97917 | } else break :mask if (has_blend) |
| 97918 | pred_reg |
| 97919 | else |
| 97920 | try self.copyToTmpRegister(pred_ty, pred_mcv) |
| 97918 | 97921 | else |
| 97919 | | try self.copyToTmpRegister(pred_ty, pred_mcv), |
| 97922 | return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}), |
| 97920 | 97923 | else => unreachable, |
| 97921 | 97924 | }, |
| 97925 | .register_mask => |pred_reg_mask| { |
| 97926 | if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size) |
| 97927 | return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}); |
| 97928 | |
| 97929 | const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: { |
| 97930 | try self.register_manager.getKnownReg(.xmm0, null); |
| 97931 | try self.genSetReg(.xmm0, ty, .{ .register = pred_reg_mask.reg }, .{}); |
| 97932 | break :mask_reg .xmm0; |
| 97933 | } else pred_reg_mask.reg; |
| 97934 | const mask_alias = registerAlias(mask_reg, abi_size); |
| 97935 | const mask_lock = self.register_manager.lockRegAssumeUnused(mask_reg); |
| 97936 | defer self.register_manager.unlockReg(mask_lock); |
| 97937 | |
| 97938 | const lhs_mcv = try self.resolveInst(extra.lhs); |
| 97939 | const lhs_lock = switch (lhs_mcv) { |
| 97940 | .register => |lhs_reg| self.register_manager.lockRegAssumeUnused(lhs_reg), |
| 97941 | else => null, |
| 97942 | }; |
| 97943 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 97944 | |
| 97945 | const rhs_mcv = try self.resolveInst(extra.rhs); |
| 97946 | const rhs_lock = switch (rhs_mcv) { |
| 97947 | .register => |rhs_reg| self.register_manager.lockReg(rhs_reg), |
| 97948 | else => null, |
| 97949 | }; |
| 97950 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 97951 | |
| 97952 | const order = has_blend != pred_reg_mask.info.inverted; |
| 97953 | const reuse_mcv, const other_mcv = if (order) |
| 97954 | .{ rhs_mcv, lhs_mcv } |
| 97955 | else |
| 97956 | .{ lhs_mcv, rhs_mcv }; |
| 97957 | const dst_mcv: MCValue = if (reuse_mcv.isRegister() and self.reuseOperand( |
| 97958 | inst, |
| 97959 | if (order) extra.rhs else extra.lhs, |
| 97960 | @intFromBool(order), |
| 97961 | reuse_mcv, |
| 97962 | )) reuse_mcv else if (has_avx) |
| 97963 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) } |
| 97964 | else |
| 97965 | try self.copyToRegisterWithInstTracking(inst, ty, reuse_mcv); |
| 97966 | const dst_reg = dst_mcv.getReg().?; |
| 97967 | const dst_alias = registerAlias(dst_reg, abi_size); |
| 97968 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 97969 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 97970 | |
| 97971 | const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .all and |
| 97972 | elem_ty.toIntern() != .f32_type and elem_ty.toIntern() != .f64_type) or pred_reg_mask.info.scalar == .byte) |
| 97973 | if (has_avx) |
| 97974 | .{ .vp_b, .blendv } |
| 97975 | else if (has_blend) |
| 97976 | .{ .p_b, .blendv } |
| 97977 | else if (pred_reg_mask.info.kind == .all) |
| 97978 | .{ .p_, undefined } |
| 97979 | else |
| 97980 | null |
| 97981 | else if ((pred_reg_mask.info.kind == .all and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or |
| 97982 | pred_reg_mask.info.scalar == .dword) |
| 97983 | if (has_avx) |
| 97984 | .{ .v_ps, .blendv } |
| 97985 | else if (has_blend) |
| 97986 | .{ ._ps, .blendv } |
| 97987 | else if (pred_reg_mask.info.kind == .all) |
| 97988 | .{ ._ps, undefined } |
| 97989 | else |
| 97990 | null |
| 97991 | else if (pred_reg_mask.info.kind == .all or pred_reg_mask.info.scalar == .qword) |
| 97992 | if (has_avx) |
| 97993 | .{ .v_pd, .blendv } |
| 97994 | else if (has_blend) |
| 97995 | .{ ._pd, .blendv } |
| 97996 | else if (pred_reg_mask.info.kind == .all) |
| 97997 | .{ ._pd, undefined } |
| 97998 | else |
| 97999 | null |
| 98000 | else |
| 98001 | null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}); |
| 98002 | if (has_avx) { |
| 98003 | const rhs_alias = if (reuse_mcv.isRegister()) |
| 98004 | registerAlias(reuse_mcv.getReg().?, abi_size) |
| 98005 | else rhs: { |
| 98006 | try self.genSetReg(dst_reg, ty, reuse_mcv, .{}); |
| 98007 | break :rhs dst_alias; |
| 98008 | }; |
| 98009 | if (other_mcv.isBase()) try self.asmRegisterRegisterMemoryRegister( |
| 98010 | mir_tag, |
| 98011 | dst_alias, |
| 98012 | rhs_alias, |
| 98013 | try other_mcv.mem(self, .{ .size = self.memSize(ty) }), |
| 98014 | mask_alias, |
| 98015 | ) else try self.asmRegisterRegisterRegisterRegister( |
| 98016 | mir_tag, |
| 98017 | dst_alias, |
| 98018 | rhs_alias, |
| 98019 | registerAlias(if (other_mcv.isRegister()) |
| 98020 | other_mcv.getReg().? |
| 98021 | else |
| 98022 | try self.copyToTmpRegister(ty, other_mcv), abi_size), |
| 98023 | mask_alias, |
| 98024 | ); |
| 98025 | } else if (has_blend) if (other_mcv.isBase()) try self.asmRegisterMemoryRegister( |
| 98026 | mir_tag, |
| 98027 | dst_alias, |
| 98028 | try other_mcv.mem(self, .{ .size = self.memSize(ty) }), |
| 98029 | mask_alias, |
| 98030 | ) else try self.asmRegisterRegisterRegister( |
| 98031 | mir_tag, |
| 98032 | dst_alias, |
| 98033 | registerAlias(if (other_mcv.isRegister()) |
| 98034 | other_mcv.getReg().? |
| 98035 | else |
| 98036 | try self.copyToTmpRegister(ty, other_mcv), abi_size), |
| 98037 | mask_alias, |
| 98038 | ) else { |
| 98039 | try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias); |
| 98040 | if (other_mcv.isBase()) try self.asmRegisterMemory( |
| 98041 | .{ mir_tag[0], .andn }, |
| 98042 | mask_alias, |
| 98043 | try other_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 98044 | ) else try self.asmRegisterRegister( |
| 98045 | .{ mir_tag[0], .andn }, |
| 98046 | mask_alias, |
| 98047 | if (other_mcv.isRegister()) |
| 98048 | other_mcv.getReg().? |
| 98049 | else |
| 98050 | try self.copyToTmpRegister(ty, other_mcv), |
| 98051 | ); |
| 98052 | try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias); |
| 98053 | } |
| 98054 | break :result dst_mcv; |
| 98055 | }, |
| 97922 | 98056 | else => {}, |
| 97923 | 98057 | } |
| 97924 | 98058 | const mask_reg: Register = if (need_xmm0) mask_reg: { |
| ... | ... | @@ -98121,7 +98255,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 98121 | 98255 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 98122 | 98256 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 98123 | 98257 | |
| 98124 | | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.childType(zcu).zigTypeTag(zcu)) { |
| 98258 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (elem_ty.zigTypeTag(zcu)) { |
| 98125 | 98259 | else => null, |
| 98126 | 98260 | .int => switch (abi_size) { |
| 98127 | 98261 | 0 => unreachable, |
| ... | ... | @@ -98137,7 +98271,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 98137 | 98271 | null, |
| 98138 | 98272 | else => null, |
| 98139 | 98273 | }, |
| 98140 | | .float => switch (ty.childType(zcu).floatBits(self.target.*)) { |
| 98274 | .float => switch (elem_ty.floatBits(self.target.*)) { |
| 98141 | 98275 | else => unreachable, |
| 98142 | 98276 | 16, 80, 128 => null, |
| 98143 | 98277 | 32 => switch (vec_len) { |
| ... | ... | @@ -98191,30 +98325,20 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 98191 | 98325 | try self.copyToTmpRegister(ty, lhs_mcv), abi_size), |
| 98192 | 98326 | mask_alias, |
| 98193 | 98327 | ) else { |
| 98194 | | const mir_fixes = @as(?Mir.Inst.Fixes, switch (elem_ty.zigTypeTag(zcu)) { |
| 98195 | | else => null, |
| 98196 | | .int => .p_, |
| 98197 | | .float => switch (elem_ty.floatBits(self.target.*)) { |
| 98198 | | 32 => ._ps, |
| 98199 | | 64 => ._pd, |
| 98200 | | 16, 80, 128 => null, |
| 98201 | | else => unreachable, |
| 98202 | | }, |
| 98203 | | }) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}); |
| 98204 | | try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_alias, mask_alias); |
| 98328 | try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias); |
| 98205 | 98329 | if (rhs_mcv.isBase()) try self.asmRegisterMemory( |
| 98206 | | .{ mir_fixes, .andn }, |
| 98330 | .{ mir_tag[0], .andn }, |
| 98207 | 98331 | mask_alias, |
| 98208 | 98332 | try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 98209 | 98333 | ) else try self.asmRegisterRegister( |
| 98210 | | .{ mir_fixes, .andn }, |
| 98334 | .{ mir_tag[0], .andn }, |
| 98211 | 98335 | mask_alias, |
| 98212 | 98336 | if (rhs_mcv.isRegister()) |
| 98213 | 98337 | rhs_mcv.getReg().? |
| 98214 | 98338 | else |
| 98215 | 98339 | try self.copyToTmpRegister(ty, rhs_mcv), |
| 98216 | 98340 | ); |
| 98217 | | try self.asmRegisterRegister(.{ mir_fixes, .@"or" }, dst_alias, mask_alias); |
| 98341 | try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias); |
| 98218 | 98342 | } |
| 98219 | 98343 | break :result dst_mcv; |
| 98220 | 98344 | }; |
| ... | ... | @@ -100753,11 +100877,11 @@ const Temp = struct { |
| 100753 | 100877 | const new_temp_index = cg.next_temp_index; |
| 100754 | 100878 | cg.temp_type[@intFromEnum(new_temp_index)] = .usize; |
| 100755 | 100879 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 100756 | | switch (temp.tracking(cg).short) { |
| 100757 | | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 100880 | const mcv = temp.tracking(cg).short; |
| 100881 | switch (mcv) { |
| 100882 | else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 100758 | 100883 | .register => |reg| { |
| 100759 | | const new_reg = |
| 100760 | | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 100884 | const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 100761 | 100885 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 100762 | 100886 | try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 100763 | 100887 | .base = .{ .reg = reg.to64() }, |
| ... | ... | @@ -100765,33 +100889,22 @@ const Temp = struct { |
| 100765 | 100889 | }); |
| 100766 | 100890 | }, |
| 100767 | 100891 | .register_offset => |reg_off| { |
| 100768 | | const new_reg = |
| 100769 | | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 100892 | const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 100770 | 100893 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 100771 | 100894 | try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 100772 | 100895 | .base = .{ .reg = reg_off.reg.to64() }, |
| 100773 | 100896 | .mod = .{ .rm = .{ .disp = reg_off.off + off } }, |
| 100774 | 100897 | }); |
| 100775 | 100898 | }, |
| 100899 | .load_symbol, .load_frame => { |
| 100900 | const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 100901 | new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ .reg = new_reg, .off = off } }); |
| 100902 | try cg.genSetReg(new_reg, .usize, mcv, .{}); |
| 100903 | }, |
| 100776 | 100904 | .lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{ |
| 100777 | 100905 | .sym_index = sym_off.sym_index, |
| 100778 | 100906 | .off = sym_off.off + off, |
| 100779 | 100907 | } }), |
| 100780 | | .load_frame => |frame_addr| { |
| 100781 | | const new_reg = |
| 100782 | | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 100783 | | new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ |
| 100784 | | .reg = new_reg, |
| 100785 | | .off = off, |
| 100786 | | } }); |
| 100787 | | try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ |
| 100788 | | .base = .{ .frame = frame_addr.index }, |
| 100789 | | .mod = .{ .rm = .{ |
| 100790 | | .size = .qword, |
| 100791 | | .disp = frame_addr.off, |
| 100792 | | } }, |
| 100793 | | }); |
| 100794 | | }, |
| 100795 | 100908 | .lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{ |
| 100796 | 100909 | .index = frame_addr.index, |
| 100797 | 100910 | .off = frame_addr.off + off, |
| ... | ... | @@ -101108,7 +101221,8 @@ const Temp = struct { |
| 101108 | 101221 | => return temp.toRegClass(true, .general_purpose, cg), |
| 101109 | 101222 | .lea_symbol => |sym_off| { |
| 101110 | 101223 | const off = sym_off.off; |
| 101111 | | if (off == 0) return false; |
| 101224 | // hack around linker relocation bugs |
| 101225 | if (false and off == 0) return false; |
| 101112 | 101226 | try temp.toOffset(-off, cg); |
| 101113 | 101227 | while (try temp.toRegClass(true, .general_purpose, cg)) {} |
| 101114 | 101228 | try temp.toOffset(off, cg); |