authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-21 08:46:12-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-24 20:56:11-05:00
logae3d95fc8dc10c0902dee0605421cec2dbd316b0
treec341176a09042324818f971ae679de2ac283c256
parent921725427efeae591793f49291807a41112ccbf9

x86_64: rewrite scalar float equality comparisons


6 files changed, 830 insertions(+), 178 deletions(-)

src/arch/x86_64/CodeGen.zig+768-168
......@@ -150,7 +150,7 @@ const Owner = union(enum) {
150150};
151151
152152const MaskKind = enum(u1) { sign, all };
153const MaskInfo = packed struct { kind: MaskKind, inverted: bool, scalar: Memory.Size };
153const MaskInfo = packed struct { kind: MaskKind, inverted: bool = false, scalar: Memory.Size };
154154
155155pub const MCValue = union(enum) {
156156 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.
......@@ -2657,10 +2657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
26572657 } else { // hack around Sema OPV bugs
26582658 res[0] = ops[0];
26592659 }
2660 for (ops) |op| for (res) |r| {
2661 if (op.index == r.index) break;
2662 } else try op.die(cg);
2663 try res[0].moveTo(inst, cg);
2660 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
26642661 },
26652662 .ptr_sub => |air_tag| if (use_old) try cg.airPtrArithmetic(inst, air_tag) else {
26662663 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
......@@ -2792,17 +2789,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
27922789 // hack around Sema OPV bugs
27932790 res[0] = ops[0];
27942791 }
2795 for (ops) |op| for (res) |r| {
2796 if (op.index == r.index) break;
2797 } else try op.die(cg);
2798 try res[0].moveTo(inst, cg);
2792 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
27992793 },
28002794 .alloc => if (use_old) try cg.airAlloc(inst) else {
28012795 const ty = air_datas[@intFromEnum(inst)].ty;
2802 var slot = try cg.tempInit(ty, .{ .lea_frame = .{
2796 const slot = try cg.tempInit(ty, .{ .lea_frame = .{
28032797 .index = try cg.allocMemPtr(inst),
28042798 } });
2805 try slot.moveTo(inst, cg);
2799 try slot.finish(inst, &.{}, &.{}, cg);
28062800 },
28072801 .inferred_alloc, .inferred_alloc_comptime => unreachable,
28082802 .ret_ptr => if (use_old) try cg.airRetPtr(inst) else {
......@@ -2818,7 +2812,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
28182812 break :slot slot;
28192813 },
28202814 };
2821 try slot.moveTo(inst, cg);
2815 try slot.finish(inst, &.{}, &.{}, cg);
28222816 },
28232817 .assembly => try cg.airAsm(inst),
28242818 .bit_and, .bit_or, .xor, .bool_and, .bool_or => |air_tag| if (use_old) try cg.airBinOp(inst, air_tag) else {
......@@ -3154,10 +3148,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
31543148 }),
31553149 else => |e| return e,
31563150 };
3157 for (ops) |op| for (res) |r| {
3158 if (op.index == r.index) break;
3159 } else try op.die(cg);
3160 try res[0].moveTo(inst, cg);
3151 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
31613152 },
31623153 .not => |air_tag| if (use_old) try cg.airUnOp(inst, air_tag) else {
31633154 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -4207,10 +4198,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42074198 }),
42084199 else => |e| return e,
42094200 };
4210 for (ops) |op| for (res) |r| {
4211 if (op.index == r.index) break;
4212 } else try op.die(cg);
4213 try res[0].moveTo(inst, cg);
4201 try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
42144202 },
42154203
42164204 .block => if (use_old) try cg.airBlock(inst) else {
......@@ -4250,13 +4238,13 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
42504238 .index = .ret_addr,
42514239 } });
42524240 while (try slot.toRegClass(true, .general_purpose, cg)) {}
4253 try slot.moveTo(inst, cg);
4241 try slot.finish(inst, &.{}, &.{}, cg);
42544242 },
42554243 .frame_addr => if (use_old) try cg.airFrameAddress(inst) else {
4256 var slot = try cg.tempInit(.usize, .{ .lea_frame = .{
4244 const slot = try cg.tempInit(.usize, .{ .lea_frame = .{
42574245 .index = .base_ptr,
42584246 } });
4259 try slot.moveTo(inst, cg);
4247 try slot.finish(inst, &.{}, &.{}, cg);
42604248 },
42614249 .call => try cg.airCall(inst, .auto, .{ .safety = true }),
42624250 .call_always_tail => try cg.airCall(inst, .always_tail, .{ .safety = true }),
......@@ -6986,10 +6974,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
69866974 }),
69876975 else => |e| return e,
69886976 };
6989 for (ops) |op| for (res) |r| {
6990 if (op.index == r.index) break;
6991 } else try op.die(cg);
6992 try res[0].moveTo(inst, cg);
6977 try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
69936978 },
69946979
69956980 .cmp_vector, .cmp_vector_optimized => |air_tag| if (use_old) try cg.airCmpVector(inst) else fallback: {
......@@ -8394,6 +8379,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
83948379 } },
83958380 }, .{
83968381 .dst_constraints = .{.{ .bool_vec = .byte }},
8382 .src_constraints = .{ .any_scalar_int, .any_scalar_int },
83978383 .patterns = &.{
83988384 .{ .src = .{ .to_mem, .to_mem } },
83998385 },
......@@ -8550,6 +8536,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
85508536 } },
85518537 }, .{
85528538 .dst_constraints = .{.{ .bool_vec = .dword }},
8539 .src_constraints = .{ .any_scalar_int, .any_scalar_int },
85538540 .patterns = &.{
85548541 .{ .src = .{ .to_mem, .to_mem } },
85558542 },
......@@ -8710,6 +8697,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
87108697 }, .{
87118698 .required_features = .{ .@"64bit", null, null, null },
87128699 .dst_constraints = .{.{ .bool_vec = .qword }},
8700 .src_constraints = .{ .any_scalar_int, .any_scalar_int },
87138701 .patterns = &.{
87148702 .{ .src = .{ .to_mem, .to_mem } },
87158703 },
......@@ -8784,6 +8772,72 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
87848772 .{ ._, ._r, .sh, .tmp3d, .si(3), ._, ._ },
87858773 .{ ._, ._, .mov, .memi(.dst0p, .tmp3), .tmp2p, ._, ._ },
87868774 } },
8775 }, .{
8776 .required_features = .{ .f16c, null, null, null },
8777 .src_constraints = .{
8778 .{ .scalar_exact_float = .{ .of = .qword, .is = .word } },
8779 .{ .scalar_exact_float = .{ .of = .qword, .is = .word } },
8780 },
8781 .patterns = &.{
8782 .{ .src = .{ .mem, .mem } },
8783 .{ .src = .{ .sse, .mem } },
8784 .{ .src = .{ .mem, .sse } },
8785 .{ .src = .{ .to_sse, .to_sse } },
8786 },
8787 .extra_temps = .{
8788 .{ .kind = .{ .rc = .sse } },
8789 .unused,
8790 .unused,
8791 .unused,
8792 .unused,
8793 .unused,
8794 },
8795 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
8796 .kind = .all,
8797 .scalar = .dword,
8798 } } }},
8799 .each = .{ .once = &.{
8800 .{ ._, .v_ps, .cvtph2, .dst0x, .src0q, ._, ._ },
8801 .{ ._, .v_ps, .cvtph2, .tmp0x, .src1q, ._, ._ },
8802 .{ ._, .v_ps, .cmp, .dst0x, .dst0x, .tmp0x, .si(switch (cc) {
8803 else => unreachable,
8804 .e => 0b00000,
8805 .ne => 0b00100,
8806 }) },
8807 } },
8808 }, .{
8809 .required_features = .{ .f16c, null, null, null },
8810 .src_constraints = .{
8811 .{ .scalar_exact_float = .{ .of = .xword, .is = .word } },
8812 .{ .scalar_exact_float = .{ .of = .xword, .is = .word } },
8813 },
8814 .patterns = &.{
8815 .{ .src = .{ .mem, .mem } },
8816 .{ .src = .{ .to_sse, .mem } },
8817 .{ .src = .{ .mem, .to_sse } },
8818 .{ .src = .{ .to_sse, .to_sse } },
8819 },
8820 .extra_temps = .{
8821 .{ .kind = .{ .rc = .sse } },
8822 .unused,
8823 .unused,
8824 .unused,
8825 .unused,
8826 .unused,
8827 },
8828 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
8829 .kind = .all,
8830 .scalar = .dword,
8831 } } }},
8832 .each = .{ .once = &.{
8833 .{ ._, .v_ps, .cvtph2, .dst0y, .src0x, ._, ._ },
8834 .{ ._, .v_ps, .cvtph2, .tmp0y, .src1x, ._, ._ },
8835 .{ ._, .v_ps, .cmp, .dst0y, .dst0y, .tmp0y, .si(switch (cc) {
8836 else => unreachable,
8837 .e => 0b00000,
8838 .ne => 0b00100,
8839 }) },
8840 } },
87878841 } },
87888842 }) catch |err| switch (err) {
87898843 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{
......@@ -8797,10 +8851,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
87978851 .gte => unreachable,
87988852 .gt => unreachable,
87998853 }
8800 for (ops) |op| for (res) |r| {
8801 if (op.index == r.index) break;
8802 } else try op.die(cg);
8803 try res[0].moveTo(inst, cg);
8854 try res[0].finish(inst, &.{ extra.lhs, extra.rhs }, &ops, cg);
88048855 },
88058856
88068857 .abs => |air_tag| if (use_old) try cg.airAbs(inst) else fallback: {
......@@ -9836,10 +9887,18 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
98369887 .required_features = .{ .x87, null, null, null },
98379888 .src_constraints = .{ .{ .scalar_exact_float = .{ .of = .xword, .is = .tbyte } }, .any },
98389889 .patterns = &.{
9890 .{ .src = .{ .mem, .none } },
98399891 .{ .src = .{ .to_x87, .none } },
98409892 },
9893 .extra_temps = .{
9894 .{ .type = .f80, .kind = .{ .reg = .st7 } },
9895 .unused,
9896 .unused,
9897 .unused,
9898 .unused,
9899 .unused,
9900 },
98419901 .dst_temps = .{.{ .mut_reg = .{ .ref = .src0, .rc = .x87 } }},
9842 .clobbers = .{ .st = 1 },
98439902 .each = .{ .once = &.{
98449903 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
98459904 .{ ._, .f_, .abs, ._, ._, ._, ._ },
......@@ -9967,10 +10026,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
996710026 }),
996810027 else => |e| return e,
996910028 };
9970 for (ops) |op| for (res) |r| {
9971 if (op.index == r.index) break;
9972 } else try op.die(cg);
9973 try res[0].moveTo(inst, cg);
10029 try res[0].finish(inst, &.{ty_op.operand}, &ops, cg);
997410030 },
997510031
997610032 .cmp_lt,
......@@ -10166,10 +10222,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1016610222 }),
1016710223 else => |e| return e,
1016810224 };
10169 for (ops) |op| for (res) |r| {
10170 if (op.index == r.index) break;
10171 } else try op.die(cg);
10172 try res[0].moveTo(inst, cg);
10225 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
1017310226 },
1017410227 .cmp_eq,
1017510228 .cmp_eq_optimized,
......@@ -10182,7 +10235,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1018210235 }) else fallback: {
1018310236 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
1018410237 const scalar_ty = cg.typeOf(bin_op.lhs).scalarType(zcu);
10185 if (cg.intInfo(scalar_ty) == null) break :fallback try cg.airCmp(inst, switch (air_tag) {
10238 if (cg.intInfo(scalar_ty) == null and cg.floatBits(scalar_ty) == null) break :fallback try cg.airCmp(inst, switch (air_tag) {
1018610239 else => unreachable,
1018710240 .cmp_eq, .cmp_eq_optimized => .eq,
1018810241 .cmp_neq, .cmp_neq_optimized => .neq,
......@@ -10424,6 +10477,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1042410477 } },
1042510478 }, .{
1042610479 .required_features = .{ .avx2, null, null, null },
10480 .src_constraints = .{
10481 .{ .remainder_int = .{ .of = .yword, .is = .yword } },
10482 .{ .remainder_int = .{ .of = .yword, .is = .yword } },
10483 },
1042710484 .patterns = &.{
1042810485 .{ .src = .{ .to_mem, .to_mem } },
1042910486 },
......@@ -10481,6 +10538,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1048110538 } },
1048210539 }, .{
1048310540 .required_features = .{ .avx, null, null, null },
10541 .src_constraints = .{
10542 .{ .remainder_int = .{ .of = .yword, .is = .yword } },
10543 .{ .remainder_int = .{ .of = .yword, .is = .yword } },
10544 },
1048410545 .patterns = &.{
1048510546 .{ .src = .{ .to_mem, .to_mem } },
1048610547 },
......@@ -10506,6 +10567,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1050610567 } },
1050710568 }, .{
1050810569 .required_features = .{ .avx, null, null, null },
10570 .src_constraints = .{
10571 .{ .remainder_int = .{ .of = .xword, .is = .xword } },
10572 .{ .remainder_int = .{ .of = .xword, .is = .xword } },
10573 },
1050910574 .patterns = &.{
1051010575 .{ .src = .{ .to_mem, .to_mem } },
1051110576 },
......@@ -10531,6 +10596,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1053110596 } },
1053210597 }, .{
1053310598 .required_features = .{ .sse4_1, null, null, null },
10599 .src_constraints = .{
10600 .{ .remainder_int = .{ .of = .xword, .is = .xword } },
10601 .{ .remainder_int = .{ .of = .xword, .is = .xword } },
10602 },
1053410603 .patterns = &.{
1053510604 .{ .src = .{ .to_mem, .to_mem } },
1053610605 },
......@@ -10556,6 +10625,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1055610625 } },
1055710626 }, .{
1055810627 .required_features = .{ .sse2, null, null, null },
10628 .src_constraints = .{
10629 .{ .remainder_int = .{ .of = .xword, .is = .xword } },
10630 .{ .remainder_int = .{ .of = .xword, .is = .xword } },
10631 },
1055910632 .patterns = &.{
1056010633 .{ .src = .{ .to_mem, .to_mem } },
1056110634 },
......@@ -10584,6 +10657,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1058410657 } },
1058510658 }, .{
1058610659 .required_features = .{ .sse, .mmx, null, null },
10660 .src_constraints = .{
10661 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
10662 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
10663 },
1058710664 .patterns = &.{
1058810665 .{ .src = .{ .to_mem, .to_mem } },
1058910666 },
......@@ -10611,6 +10688,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1061110688 .{ ._, ._, .cmp, .tmp0d, .si(0xff), ._, ._ },
1061210689 } },
1061310690 }, .{
10691 .src_constraints = .{
10692 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
10693 .{ .remainder_int = .{ .of = .qword, .is = .qword } },
10694 },
1061410695 .patterns = &.{
1061510696 .{ .src = .{ .to_mem, .to_mem } },
1061610697 },
......@@ -10634,6 +10715,443 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1063410715 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
1063510716 .{ ._, ._, .@"test", .tmp1p, .tmp1p, ._, ._ },
1063610717 } },
10718 }, .{
10719 .required_features = .{ .f16c, null, null, null },
10720 .src_constraints = .{ .{ .float = .word }, .{ .float = .word } },
10721 .patterns = &.{
10722 .{ .src = .{ .to_sse, .to_sse } },
10723 },
10724 .extra_temps = .{
10725 .{ .kind = .{ .rc = .sse } },
10726 .{ .kind = .{ .rc = .sse } },
10727 .unused,
10728 .unused,
10729 .unused,
10730 .unused,
10731 },
10732 .dst_temps = .{.{ .cc = switch (cc) {
10733 else => unreachable,
10734 .e => .z_and_np,
10735 .ne => .nz_or_p,
10736 } }},
10737 .clobbers = .{ .eflags = true },
10738 .each = .{ .once = &.{
10739 .{ ._, .vp_, .unpcklwd, .tmp0x, .src0x, .src1x, ._ },
10740 .{ ._, .v_ps, .cvtph2, .tmp0x, .tmp0x, ._, ._ },
10741 .{ ._, .v_, .movshdup, .tmp1x, .tmp0x, ._, ._ },
10742 .{ ._, .v_ss, .ucomi, .tmp0x, .tmp1x, ._, ._ },
10743 } },
10744 }, .{
10745 .required_features = .{ .sse, null, null, null },
10746 .src_constraints = .{ .{ .float = .word }, .{ .float = .word } },
10747 .patterns = &.{
10748 .{ .src = .{ .{ .to_reg = .xmm0 }, .{ .to_reg = .xmm1 } } },
10749 },
10750 .call_frame = .{ .size = 0, .alignment = .@"16" },
10751 .extra_temps = .{
10752 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (cc) {
10753 else => unreachable,
10754 .e => "__eqhf2",
10755 .ne => "__nehf2",
10756 } } } },
10757 .{ .type = .i32, .kind = .{ .reg = .eax } },
10758 .unused,
10759 .unused,
10760 .unused,
10761 .unused,
10762 },
10763 .dst_temps = .{.{ .cc = cc }},
10764 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
10765 .each = .{ .once = &.{
10766 .{ ._, ._, .call, .tmp0p, ._, ._, ._ },
10767 .{ ._, ._, .@"test", .tmp1d, .tmp1d, ._, ._ },
10768 } },
10769 }, .{
10770 .required_features = .{ .avx, null, null, null },
10771 .src_constraints = .{ .{ .float = .dword }, .{ .float = .dword } },
10772 .patterns = &.{
10773 .{ .src = .{ .to_sse, .mem } },
10774 .{ .src = .{ .mem, .to_sse }, .commute = .{ 0, 1 } },
10775 .{ .src = .{ .to_sse, .to_sse } },
10776 },
10777 .extra_temps = .{
10778 .{ .type = .f16, .kind = .{ .rc = .sse } },
10779 .{ .type = .f16, .kind = .{ .rc = .sse } },
10780 .unused,
10781 .unused,
10782 .unused,
10783 .unused,
10784 },
10785 .dst_temps = .{.{ .cc = switch (cc) {
10786 else => unreachable,
10787 .e => .z_and_np,
10788 .ne => .nz_or_p,
10789 } }},
10790 .clobbers = .{ .eflags = true },
10791 .each = .{ .once = &.{
10792 .{ ._, .v_ss, .ucomi, .src0x, .src1d, ._, ._ },
10793 } },
10794 }, .{
10795 .required_features = .{ .sse, null, null, null },
10796 .src_constraints = .{ .{ .float = .dword }, .{ .float = .dword } },
10797 .patterns = &.{
10798 .{ .src = .{ .to_sse, .mem } },
10799 .{ .src = .{ .mem, .to_sse }, .commute = .{ 0, 1 } },
10800 .{ .src = .{ .to_sse, .to_sse } },
10801 },
10802 .extra_temps = .{
10803 .{ .type = .f16, .kind = .{ .rc = .sse } },
10804 .{ .type = .f16, .kind = .{ .rc = .sse } },
10805 .unused,
10806 .unused,
10807 .unused,
10808 .unused,
10809 },
10810 .dst_temps = .{.{ .cc = switch (cc) {
10811 else => unreachable,
10812 .e => .z_and_np,
10813 .ne => .nz_or_p,
10814 } }},
10815 .clobbers = .{ .eflags = true },
10816 .each = .{ .once = &.{
10817 .{ ._, ._ss, .ucomi, .src0x, .src1d, ._, ._ },
10818 } },
10819 }, .{
10820 .required_features = .{ .sse, null, null, null },
10821 .src_constraints = .{ .{ .float = .dword }, .{ .float = .word } },
10822 .patterns = &.{
10823 .{ .src = .{ .{ .to_reg = .xmm0 }, .{ .to_reg = .xmm1 } } },
10824 },
10825 .call_frame = .{ .size = 0, .alignment = .@"16" },
10826 .extra_temps = .{
10827 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (cc) {
10828 else => unreachable,
10829 .e => "__eqsf2",
10830 .ne => "__nesf2",
10831 } } } },
10832 .{ .type = .i32, .kind = .{ .reg = .eax } },
10833 .unused,
10834 .unused,
10835 .unused,
10836 .unused,
10837 },
10838 .dst_temps = .{.{ .cc = cc }},
10839 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
10840 .each = .{ .once = &.{
10841 .{ ._, ._, .call, .tmp0p, ._, ._, ._ },
10842 .{ ._, ._, .@"test", .tmp1d, .tmp1d, ._, ._ },
10843 } },
10844 }, .{
10845 .required_features = .{ .avx, null, null, null },
10846 .src_constraints = .{ .{ .float = .qword }, .{ .float = .qword } },
10847 .patterns = &.{
10848 .{ .src = .{ .to_sse, .mem } },
10849 .{ .src = .{ .mem, .to_sse }, .commute = .{ 0, 1 } },
10850 .{ .src = .{ .to_sse, .to_sse } },
10851 },
10852 .extra_temps = .{
10853 .{ .type = .f16, .kind = .{ .rc = .sse } },
10854 .{ .type = .f16, .kind = .{ .rc = .sse } },
10855 .unused,
10856 .unused,
10857 .unused,
10858 .unused,
10859 },
10860 .dst_temps = .{.{ .cc = switch (cc) {
10861 else => unreachable,
10862 .e => .z_and_np,
10863 .ne => .nz_or_p,
10864 } }},
10865 .clobbers = .{ .eflags = true },
10866 .each = .{ .once = &.{
10867 .{ ._, .v_sd, .ucomi, .src0x, .src1q, ._, ._ },
10868 } },
10869 }, .{
10870 .required_features = .{ .sse2, null, null, null },
10871 .src_constraints = .{ .{ .float = .qword }, .{ .float = .qword } },
10872 .patterns = &.{
10873 .{ .src = .{ .to_sse, .mem } },
10874 .{ .src = .{ .mem, .to_sse }, .commute = .{ 0, 1 } },
10875 .{ .src = .{ .to_sse, .to_sse } },
10876 },
10877 .extra_temps = .{
10878 .{ .type = .f16, .kind = .{ .rc = .sse } },
10879 .{ .type = .f16, .kind = .{ .rc = .sse } },
10880 .unused,
10881 .unused,
10882 .unused,
10883 .unused,
10884 },
10885 .dst_temps = .{.{ .cc = switch (cc) {
10886 else => unreachable,
10887 .e => .z_and_np,
10888 .ne => .nz_or_p,
10889 } }},
10890 .clobbers = .{ .eflags = true },
10891 .each = .{ .once = &.{
10892 .{ ._, ._sd, .ucomi, .src0x, .src1q, ._, ._ },
10893 } },
10894 }, .{
10895 .required_features = .{ .sse, null, null, null },
10896 .src_constraints = .{ .{ .float = .qword }, .{ .float = .qword } },
10897 .patterns = &.{
10898 .{ .src = .{ .{ .to_reg = .xmm0 }, .{ .to_reg = .xmm1 } } },
10899 },
10900 .call_frame = .{ .size = 0, .alignment = .@"16" },
10901 .extra_temps = .{
10902 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (cc) {
10903 else => unreachable,
10904 .e => "__eqdf2",
10905 .ne => "__nedf2",
10906 } } } },
10907 .{ .type = .i32, .kind = .{ .reg = .eax } },
10908 .unused,
10909 .unused,
10910 .unused,
10911 .unused,
10912 },
10913 .dst_temps = .{.{ .cc = cc }},
10914 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
10915 .each = .{ .once = &.{
10916 .{ ._, ._, .call, .tmp0p, ._, ._, ._ },
10917 .{ ._, ._, .@"test", .tmp1d, .tmp1d, ._, ._ },
10918 } },
10919 }, .{
10920 .required_features = .{ .x87, .cmov, null, null },
10921 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
10922 .patterns = &.{
10923 .{ .src = .{ .mem, .mem } },
10924 },
10925 .extra_temps = .{
10926 .{ .type = .f80, .kind = .{ .reg = .st6 } },
10927 .{ .type = .f80, .kind = .{ .reg = .st7 } },
10928 .unused,
10929 .unused,
10930 .unused,
10931 .unused,
10932 },
10933 .dst_temps = .{.{ .cc = switch (cc) {
10934 else => unreachable,
10935 .e => .z_and_np,
10936 .ne => .nz_or_p,
10937 } }},
10938 .clobbers = .{ .eflags = true },
10939 .each = .{ .once = &.{
10940 .{ ._, .f_, .ld, .src1t, ._, ._, ._ },
10941 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
10942 .{ ._, .f_p, .ucomi, .tmp0t, .tmp1t, ._, ._ },
10943 .{ ._, .f_p, .st, .tmp1t, ._, ._, ._ },
10944 } },
10945 }, .{
10946 .required_features = .{ .x87, .cmov, null, null },
10947 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
10948 .patterns = &.{
10949 .{ .src = .{ .to_x87, .mem }, .commute = .{ 0, 1 } },
10950 .{ .src = .{ .mem, .to_x87 } },
10951 .{ .src = .{ .to_x87, .to_x87 } },
10952 },
10953 .extra_temps = .{
10954 .{ .type = .f80, .kind = .{ .reg = .st7 } },
10955 .unused,
10956 .unused,
10957 .unused,
10958 .unused,
10959 .unused,
10960 },
10961 .dst_temps = .{.{ .cc = switch (cc) {
10962 else => unreachable,
10963 .e => .z_and_np,
10964 .ne => .nz_or_p,
10965 } }},
10966 .clobbers = .{ .eflags = true },
10967 .each = .{ .once = &.{
10968 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
10969 .{ ._, .f_p, .ucomi, .tmp0t, .src1t, ._, ._ },
10970 } },
10971 }, .{
10972 .required_features = .{ .sahf, .x87, null, null },
10973 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
10974 .patterns = &.{
10975 .{ .src = .{ .mem, .mem } },
10976 },
10977 .extra_temps = .{
10978 .{ .type = .f80, .kind = .{ .reg = .st6 } },
10979 .{ .type = .f80, .kind = .{ .reg = .st7 } },
10980 .{ .type = .u16, .kind = .{ .reg = .ax } },
10981 .unused,
10982 .unused,
10983 .unused,
10984 },
10985 .dst_temps = .{.{ .cc = switch (cc) {
10986 else => unreachable,
10987 .e => .z_and_np,
10988 .ne => .nz_or_p,
10989 } }},
10990 .clobbers = .{ .eflags = true },
10991 .each = .{ .once = &.{
10992 .{ ._, .f_, .ld, .src1t, ._, ._, ._ },
10993 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
10994 .{ ._, .f_pp, .ucom, ._, ._, ._, ._ },
10995 .{ ._, .fn_sw, .st, .tmp2w, ._, ._, ._ },
10996 .{ ._, ._, .sahf, ._, ._, ._, ._ },
10997 } },
10998 }, .{
10999 .required_features = .{ .@"64bit", .x87, null, null },
11000 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
11001 .patterns = &.{
11002 .{ .src = .{ .mem, .mem } },
11003 },
11004 .extra_temps = .{
11005 .{ .type = .f80, .kind = .{ .reg = .st6 } },
11006 .{ .type = .f80, .kind = .{ .reg = .st7 } },
11007 .{ .type = .u16, .kind = .{ .reg = .ax } },
11008 .{ .type = .u8, .kind = .{ .reg = .ah } },
11009 .unused,
11010 .unused,
11011 },
11012 .dst_temps = .{.{ .cc = cc }},
11013 .clobbers = .{ .eflags = true },
11014 .each = .{ .once = &.{
11015 .{ ._, .f_, .ld, .src1t, ._, ._, ._ },
11016 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
11017 .{ ._, .f_pp, .ucom, ._, ._, ._, ._ },
11018 .{ ._, .fn_sw, .st, .tmp2w, ._, ._, ._ },
11019 .{ ._, ._, .xor, .tmp3b, .si(0b0_1_000_000), ._, ._ },
11020 .{ ._, ._, .@"test", .tmp3b, .si(0b0_1_000_100), ._, ._ },
11021 } },
11022 }, .{
11023 .required_features = .{ .x87, null, null, null },
11024 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
11025 .patterns = &.{
11026 .{ .src = .{ .mem, .mem } },
11027 },
11028 .extra_temps = .{
11029 .{ .type = .f80, .kind = .{ .reg = .st6 } },
11030 .{ .type = .f80, .kind = .{ .reg = .st7 } },
11031 .{ .type = .u16, .kind = .{ .reg = .ax } },
11032 .unused,
11033 .unused,
11034 .unused,
11035 },
11036 .dst_temps = .{.{ .cc = switch (cc) {
11037 else => unreachable,
11038 .e => .z_and_np,
11039 .ne => .nz_or_p,
11040 } }},
11041 .clobbers = .{ .eflags = true },
11042 .each = .{ .once = &.{
11043 .{ ._, .f_, .ld, .src1t, ._, ._, ._ },
11044 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
11045 .{ ._, .f_pp, .ucom, ._, ._, ._, ._ },
11046 .{ ._, .fn_sw, .st, .tmp2w, ._, ._, ._ },
11047 .{ ._, ._, .sahf, ._, ._, ._, ._ },
11048 } },
11049 }, .{
11050 .required_features = .{ .sahf, .x87, null, null },
11051 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
11052 .patterns = &.{
11053 .{ .src = .{ .to_x87, .mem }, .commute = .{ 0, 1 } },
11054 .{ .src = .{ .mem, .to_x87 } },
11055 .{ .src = .{ .to_x87, .to_x87 } },
11056 },
11057 .extra_temps = .{
11058 .{ .type = .f80, .kind = .{ .reg = .st6 } },
11059 .{ .type = .f80, .kind = .{ .reg = .st7 } },
11060 .{ .type = .u16, .kind = .{ .reg = .ax } },
11061 .unused,
11062 .unused,
11063 .unused,
11064 },
11065 .dst_temps = .{.{ .cc = switch (cc) {
11066 else => unreachable,
11067 .e => .z_and_np,
11068 .ne => .nz_or_p,
11069 } }},
11070 .clobbers = .{ .eflags = true },
11071 .each = .{ .once = &.{
11072 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
11073 .{ ._, .f_p, .ucom, .src1t, ._, ._, ._ },
11074 .{ ._, .fn_sw, .st, .tmp2w, ._, ._, ._ },
11075 .{ ._, ._, .sahf, ._, ._, ._, ._ },
11076 } },
11077 }, .{
11078 .required_features = .{ .@"64bit", .x87, null, null },
11079 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
11080 .patterns = &.{
11081 .{ .src = .{ .to_x87, .mem }, .commute = .{ 0, 1 } },
11082 .{ .src = .{ .mem, .to_x87 } },
11083 .{ .src = .{ .to_x87, .to_x87 } },
11084 },
11085 .extra_temps = .{
11086 .{ .type = .f80, .kind = .{ .reg = .st6 } },
11087 .{ .type = .f80, .kind = .{ .reg = .st7 } },
11088 .{ .type = .u16, .kind = .{ .reg = .ax } },
11089 .{ .type = .u8, .kind = .{ .reg = .ah } },
11090 .unused,
11091 .unused,
11092 },
11093 .dst_temps = .{.{ .cc = cc }},
11094 .clobbers = .{ .eflags = true },
11095 .each = .{ .once = &.{
11096 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
11097 .{ ._, .f_p, .ucom, .src1t, ._, ._, ._ },
11098 .{ ._, .fn_sw, .st, .tmp2w, ._, ._, ._ },
11099 .{ ._, ._, .xor, .tmp3b, .si(0b0_1_000_000), ._, ._ },
11100 .{ ._, ._, .@"test", .tmp3b, .si(0b0_1_000_100), ._, ._ },
11101 } },
11102 }, .{
11103 .required_features = .{ .x87, null, null, null },
11104 .src_constraints = .{ .{ .float = .tbyte }, .{ .float = .tbyte } },
11105 .patterns = &.{
11106 .{ .src = .{ .to_x87, .mem }, .commute = .{ 0, 1 } },
11107 .{ .src = .{ .mem, .to_x87 } },
11108 .{ .src = .{ .to_x87, .to_x87 } },
11109 },
11110 .extra_temps = .{
11111 .{ .type = .f80, .kind = .{ .reg = .st6 } },
11112 .{ .type = .f80, .kind = .{ .reg = .st7 } },
11113 .{ .type = .u16, .kind = .{ .reg = .ax } },
11114 .unused,
11115 .unused,
11116 .unused,
11117 },
11118 .dst_temps = .{.{ .cc = switch (cc) {
11119 else => unreachable,
11120 .e => .z_and_np,
11121 .ne => .nz_or_p,
11122 } }},
11123 .clobbers = .{ .eflags = true },
11124 .each = .{ .once = &.{
11125 .{ ._, .f_, .ld, .src0t, ._, ._, ._ },
11126 .{ ._, .f_p, .ucom, .src1t, ._, ._, ._ },
11127 .{ ._, .fn_sw, .st, .tmp2w, ._, ._, ._ },
11128 .{ ._, ._, .sahf, ._, ._, ._, ._ },
11129 } },
11130 }, .{
11131 .required_features = .{ .sse, null, null, null },
11132 .src_constraints = .{ .{ .float = .xword }, .{ .float = .xword } },
11133 .patterns = &.{
11134 .{ .src = .{ .{ .to_reg = .xmm0 }, .{ .to_reg = .xmm1 } } },
11135 },
11136 .call_frame = .{ .size = 0, .alignment = .@"16" },
11137 .extra_temps = .{
11138 .{ .type = .usize, .kind = .{ .symbol = &.{ .name = switch (cc) {
11139 else => unreachable,
11140 .e => "__eqtf2",
11141 .ne => "__netf2",
11142 } } } },
11143 .{ .type = .i32, .kind = .{ .reg = .eax } },
11144 .unused,
11145 .unused,
11146 .unused,
11147 .unused,
11148 },
11149 .dst_temps = .{.{ .cc = cc }},
11150 .clobbers = .{ .eflags = true, .caller_preserved = .ccc },
11151 .each = .{ .once = &.{
11152 .{ ._, ._, .call, .tmp0p, ._, ._, ._ },
11153 .{ ._, ._, .@"test", .tmp1d, .tmp1d, ._, ._ },
11154 } },
1063711155 } },
1063811156 }) catch |err| switch (err) {
1063911157 error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{
......@@ -10644,10 +11162,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1064411162 }),
1064511163 else => |e| return e,
1064611164 };
10647 for (ops) |op| for (res) |r| {
10648 if (op.index == r.index) break;
10649 } else try op.die(cg);
10650 try res[0].moveTo(inst, cg);
11165 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
1065111166 },
1065211167
1065311168 .cond_br => try cg.airCondBr(inst),
......@@ -10718,9 +11233,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1071811233 .fromSize(opt_child_abi_size) }),
1071911234 .u(0),
1072011235 );
10721 var is_null = try cg.tempInit(.bool, .{ .eflags = .e });
10722 try ops[0].die(cg);
10723 try is_null.moveTo(inst, cg);
11236 const is_null = try cg.tempInit(.bool, .{ .eflags = .e });
11237 try is_null.finish(inst, &.{un_op}, &ops, cg);
1072411238 },
1072511239 .is_non_null_ptr => if (use_old) try cg.airIsNonNullPtr(inst) else {
1072611240 const un_op = air_datas[@intFromEnum(inst)].un_op;
......@@ -10741,9 +11255,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1074111255 .fromSize(opt_child_abi_size) }),
1074211256 .u(0),
1074311257 );
10744 var is_non_null = try cg.tempInit(.bool, .{ .eflags = .ne });
10745 try ops[0].die(cg);
10746 try is_non_null.moveTo(inst, cg);
11258 const is_non_null = try cg.tempInit(.bool, .{ .eflags = .ne });
11259 try is_non_null.finish(inst, &.{un_op}, &ops, cg);
1074711260 },
1074811261 .is_err_ptr => if (use_old) try cg.airIsErrPtr(inst) else {
1074911262 const un_op = air_datas[@intFromEnum(inst)].un_op;
......@@ -10759,9 +11272,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1075911272 try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),
1076011273 .u(0),
1076111274 );
10762 var is_err = try cg.tempInit(.bool, .{ .eflags = .ne });
10763 try ops[0].die(cg);
10764 try is_err.moveTo(inst, cg);
11275 const is_err = try cg.tempInit(.bool, .{ .eflags = .ne });
11276 try is_err.finish(inst, &.{un_op}, &ops, cg);
1076511277 },
1076611278 .is_non_err_ptr => if (use_old) try cg.airIsNonErrPtr(inst) else {
1076711279 const un_op = air_datas[@intFromEnum(inst)].un_op;
......@@ -10777,9 +11289,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1077711289 try ops[0].tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(eu_err_ty) }),
1077811290 .u(0),
1077911291 );
10780 var is_non_err = try cg.tempInit(.bool, .{ .eflags = .e });
10781 try ops[0].die(cg);
10782 try is_non_err.moveTo(inst, cg);
11292 const is_non_err = try cg.tempInit(.bool, .{ .eflags = .e });
11293 try is_non_err.finish(inst, &.{un_op}, &ops, cg);
1078311294 },
1078411295 .load => if (use_old) try cg.airLoad(inst) else fallback: {
1078511296 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -10790,26 +11301,25 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1079011301 (ptr_info.flags.vector_index == .none or val_ty.toIntern() == .bool_type))
1079111302 break :fallback try cg.airLoad(inst);
1079211303 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
10793 var res = try ops[0].load(val_ty, .{
11304 const res = try ops[0].load(val_ty, .{
1079411305 .disp = switch (ptr_info.flags.vector_index) {
1079511306 .none => 0,
1079611307 .runtime => unreachable,
1079711308 else => |vector_index| @intCast(val_ty.abiSize(zcu) * @intFromEnum(vector_index)),
1079811309 },
1079911310 }, cg);
10800 for (ops) |op| if (op.index != res.index) try op.die(cg);
10801 try res.moveTo(inst, cg);
11311 try res.finish(inst, &.{ty_op.operand}, &ops, cg);
1080211312 },
1080311313 .int_from_ptr => if (use_old) try cg.airIntFromPtr(inst) else {
1080411314 const un_op = air_datas[@intFromEnum(inst)].un_op;
1080511315 var ops = try cg.tempsFromOperands(inst, .{un_op});
1080611316 try ops[0].toSlicePtr(cg);
10807 try ops[0].moveTo(inst, cg);
11317 try ops[0].finish(inst, &.{un_op}, &ops, cg);
1080811318 },
1080911319 .int_from_bool => if (use_old) try cg.airIntFromBool(inst) else {
1081011320 const un_op = air_datas[@intFromEnum(inst)].un_op;
10811 var ops = try cg.tempsFromOperands(inst, .{un_op});
10812 try ops[0].moveTo(inst, cg);
11321 const ops = try cg.tempsFromOperands(inst, .{un_op});
11322 try ops[0].finish(inst, &.{un_op}, &ops, cg);
1081311323 },
1081411324 .ret => try cg.airRet(inst, false),
1081511325 .ret_safe => try cg.airRet(inst, true),
......@@ -10848,8 +11358,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1084811358 .unreach => {},
1084911359 .optional_payload_ptr => if (use_old) try cg.airOptionalPayloadPtr(inst) else {
1085011360 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
10851 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
10852 try ops[0].moveTo(inst, cg);
11361 const ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
11362 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1085311363 },
1085411364 .optional_payload_ptr_set => if (use_old) try cg.airOptionalPayloadPtrSet(inst) else {
1085511365 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -10864,7 +11374,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1086411374 try has_value.die(cg);
1086511375 try ops[0].toOffset(-opt_child_abi_size, cg);
1086611376 }
10867 try ops[0].moveTo(inst, cg);
11377 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1086811378 },
1086911379 .unwrap_errunion_payload_ptr => if (use_old) try cg.airUnwrapErrUnionPayloadPtr(inst) else {
1087011380 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -10873,7 +11383,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1087311383 const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu));
1087411384 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1087511385 try ops[0].toOffset(eu_pl_off, cg);
10876 try ops[0].moveTo(inst, cg);
11386 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1087711387 },
1087811388 .unwrap_errunion_err_ptr => if (use_old) try cg.airUnwrapErrUnionErrPtr(inst) else {
1087911389 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -10882,9 +11392,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1088211392 const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
1088311393 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1088411394 try ops[0].toOffset(eu_err_off, cg);
10885 var err = try ops[0].load(eu_ty.errorUnionSet(zcu), .{}, cg);
10886 try ops[0].die(cg);
10887 try err.moveTo(inst, cg);
11395 const err = try ops[0].load(eu_ty.errorUnionSet(zcu), .{}, cg);
11396 try err.finish(inst, &.{ty_op.operand}, &ops, cg);
1088811397 },
1088911398 .errunion_payload_ptr_set => if (use_old) try cg.airErrUnionPayloadPtrSet(inst) else {
1089011399 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -10899,7 +11408,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1089911408 try ops[0].store(&no_err, .{}, cg);
1090011409 try no_err.die(cg);
1090111410 try ops[0].toOffset(eu_pl_off - eu_err_off, cg);
10902 try ops[0].moveTo(inst, cg);
11411 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1090311412 },
1090411413 .struct_field_ptr => if (use_old) try cg.airStructFieldPtr(inst) else {
1090511414 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
......@@ -10910,7 +11419,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1091011419 ty_pl.ty.toType(),
1091111420 extra.field_index,
1091211421 ), cg);
10913 try ops[0].moveTo(inst, cg);
11422 try ops[0].finish(inst, &.{extra.struct_operand}, &ops, cg);
1091411423 },
1091511424 .struct_field_ptr_index_0,
1091611425 .struct_field_ptr_index_1,
......@@ -10936,7 +11445,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1093611445 .struct_field_ptr_index_3 => 3,
1093711446 },
1093811447 ), cg);
10939 try ops[0].moveTo(inst, cg);
11448 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1094011449 },
1094111450 .struct_field_val => if (use_old) try cg.airStructFieldVal(inst) else fallback: {
1094211451 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
......@@ -10953,8 +11462,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1095311462 try ops[0].read(field_ty, .{ .disp = field_off }, cg)
1095411463 else
1095511464 try cg.tempInit(field_ty, .none);
10956 for (ops) |op| if (op.index != res.index) try op.die(cg);
10957 try res.moveTo(inst, cg);
11465 try res.finish(inst, &.{extra.struct_operand}, &ops, cg);
1095811466 },
1095911467 .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {
1096011468 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
......@@ -10965,7 +11473,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1096511473 if (union_layout.tag_size > 0) try ops[0].store(&ops[1], .{
1096611474 .disp = @intCast(union_layout.tagOffset()),
1096711475 }, cg);
10968 for (ops) |op| try op.die(cg);
11476 const res = try cg.tempInit(.void, .none);
11477 try res.finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
1096911478 },
1097011479 .get_union_tag => if (use_old) try cg.airGetUnionTag(inst) else {
1097111480 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -10973,42 +11482,41 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1097311482 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1097411483 const union_layout = union_ty.unionGetLayout(zcu);
1097511484 assert(union_layout.tag_size > 0);
10976 var res = try ops[0].read(ty_op.ty.toType(), .{
11485 const res = try ops[0].read(ty_op.ty.toType(), .{
1097711486 .disp = @intCast(union_layout.tagOffset()),
1097811487 }, cg);
10979 for (ops) |op| if (op.index != res.index) try op.die(cg);
10980 try res.moveTo(inst, cg);
11488 try res.finish(inst, &.{ty_op.operand}, &ops, cg);
1098111489 },
1098211490 .slice => if (use_old) try cg.airSlice(inst) else {
1098311491 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
1098411492 const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
1098511493 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
1098611494 try ops[0].toPair(&ops[1], cg);
10987 try ops[0].moveTo(inst, cg);
11495 try ops[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
1098811496 },
1098911497 .slice_len => if (use_old) try cg.airSliceLen(inst) else {
1099011498 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
1099111499 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1099211500 try ops[0].toSliceLen(cg);
10993 try ops[0].moveTo(inst, cg);
11501 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1099411502 },
1099511503 .slice_ptr => if (use_old) try cg.airSlicePtr(inst) else {
1099611504 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
1099711505 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1099811506 try ops[0].toSlicePtr(cg);
10999 try ops[0].moveTo(inst, cg);
11507 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1100011508 },
1100111509 .ptr_slice_len_ptr => if (use_old) try cg.airPtrSliceLenPtr(inst) else {
1100211510 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
1100311511 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1100411512 try ops[0].toOffset(8, cg);
11005 try ops[0].moveTo(inst, cg);
11513 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1100611514 },
1100711515 .ptr_slice_ptr_ptr => if (use_old) try cg.airPtrSlicePtrPtr(inst) else {
1100811516 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
1100911517 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1101011518 try ops[0].toOffset(0, cg);
11011 try ops[0].moveTo(inst, cg);
11519 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1101211520 },
1101311521 .slice_elem_val, .ptr_elem_val => |air_tag| if (use_old) switch (air_tag) {
1101411522 else => unreachable,
......@@ -11139,10 +11647,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1113911647 // hack around Sema OPV bugs
1114011648 res[0] = try cg.tempInit(res_ty, .none);
1114111649 }
11142 for (ops) |op| for (res) |r| {
11143 if (op.index == r.index) break;
11144 } else try op.die(cg);
11145 try res[0].moveTo(inst, cg);
11650 try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
1114611651 },
1114711652 .slice_elem_ptr, .ptr_elem_ptr => |air_tag| if (use_old) switch (air_tag) {
1114811653 else => unreachable,
......@@ -11195,8 +11700,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1119511700 } },
1119611701 });
1119711702 }
11198 try ops[1].die(cg);
11199 try ops[0].moveTo(inst, cg);
11703 try ops[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg);
1120011704 },
1120111705 .array_to_slice => if (use_old) try cg.airArrayToSlice(inst) else {
1120211706 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
......@@ -11205,7 +11709,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1120511709 .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu),
1120611710 });
1120711711 try ops[0].toPair(&len, cg);
11208 try ops[0].moveTo(inst, cg);
11712 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1120911713 },
1121011714 .error_set_has_value => return cg.fail("TODO implement error_set_has_value", .{}),
1121111715 .union_init => if (use_old) try cg.airUnionInit(inst) else {
......@@ -11228,8 +11732,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1122811732 try res.write(&ops[0], .{
1122911733 .disp = @intCast(union_layout.payloadOffset()),
1123011734 }, cg);
11231 try ops[0].die(cg);
11232 try res.moveTo(inst, cg);
11735 try res.finish(inst, &.{extra.init}, &ops, cg);
1123311736 },
1123411737 .field_parent_ptr => if (use_old) try cg.airFieldParentPtr(inst) else {
1123511738 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
......@@ -11240,7 +11743,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1124011743 cg.typeOf(extra.field_ptr),
1124111744 extra.field_index,
1124211745 ), cg);
11243 try ops[0].moveTo(inst, cg);
11746 try ops[0].finish(inst, &.{extra.field_ptr}, &ops, cg);
1124411747 },
1124511748
1124611749 .is_named_enum_value => return cg.fail("TODO implement is_named_enum_value", .{}),
......@@ -11274,8 +11777,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1127411777
1127511778 .addrspace_cast => {
1127611779 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
11277 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
11278 try ops[0].moveTo(inst, cg);
11780 const ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
11781 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
1127911782 },
1128011783
1128111784 .save_err_return_trace_index => {
......@@ -21474,11 +21977,16 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
2147421977 const ret_ty = self.fn_type.fnReturnType(zcu);
2147521978 switch (self.ret_mcv.short) {
2147621979 .none => {},
21477 .register,
21478 .register_pair,
21479 .register_triple,
21480 .register_quadruple,
21481 => try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety }),
21980 .register => |reg| {
21981 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
21982 defer self.register_manager.unlockReg(reg_lock);
21983 try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety });
21984 },
21985 inline .register_pair, .register_triple, .register_quadruple => |regs| {
21986 const reg_locks = self.register_manager.lockRegsAssumeUnused(regs.len, regs);
21987 defer for (reg_locks) |reg_lock| self.register_manager.unlockReg(reg_lock);
21988 try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }, .{ .safety = safety });
21989 },
2148221990 .indirect => |reg_off| {
2148321991 try self.register_manager.getReg(reg_off.reg, null);
2148421992 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);
......@@ -29772,6 +30280,7 @@ const Temp = struct {
2977230280 cg.temp_type[@intFromEnum(result_temp_index)] = .slice_const_u8;
2977330281 result_temp_index.tracking(cg).* = .init(result);
2977430282 first_temp.* = result_temp;
30283 second_temp.* = result_temp;
2977530284 }
2977630285
2977730286 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {
......@@ -30248,7 +30757,20 @@ const Temp = struct {
3024830757 try cg.asmOpOnly(.{ .@"rep _sb", .sto });
3024930758 }
3025030759
30251 fn moveTo(temp: Temp, inst: Air.Inst.Index, cg: *CodeGen) !void {
30760 fn finish(
30761 temp: Temp,
30762 inst: Air.Inst.Index,
30763 op_refs: []const Air.Inst.Ref,
30764 op_temps: []const Temp,
30765 cg: *CodeGen,
30766 ) !void {
30767 const tomb_bits = cg.liveness.getTombBits(inst);
30768 for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| {
30769 if (op_temp.index != temp.index) try op_temp.die(cg);
30770 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
30771 if (cg.reused_operands.isSet(op_index)) continue;
30772 try cg.processDeath(op_ref.toIndexAllowNone() orelse continue);
30773 }
3025230774 if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) {
3025330775 .ref, .err_ret_trace => {
3025430776 const result = try cg.allocRegOrMem(inst, true);
......@@ -30529,35 +31051,94 @@ const Select = struct {
3052931051 };
3053031052 switch (mir_tag[0]) {
3053131053 .f_ => switch (mir_tag[1]) {
30532 .abs, .st => {},
31054 .@"2xm1",
31055 .abs,
31056 .add,
31057 .chs,
31058 .clex,
31059 .com,
31060 .comi,
31061 .cos,
31062 .div,
31063 .divr,
31064 .free,
31065 .mul,
31066 .nop,
31067 .prem,
31068 .rndint,
31069 .scale,
31070 .sin,
31071 .sqrt,
31072 .st,
31073 .sub,
31074 .subr,
31075 .tst,
31076 .ucom,
31077 .ucomi,
31078 .wait,
31079 .xam,
31080 .xch,
31081 => {},
31082 .init, .save => s.top = 0,
31083 .ld, .ptan, .sincos, .xtract => s.top -%= 1,
31084 .patan, .yl2x => s.top +%= 1,
31085 .rstor => unreachable,
31086 else => unreachable,
31087 },
31088 .f_1 => switch (mir_tag[1]) {
3053331089 .ld => s.top -%= 1,
30534 else => {
30535 const fixes = @tagName(mir_tag[0]);
30536 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
30537 std.debug.panic("{s}: {s}{s}{s}\n", .{
30538 @src().fn_name,
30539 fixes[0..fixes_blank],
30540 @tagName(mir_tag[1]),
30541 fixes[fixes_blank + 1 ..],
30542 });
30543 },
31090 .prem => {},
31091 else => unreachable,
3054431092 },
30545 .f_p => switch (mir_tag[1]) {
31093 .f_b, .f_be, .f_e, .f_nb, .f_nbe, .f_ne, .f_nu, .f_u => switch (mir_tag[1]) {
31094 .cmov => {},
31095 else => unreachable,
31096 },
31097 .f_cw, .f_env, .f_sw => switch (mir_tag[1]) {
31098 .ld, .st => {},
31099 else => unreachable,
31100 },
31101 .f_p1 => switch (mir_tag[1]) {
31102 .yl2x => s.top +%= 1,
31103 else => unreachable,
31104 },
31105 .fb_ => switch (mir_tag[1]) {
31106 .ld => s.top -%= 1,
31107 else => unreachable,
31108 },
31109 .fb_p => switch (mir_tag[1]) {
3054631110 .st => s.top +%= 1,
30547 else => {
30548 const fixes = @tagName(mir_tag[0]);
30549 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
30550 std.debug.panic("{s}: {s}{s}{s}\n", .{
30551 @src().fn_name,
30552 fixes[0..fixes_blank],
30553 @tagName(mir_tag[1]),
30554 fixes[fixes_blank + 1 ..],
30555 });
30556 },
31111 else => unreachable,
3055731112 },
30558 .f_1,
30559 => switch (mir_tag[1]) {
31113 .fi_ => switch (mir_tag[1]) {
31114 .add, .com, .div, .divr, .mul, .st, .stt, .sub, .subr => {},
3056031115 .ld => s.top -%= 1,
31116 else => unreachable,
31117 },
31118 .fi_p => switch (mir_tag[1]) {
31119 .com, .st => s.top +%= 1,
31120 else => unreachable,
31121 },
31122 .fn_ => switch (mir_tag[1]) {
31123 .clex => {},
31124 .init, .save => s.top = 0,
31125 else => unreachable,
31126 },
31127 .fn_cw, .fn_env, .fn_sw => switch (mir_tag[1]) {
31128 .st => {},
31129 else => unreachable,
31130 },
31131 .f_cstp => switch (mir_tag[1]) {
31132 .de => s.top -%= 1,
31133 .in => s.top +%= 1,
31134 else => unreachable,
31135 },
31136 .f_l2e, .f_l2t, .f_lg2, .f_ln2, .f_pi, .f_z => switch (mir_tag[1]) {
31137 .ld => s.top -%= 1,
31138 else => unreachable,
31139 },
31140 .f_p => switch (mir_tag[1]) {
31141 .add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1,
3056131142 else => {
3056231143 const fixes = @tagName(mir_tag[0]);
3056331144 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
......@@ -30569,41 +31150,13 @@ const Select = struct {
3056931150 });
3057031151 },
3057131152 },
30572 .f_l2e,
30573 .f_l2t,
30574 .f_lg2,
30575 .f_ln2,
30576 .f_pi,
30577 .f_z,
30578 => switch (mir_tag[1]) {
30579 .ld => s.top -%= 1,
31153 .f_pp => switch (mir_tag[1]) {
31154 .com, .ucom => s.top +%= 2,
3058031155 else => unreachable,
3058131156 },
30582 .f_b,
30583 .f_be,
30584 .f_cw,
30585 .f_e,
30586 .f_env,
30587 .f_nb,
30588 .f_nbe,
30589 .f_ne,
30590 .f_nu,
30591 .f_p1,
30592 .f_pp,
30593 .f_sw,
30594 .f_u,
30595 .fb_,
30596 .fb_p,
30597 .fi_,
30598 .fi_p,
30599 .fn_,
30600 .fn_cw,
30601 .fn_env,
30602 .fn_sw,
30603 => {},
30604 .f_cstp => switch (mir_tag[1]) {
30605 .de => s.top -%= 1,
30606 .in => s.top +%= 1,
31157 .fx_ => switch (mir_tag[1]) {
31158 .rstor => unreachable,
31159 .save => {},
3060731160 else => unreachable,
3060831161 },
3060931162 else => {},
......@@ -30620,9 +31173,13 @@ const Select = struct {
3062031173 dst_constraints: [@intFromEnum(Select.Operand.Ref.src0) - @intFromEnum(Select.Operand.Ref.dst0)]Constraint = @splat(.any),
3062131174 src_constraints: [@intFromEnum(Select.Operand.Ref.none) - @intFromEnum(Select.Operand.Ref.src0)]Constraint = @splat(.any),
3062231175 patterns: []const Select.Pattern,
31176 call_frame: packed struct(u16) { size: u10, alignment: InternPool.Alignment } = .{ .size = 0, .alignment = .none },
3062331177 extra_temps: [@intFromEnum(Select.Operand.Ref.dst0) - @intFromEnum(Select.Operand.Ref.tmp0)]TempSpec = @splat(.unused),
3062431178 dst_temps: [@intFromEnum(Select.Operand.Ref.src0) - @intFromEnum(Select.Operand.Ref.dst0)]TempSpec.Kind = @splat(.unused),
30625 clobbers: struct { eflags: bool = false, st: u3 = 0 } = .{},
31179 clobbers: packed struct {
31180 eflags: bool = false,
31181 caller_preserved: enum(u2) { none, ccc, zigcc } = .none,
31182 } = .{},
3062631183 each: union(enum) {
3062731184 once: []const Instruction,
3062831185 },
......@@ -30649,6 +31206,7 @@ const Select = struct {
3064931206 scalar_signed_int: Memory.Size,
3065031207 scalar_unsigned_int: Memory.Size,
3065131208 scalar_remainder_int: struct { of: Memory.Size, is: Memory.Size },
31209 float: Memory.Size,
3065231210 scalar_float: struct { of: Memory.Size, is: Memory.Size },
3065331211 scalar_exact_float: struct { of: Memory.Size, is: Memory.Size },
3065431212 multiple_scalar_int: struct { of: Memory.Size, is: Memory.Size },
......@@ -30716,6 +31274,7 @@ const Select = struct {
3071631274 of_is.is.bitSize(cg.target) >= (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1
3071731275 else
3071831276 false,
31277 .float => |size| if (cg.floatBits(ty)) |float_bits| size.bitSize(cg.target) == float_bits else false,
3071931278 .scalar_float => |of_is| @divExact(of_is.of.bitSize(cg.target), 8) >= ty.abiSize(zcu) and
3072031279 if (cg.floatBits(ty.scalarType(zcu))) |float_bits| of_is.is.bitSize(cg.target) >= float_bits else false,
3072131280 .scalar_exact_float => |of_is| @divExact(of_is.of.bitSize(cg.target), 8) >= ty.abiSize(zcu) and
......@@ -30787,13 +31346,14 @@ const Select = struct {
3078731346 src: [2]Src,
3078831347 commute: struct { u8, u8 } = .{ 0, 0 },
3078931348
30790 const Src = enum {
31349 const Src = union(enum) {
3079131350 none,
3079231351 any,
3079331352 imm8,
3079431353 imm16,
3079531354 imm32,
3079631355 simm32,
31356 to_reg: Register,
3079731357 mem,
3079831358 to_mem,
3079931359 mut_mem,
......@@ -30846,6 +31406,7 @@ const Select = struct {
3084631406 .mem => temp.tracking(cg).short.isMemory(),
3084731407 .to_mem, .to_mut_mem => true,
3084831408 .mut_mem => temp.isMut(cg) and temp.tracking(cg).short.isMemory(),
31409 .to_reg => true,
3084931410 .gpr => temp.typeOf(cg).abiSize(cg.pt.zcu) <= 8 and switch (temp.tracking(cg).short) {
3085031411 .register => |reg| reg.class() == .general_purpose,
3085131412 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and reg_off.off == 0,
......@@ -30920,6 +31481,7 @@ const Select = struct {
3092031481 .none => unreachable,
3092131482 .any, .imm8, .imm16, .imm32, .simm32 => false,
3092231483 .mem, .to_mem, .mut_mem, .to_mut_mem => try temp.toBase(cg),
31484 .to_reg => |reg| try temp.toReg(reg, cg),
3092331485 .gpr, .to_gpr => try temp.toRegClass(false, .general_purpose, cg),
3092431486 .mut_gpr, .to_mut_gpr => try temp.toRegClass(true, .general_purpose, cg),
3092531487 .x87, .to_x87 => try temp.toRegClass(false, .x87, cg),
......@@ -30954,6 +31516,7 @@ const Select = struct {
3095431516 ref: Select.Operand.Ref,
3095531517 ref_mask: struct { ref: Select.Operand.Ref, info: MaskInfo },
3095631518 mut_reg: struct { ref: Select.Operand.Ref, rc: Register.Class },
31519 symbol: *const struct { lib: ?[]const u8 = null, name: []const u8 },
3095731520
3095831521 const ConstInfo = struct { ref: Select.Operand.Ref, vectorize: bool = false };
3095931522
......@@ -31048,6 +31611,11 @@ const Select = struct {
3104831611 };
3104931612 return try cg.tempAllocReg(spec.type, regSetForRegClass(ref_rc.rc));
3105031613 },
31614 .symbol => |symbol| if (cg.bin_file.cast(.elf)) |elf_file| try cg.tempInit(spec.type, .{ .lea_symbol = .{
31615 .sym_index = try elf_file.getGlobalSymbol(symbol.name, symbol.lib),
31616 } }) else if (cg.bin_file.cast(.macho)) |macho_file| try cg.tempInit(spec.type, .{ .lea_symbol = .{
31617 .sym_index = try macho_file.getGlobalSymbol(symbol.name, symbol.lib),
31618 } }) else cg.fail("external symbols unimplemented for {s}", .{@tagName(cg.bin_file.tag)}),
3105131619 };
3105231620 }
3105331621 };
......@@ -31566,6 +32134,7 @@ const Select = struct {
3156632134 } },
3156732135 else => |mcv| .{ .mem = try mcv.mem(s.cg, .{ .size = op.base.size }) },
3156832136 .register => |reg| .{ .reg = s.lowerReg(registerAlias(reg, @intCast(@divExact(op.base.size.bitSize(s.cg.target), 8)))) },
32137 .lea_symbol => |sym_off| .{ .imm = .rel(sym_off) },
3156932138 },
3157032139 .simm => .{ .imm = .s(op.adjustedImm(i32, s)) },
3157132140 .uimm => .{ .imm = .u(@bitCast(op.adjustedImm(i64, s))) },
......@@ -31601,6 +32170,7 @@ fn select(
3160132170 src_temps: []Temp,
3160232171 cases: []const Select.Case,
3160332172) !void {
32173 @setEvalBranchQuota(33_600);
3160432174 cases: for (cases) |case| {
3160532175 for (case.required_features) |required_feature| if (required_feature) |feature| if (!cg.hasFeature(feature)) continue :cases;
3160632176 for (case.dst_constraints[0..dst_temps.len], dst_tys) |dst_constraint, dst_ty| if (!dst_constraint.accepts(dst_ty, cg)) continue :cases;
......@@ -31613,6 +32183,16 @@ fn select(
3161332183 for (pattern.src[0..src_temps.len], src_temps) |src_pattern, src_temp| if (!src_pattern.matches(src_temp, cg)) continue :patterns;
3161432184 if (std.debug.runtime_safety) for (pattern.src[src_temps.len..]) |src_pattern| assert(src_pattern == .none);
3161532185
32186 if (case.call_frame.alignment != .none) {
32187 const frame_allocs_slice = cg.frame_allocs.slice();
32188 const stack_frame_size =
32189 &frame_allocs_slice.items(.abi_size)[@intFromEnum(FrameIndex.call_frame)];
32190 stack_frame_size.* = @max(stack_frame_size.*, case.call_frame.size);
32191 const stack_frame_align =
32192 &frame_allocs_slice.items(.abi_align)[@intFromEnum(FrameIndex.call_frame)];
32193 stack_frame_align.* = stack_frame_align.max(case.call_frame.alignment);
32194 }
32195
3161632196 var s: Select = .{
3161732197 .cg = cg,
3161832198 .temps = undefined,
......@@ -31623,10 +32203,19 @@ fn select(
3162332203 const dst_slots = s.temps[@intFromEnum(Select.Operand.Ref.dst0)..@intFromEnum(Select.Operand.Ref.src0)];
3162432204 const src_slots = s.temps[@intFromEnum(Select.Operand.Ref.src0)..@intFromEnum(Select.Operand.Ref.none)];
3162532205
31626 for (0..case.clobbers.st -| 1) |i| {
31627 const tracked_index: RegisterManager.TrackedIndex = @intCast(RegisterManager.indexOfKnownRegIntoTracked(.st6).? - i);
31628 try cg.register_manager.getRegIndex(tracked_index, null);
31629 _ = cg.register_manager.lockRegIndexAssumeUnused(tracked_index);
32206 caller_preserved: {
32207 switch (switch (case.clobbers.caller_preserved) {
32208 .none => break :caller_preserved,
32209 .ccc => cg.target.cCallingConvention().?,
32210 .zigcc => .auto,
32211 }) {
32212 else => unreachable,
32213 inline .x86_64_sysv, .x86_64_win, .auto => |_, tag| inline for (comptime abi.getCallerPreservedRegs(tag)) |reg| {
32214 const tracked_index = RegisterManager.indexOfKnownRegIntoTracked(reg) orelse continue;
32215 try cg.register_manager.getRegIndex(tracked_index, null);
32216 assert(cg.register_manager.lockRegIndexAssumeUnused(tracked_index).tracked_index == tracked_index);
32217 },
32218 }
3163032219 }
3163132220
3163232221 @memcpy(src_slots[0..src_temps.len], src_temps);
......@@ -31653,9 +32242,20 @@ fn select(
3165332242 }
3165432243 assert(s.top == 0);
3165532244
31656 for (0..case.clobbers.st -| 1) |i| cg.register_manager.unlockReg(.{
31657 .tracked_index = @intCast(RegisterManager.indexOfKnownRegIntoTracked(.st6).? - i),
31658 });
32245 caller_preserved: {
32246 switch (switch (case.clobbers.caller_preserved) {
32247 .none => break :caller_preserved,
32248 .ccc => cg.target.cCallingConvention().?,
32249 .zigcc => .auto,
32250 }) {
32251 else => unreachable,
32252 inline .x86_64_sysv, .x86_64_win, .auto => |_, tag| inline for (comptime abi.getCallerPreservedRegs(tag)) |reg| {
32253 cg.register_manager.unlockReg(.{
32254 .tracked_index = RegisterManager.indexOfKnownRegIntoTracked(reg) orelse continue,
32255 });
32256 },
32257 }
32258 }
3165932259 for (dst_temps, case.dst_temps[0..dst_temps.len]) |dst_temp, dst_kind| dst_kind.finish(dst_temp, &s);
3166032260 for (case.extra_temps, tmp_slots) |spec, temp| if (spec.kind != .unused) try temp.die(cg);
3166132261 return;
src/arch/x86_64/Encoding.zig+3-2
......@@ -361,7 +361,7 @@ pub const Mnemonic = enum {
361361 addps, addss,
362362 andps,
363363 andnps,
364 cmpps, cmpss,
364 cmpps, cmpss, comiss,
365365 cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,
366366 divps, divss,
367367 fxrstor, fxrstor64, fxsave, fxsave64,
......@@ -386,7 +386,7 @@ pub const Mnemonic = enum {
386386 andpd,
387387 andnpd,
388388 cmppd, //cmpsd,
389 comisd, comiss,
389 comisd,
390390 cvtdq2pd, cvtdq2ps, cvtpd2dq, cvtpd2pi, cvtpd2ps, cvtpi2pd,
391391 cvtps2dq, cvtps2pd, cvtsd2si, cvtsd2ss, cvtsi2sd, cvtss2sd,
392392 cvttpd2dq, cvttpd2pi, cvttps2dq, cvttsd2si,
......@@ -504,6 +504,7 @@ pub const Mnemonic = enum {
504504 vstmxcsr,
505505 vsubpd, vsubps, vsubsd, vsubss,
506506 vtestpd, vtestps,
507 vucomisd, vucomiss,
507508 vxorpd, vxorps,
508509 // F16C
509510 vcvtph2ps, vcvtps2ph,
src/arch/x86_64/Mir.zig+4-4
......@@ -354,6 +354,8 @@ pub const Inst = struct {
354354 fn_env,
355355 /// Float No Wait ___ status word
356356 fn_sw,
357 /// Float Extended ___
358 fx_,
357359
358360 /// ___ in 32-bit and Compatibility Mode
359361 _32,
......@@ -817,8 +819,10 @@ pub const Inst = struct {
817819 /// Round to integer
818820 rndint,
819821 /// Restore x87 FPU state
822 /// Restore x87 FPU, MMX, XMM, and MXCSR state
820823 rstor,
821824 /// Store x87 FPU state
825 /// Save x87 FPU, MMX technology, and MXCSR state
822826 save,
823827 /// Scale
824828 scale,
......@@ -923,10 +927,6 @@ pub const Inst = struct {
923927 /// Extract doubleword
924928 /// Extract quadword
925929 extr,
926 /// Restore x87 FPU, MMX, XMM, and MXCSR state
927 fxrstor,
928 /// Save x87 FPU, MMX technology, and MXCSR state
929 fxsave,
930930 /// Insert byte
931931 /// Insert word
932932 /// Insert doubleword
src/arch/x86_64/bits.zig+4-2
......@@ -366,7 +366,6 @@ pub const Register = enum(u8) {
366366 @intFromEnum(Register.eax) ... @intFromEnum(Register.r15d) => @intFromEnum(Register.eax),
367367 @intFromEnum(Register.ax) ... @intFromEnum(Register.r15w) => @intFromEnum(Register.ax),
368368 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => @intFromEnum(Register.al),
369 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah) - 4,
370369 else => unreachable,
371370 // zig fmt: on
372371 };
......@@ -385,7 +384,10 @@ pub const Register = enum(u8) {
385384 }
386385
387386 pub fn to8(reg: Register) Register {
388 return @enumFromInt(@intFromEnum(reg) - reg.gpBase() + @intFromEnum(Register.al));
387 return switch (@intFromEnum(reg)) {
388 else => @enumFromInt(@intFromEnum(reg) - reg.gpBase() + @intFromEnum(Register.al)),
389 @intFromEnum(Register.ah)...@intFromEnum(Register.bh) => reg,
390 };
389391 }
390392
391393 fn sseBase(reg: Register) u7 {
src/arch/x86_64/encodings.zig+6
......@@ -437,6 +437,7 @@ pub const table = [_]Entry{
437437 .{ .jmp, .d, &.{ .rel32 }, &.{ 0xe9 }, 0, .none, .none },
438438 .{ .jmp, .m, &.{ .rm64 }, &.{ 0xff }, 4, .none, .none },
439439
440 .{ .lahf, .z, &.{}, &.{ 0x9f }, 0, .none, .@"32bit" },
440441 .{ .lahf, .z, &.{}, &.{ 0x9f }, 0, .none, .sahf },
441442
442443 .{ .lar, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x02 }, 0, .none, .none },
......@@ -744,6 +745,7 @@ pub const table = [_]Entry{
744745
745746 .{ .rsm, .z, &.{}, &.{ 0x0f, 0xaa }, 0, .none, .none },
746747
748 .{ .sahf, .z, &.{}, &.{ 0x9e }, 0, .none, .@"32bit" },
747749 .{ .sahf, .z, &.{}, &.{ 0x9e }, 0, .none, .sahf },
748750
749751 .{ .sal, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none, .none },
......@@ -2275,6 +2277,10 @@ pub const table = [_]Entry{
22752277 .{ .vtestpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x0f }, 0, .vex_128_w0, .avx },
22762278 .{ .vtestpd, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x0f }, 0, .vex_256_w0, .avx },
22772279
2280 .{ .vucomisd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x2e }, 0, .vex_lig_wig, .avx },
2281
2282 .{ .vucomiss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x0f, 0x2e }, 0, .vex_lig_wig, .avx },
2283
22782284 .{ .vxorpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_128_wig, .avx },
22792285 .{ .vxorpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_256_wig, .avx },
22802286
test/behavior/x86_64/math.zig+45-2
......@@ -17,8 +17,23 @@ const Sse = if (std.Target.x86.featureSetHas(builtin.cpu.features, .avx))
1717else
1818 @Vector(16, u8);
1919
20inline fn sign(rhs: anytype) bool {
21 return @call(.always_inline, math.signbit, .{rhs});
20inline fn sign(rhs: anytype) switch (@typeInfo(@TypeOf(rhs))) {
21 else => bool,
22 .vector => |vector| @Vector(vector.len, bool),
23} {
24 switch (@typeInfo(@TypeOf(rhs))) {
25 else => return @as(@Type(.{ .int = .{
26 .signedness = .signed,
27 .bits = @bitSizeOf(@TypeOf(rhs)),
28 } }), @bitCast(rhs)) < 0,
29 .vector => |vector| {
30 const V = @Vector(vector.len, @Type(.{ .int = .{
31 .signedness = .signed,
32 .bits = @bitSizeOf(vector.child),
33 } }));
34 return @as(V, @bitCast(rhs)) < @as(V, @splat(0));
35 },
36 }
2237}
2338inline fn boolAnd(lhs: anytype, rhs: @TypeOf(lhs)) @TypeOf(lhs) {
2439 switch (@typeInfo(@TypeOf(lhs))) {
......@@ -69,12 +84,40 @@ noinline fn checkExpected(expected: anytype, actual: @TypeOf(expected)) !void {
6984 }) return error.Unexpected;
7085}
7186test checkExpected {
87 if (checkExpected(nan(f16), nan(f16)) == error.Unexpected) return error.Unexpected;
88 if (checkExpected(nan(f16), -nan(f16)) != error.Unexpected) return error.Unexpected;
89 if (checkExpected(@as(f16, 0.0), @as(f16, 0.0)) == error.Unexpected) return error.Unexpected;
90 if (checkExpected(@as(f16, -0.0), @as(f16, -0.0)) == error.Unexpected) return error.Unexpected;
91 if (checkExpected(@as(f16, -0.0), @as(f16, 0.0)) != error.Unexpected) return error.Unexpected;
92 if (checkExpected(@as(f16, 0.0), @as(f16, -0.0)) != error.Unexpected) return error.Unexpected;
93
7294 if (checkExpected(nan(f32), nan(f32)) == error.Unexpected) return error.Unexpected;
7395 if (checkExpected(nan(f32), -nan(f32)) != error.Unexpected) return error.Unexpected;
7496 if (checkExpected(@as(f32, 0.0), @as(f32, 0.0)) == error.Unexpected) return error.Unexpected;
7597 if (checkExpected(@as(f32, -0.0), @as(f32, -0.0)) == error.Unexpected) return error.Unexpected;
7698 if (checkExpected(@as(f32, -0.0), @as(f32, 0.0)) != error.Unexpected) return error.Unexpected;
7799 if (checkExpected(@as(f32, 0.0), @as(f32, -0.0)) != error.Unexpected) return error.Unexpected;
100
101 if (checkExpected(nan(f64), nan(f64)) == error.Unexpected) return error.Unexpected;
102 if (checkExpected(nan(f64), -nan(f64)) != error.Unexpected) return error.Unexpected;
103 if (checkExpected(@as(f64, 0.0), @as(f64, 0.0)) == error.Unexpected) return error.Unexpected;
104 if (checkExpected(@as(f64, -0.0), @as(f64, -0.0)) == error.Unexpected) return error.Unexpected;
105 if (checkExpected(@as(f64, -0.0), @as(f64, 0.0)) != error.Unexpected) return error.Unexpected;
106 if (checkExpected(@as(f64, 0.0), @as(f64, -0.0)) != error.Unexpected) return error.Unexpected;
107
108 if (checkExpected(nan(f80), nan(f80)) == error.Unexpected) return error.Unexpected;
109 if (checkExpected(nan(f80), -nan(f80)) != error.Unexpected) return error.Unexpected;
110 if (checkExpected(@as(f80, 0.0), @as(f80, 0.0)) == error.Unexpected) return error.Unexpected;
111 if (checkExpected(@as(f80, -0.0), @as(f80, -0.0)) == error.Unexpected) return error.Unexpected;
112 if (checkExpected(@as(f80, -0.0), @as(f80, 0.0)) != error.Unexpected) return error.Unexpected;
113 if (checkExpected(@as(f80, 0.0), @as(f80, -0.0)) != error.Unexpected) return error.Unexpected;
114
115 if (checkExpected(nan(f128), nan(f128)) == error.Unexpected) return error.Unexpected;
116 if (checkExpected(nan(f128), -nan(f128)) != error.Unexpected) return error.Unexpected;
117 if (checkExpected(@as(f128, 0.0), @as(f128, 0.0)) == error.Unexpected) return error.Unexpected;
118 if (checkExpected(@as(f128, -0.0), @as(f128, -0.0)) == error.Unexpected) return error.Unexpected;
119 if (checkExpected(@as(f128, -0.0), @as(f128, 0.0)) != error.Unexpected) return error.Unexpected;
120 if (checkExpected(@as(f128, 0.0), @as(f128, -0.0)) != error.Unexpected) return error.Unexpected;
78121}
79122
80123fn Unary(comptime op: anytype) type {