authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-12-23 01:56:39-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:42:08-05:00
log73a42953c93273c178a1f8c8067bc732ca933be0
tree19f59148e6f9d65a74dddaa13a1b900b16e25123
parentb9c44007762b9b302c263a89b7c2e8a8470b97ec

x86_64: 2 means better


5 files changed, 2166 insertions(+), 602 deletions(-)

src/arch/x86_64/CodeGen.zig+2122-602
...@@ -135,7 +135,8 @@ const Owner = union(enum) {...@@ -135,7 +135,8 @@ const Owner = union(enum) {
135 }135 }
136};136};
137137
138const MaskKind = enum { sign, all };138const MaskKind = enum(u1) { sign, all };
139const MaskInfo = packed struct { kind: MaskKind, inverted: bool, scalar: Memory.Size };
139140
140pub const MCValue = union(enum) {141pub const MCValue = union(enum) {
141 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.142 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.
...@@ -167,7 +168,7 @@ pub const MCValue = union(enum) {...@@ -167,7 +168,7 @@ pub const MCValue = union(enum) {
167 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.168 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
168 register_overflow: struct { reg: Register, eflags: Condition },169 register_overflow: struct { reg: Register, eflags: Condition },
169 /// The value is a bool vector stored in a vector register with a different scalar type.170 /// The value is a bool vector stored in a vector register with a different scalar type.
170 register_mask: struct { reg: Register, kind: MaskKind, inverted: bool, scalar: Memory.Size },171 register_mask: struct { reg: Register, info: MaskInfo },
171 /// The value is in memory at a hard-coded address.172 /// The value is in memory at a hard-coded address.
172 /// If the type is a pointer, it means the pointer address is stored at this memory location.173 /// If the type is a pointer, it means the pointer address is stored at this memory location.
173 memory: u64,174 memory: u64,
...@@ -509,11 +510,23 @@ pub const MCValue = union(enum) {...@@ -509,11 +510,23 @@ pub const MCValue = union(enum) {
509 .memory => |pl| try writer.print("[ds:0x{x}]", .{pl}),510 .memory => |pl| try writer.print("[ds:0x{x}]", .{pl}),
510 inline .eflags, .register => |pl| try writer.print("{s}", .{@tagName(pl)}),511 inline .eflags, .register => |pl| try writer.print("{s}", .{@tagName(pl)}),
511 .register_pair => |pl| try writer.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),512 .register_pair => |pl| try writer.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
512 .register_triple => |pl| try writer.print("{s}:{s}:{s}", .{ @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]) }),513 .register_triple => |pl| try writer.print("{s}:{s}:{s}", .{
513 .register_quadruple => |pl| try writer.print("{s}:{s}:{s}:{s}", .{ @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]) }),514 @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
515 }),
516 .register_quadruple => |pl| try writer.print("{s}:{s}:{s}:{s}", .{
517 @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
518 }),
514 .register_offset => |pl| try writer.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),519 .register_offset => |pl| try writer.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),
515 .register_overflow => |pl| try writer.print("{s}:{s}", .{ @tagName(pl.eflags), @tagName(pl.reg) }),520 .register_overflow => |pl| try writer.print("{s}:{s}", .{
516 .register_mask => |pl| try writer.print("mask({s},{}):{s}", .{ @tagName(pl.kind), pl.scalar, @tagName(pl.reg) }),521 @tagName(pl.eflags),
522 @tagName(pl.reg),
523 }),
524 .register_mask => |pl| try writer.print("mask({s},{}):{c}{s}", .{
525 @tagName(pl.info.kind),
526 pl.info.scalar,
527 @as(u8, if (pl.info.inverted) '!' else ' '),
528 @tagName(pl.reg),
529 }),
517 .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }),530 .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }),
518 .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }),531 .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }),
519 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),532 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
...@@ -524,7 +537,9 @@ pub const MCValue = union(enum) {...@@ -524,7 +537,9 @@ pub const MCValue = union(enum) {
524 .load_tlv => |pl| try writer.print("[tlv:{d}]", .{pl}),537 .load_tlv => |pl| try writer.print("[tlv:{d}]", .{pl}),
525 .lea_tlv => |pl| try writer.print("tlv:{d}", .{pl}),538 .lea_tlv => |pl| try writer.print("tlv:{d}", .{pl}),
526 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),539 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
527 .elementwise_regs_then_frame => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{ pl.regs, pl.frame_index, pl.frame_off }),540 .elementwise_regs_then_frame => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{
541 pl.regs, pl.frame_index, pl.frame_off,
542 }),
528 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),543 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
529 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),544 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),
530 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),545 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),
...@@ -2390,13 +2405,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2390,13 +2405,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
23902405
2391 .div_float, .div_trunc, .div_floor, .div_exact => try cg.airMulDivBinOp(inst),2406 .div_float, .div_trunc, .div_floor, .div_exact => try cg.airMulDivBinOp(inst),
23922407
2393 .cmp_lt => try cg.airCmp(inst, .lt),
2394 .cmp_lte => try cg.airCmp(inst, .lte),
2395 .cmp_eq => try cg.airCmp(inst, .eq),
2396 .cmp_gte => try cg.airCmp(inst, .gte),
2397 .cmp_gt => try cg.airCmp(inst, .gt),
2398 .cmp_neq => try cg.airCmp(inst, .neq),
2399
2400 .cmp_lt_errors_len => try cg.airCmpLtErrorsLen(inst),2408 .cmp_lt_errors_len => try cg.airCmpLtErrorsLen(inst),
24012409
2402 .bitcast => try cg.airBitCast(inst),2410 .bitcast => try cg.airBitCast(inst),
...@@ -2474,12 +2482,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2474,12 +2482,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2474 .rem_optimized,2482 .rem_optimized,
2475 .mod_optimized,2483 .mod_optimized,
2476 .neg_optimized,2484 .neg_optimized,
2477 .cmp_lt_optimized,
2478 .cmp_lte_optimized,
2479 .cmp_eq_optimized,
2480 .cmp_gte_optimized,
2481 .cmp_gt_optimized,
2482 .cmp_neq_optimized,
2483 .reduce_optimized,2485 .reduce_optimized,
2484 .int_from_float_optimized,2486 .int_from_float_optimized,
2485 => return cg.fail("TODO implement optimized float mode", .{}),2487 => return cg.fail("TODO implement optimized float mode", .{}),
...@@ -2512,148 +2514,313 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2512,148 +2514,313 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2512 const bin_op = air_datas[@intFromEnum(inst)].bin_op;2514 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
2513 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });2515 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2514 var res: [1]Temp = undefined;2516 var res: [1]Temp = undefined;
2515 try cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, pattern_sets: switch (air_tag) {2517 cg.select2(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Mir.Inst.Tag, switch (air_tag) {
2516 else => unreachable,2518 else => unreachable,
2517 inline .bit_and, .bit_or, .xor => |ct_air_tag| {2519 .bit_and => .@"and",
2518 const mir_tag: Mir.Inst.Tag = switch (ct_air_tag) {2520 .bit_or => .@"or",
2519 else => unreachable,2521 .xor => .xor,
2520 .bit_and => .@"and",2522 })) {
2521 .bit_or => .@"or",2523 else => unreachable,
2522 .xor => .xor,2524 inline .@"and", .@"or", .xor => |mir_tag| comptime &.{ .{
2523 };2525 .required_features = .{ .avx2, null },
2524 break :pattern_sets &.{2526 .patterns = &.{
2525 .{2527 .{ .src = .{ .ymm, .mem } },
2526 .required_features = &.{.avx2},2528 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
2527 .mir_tag = .{ .vp_, mir_tag },2529 .{ .src = .{ .ymm, .ymm } },
2528 .patterns = &.{2530 },
2529 .{ .ops = &.{ .ymm, .ymm, .mem } },2531 .dst_temps = .{.{ .rc = .sse }},
2530 .{ .ops = &.{ .ymm, .mem, .ymm }, .commute = .{ 1, 2 } },2532 .each = .{ .once = &.{
2531 .{ .ops = &.{ .ymm, .ymm, .ymm } },2533 .{ .vp_, mir_tag, .ydst0, .ysrc0, .ysrc1, .none },
2532 },2534 } },
2533 },2535 }, .{
2534 .{2536 .required_features = .{ .avx, null },
2535 .required_features = &.{.avx},2537 .patterns = &.{
2536 .mir_tag = .{ .vp_, mir_tag },2538 .{ .src = .{ .ymm, .mem } },
2537 .patterns = &.{2539 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
2538 .{ .ops = &.{ .xmm, .xmm, .mem } },2540 .{ .src = .{ .ymm, .ymm } },
2539 .{ .ops = &.{ .xmm, .mem, .xmm }, .commute = .{ 1, 2 } },2541 },
2540 .{ .ops = &.{ .xmm, .xmm, .xmm } },2542 .dst_temps = .{.{ .rc = .sse }},
2541 },2543 .each = .{ .once = &.{
2542 },2544 .{ .v_pd, mir_tag, .ydst0, .ysrc0, .ysrc1, .none },
2543 .{2545 } },
2544 .required_features = &.{.sse2},2546 }, .{
2545 .mir_tag = .{ .p_, mir_tag },2547 .required_features = .{ .avx, null },
2546 .patterns = &.{2548 .patterns = &.{
2547 .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .mem } },2549 .{ .src = .{ .xmm, .mem } },
2548 .{ .ops = &.{ .xmm, .mem, .{ .implicit = 0 } } },2550 .{ .src = .{ .mem, .xmm }, .commute = .{ 0, 1 } },
2549 .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .xmm } },2551 .{ .src = .{ .xmm, .xmm } },
2550 .{ .ops = &.{ .xmm, .xmm, .{ .implicit = 0 } } },2552 },
2551 },2553 .dst_temps = .{.{ .rc = .sse }},
2552 },2554 .each = .{ .once = &.{
2553 .{2555 .{ .vp_, mir_tag, .xdst0, .xsrc0, .xsrc1, .none },
2554 .required_features = &.{.sse},2556 } },
2555 .mir_tag = .{ ._ps, mir_tag },2557 }, .{
2556 .patterns = &.{2558 .required_features = .{ .sse2, null },
2557 .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .mem } },2559 .patterns = &.{
2558 .{ .ops = &.{ .xmm, .mem, .{ .implicit = 0 } } },2560 .{ .src = .{ .mut_xmm, .mem } },
2559 .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .xmm } },2561 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
2560 .{ .ops = &.{ .xmm, .xmm, .{ .implicit = 0 } } },2562 .{ .src = .{ .mut_xmm, .xmm } },
2561 },2563 },
2562 },2564 .dst_temps = .{.{ .src = 0 }},
2563 .{2565 .each = .{ .once = &.{
2564 .required_features = &.{.mmx},2566 .{ .p_, mir_tag, .xdst0, .xsrc1, .none, .none },
2565 .mir_tag = .{ .p_, mir_tag },2567 } },
2566 .patterns = &.{2568 }, .{
2567 .{ .ops = &.{ .mm, .{ .implicit = 0 }, .mem } },2569 .required_features = .{ .sse, null },
2568 .{ .ops = &.{ .mm, .mem, .{ .implicit = 0 } } },2570 .patterns = &.{
2569 .{ .ops = &.{ .mm, .{ .implicit = 0 }, .mm } },2571 .{ .src = .{ .mut_xmm, .mem } },
2570 .{ .ops = &.{ .mm, .mm, .{ .implicit = 0 } } },2572 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
2571 },2573 .{ .src = .{ .mut_xmm, .xmm } },
2574 },
2575 .dst_temps = .{.{ .src = 0 }},
2576 .each = .{ .once = &.{
2577 .{ ._ps, mir_tag, .xdst0, .xsrc1, .none, .none },
2578 } },
2579 }, .{
2580 .required_features = .{ .mmx, null },
2581 .patterns = &.{
2582 .{ .src = .{ .mut_mm, .mem } },
2583 .{ .src = .{ .mem, .mut_mm }, .commute = .{ 0, 1 } },
2584 .{ .src = .{ .mut_mm, .mm } },
2585 },
2586 .dst_temps = .{.{ .src = 0 }},
2587 .each = .{ .once = &.{
2588 .{ .p_, mir_tag, .rdst0, .rsrc1, .none, .none },
2589 } },
2590 }, .{
2591 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
2592 .patterns = &.{
2593 .{ .src = .{ .mut_mem, .imm8 } },
2594 .{ .src = .{ .imm8, .mut_mem }, .commute = .{ 0, 1 } },
2595 .{ .src = .{ .mut_gpr, .imm8 } },
2596 .{ .src = .{ .imm8, .mut_gpr }, .commute = .{ 0, 1 } },
2597 .{ .src = .{ .mut_mem, .gpr } },
2598 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
2599 .{ .src = .{ .mut_gpr, .mem } },
2600 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
2601 .{ .src = .{ .mut_gpr, .gpr } },
2602 },
2603 .clobbers = .{ .eflags = true },
2604 .dst_temps = .{.{ .src = 0 }},
2605 .each = .{ .once = &.{
2606 .{ ._, mir_tag, .dst0b, .src1b, .none, .none },
2607 } },
2608 }, .{
2609 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
2610 .patterns = &.{
2611 .{ .src = .{ .mut_mem, .imm16 } },
2612 .{ .src = .{ .imm16, .mut_mem }, .commute = .{ 0, 1 } },
2613 .{ .src = .{ .mut_gpr, .imm16 } },
2614 .{ .src = .{ .imm16, .mut_gpr }, .commute = .{ 0, 1 } },
2615 .{ .src = .{ .mut_mem, .gpr } },
2616 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
2617 .{ .src = .{ .mut_gpr, .mem } },
2618 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
2619 .{ .src = .{ .mut_gpr, .gpr } },
2620 },
2621 .clobbers = .{ .eflags = true },
2622 .dst_temps = .{.{ .src = 0 }},
2623 .each = .{ .once = &.{
2624 .{ ._, mir_tag, .dst0w, .src1w, .none, .none },
2625 } },
2626 }, .{
2627 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
2628 .patterns = &.{
2629 .{ .src = .{ .mut_mem, .imm32 } },
2630 .{ .src = .{ .imm32, .mut_mem }, .commute = .{ 0, 1 } },
2631 .{ .src = .{ .mut_gpr, .imm32 } },
2632 .{ .src = .{ .imm32, .mut_gpr }, .commute = .{ 0, 1 } },
2633 .{ .src = .{ .mut_mem, .gpr } },
2634 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
2635 .{ .src = .{ .mut_gpr, .mem } },
2636 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
2637 .{ .src = .{ .mut_gpr, .gpr } },
2638 },
2639 .clobbers = .{ .eflags = true },
2640 .dst_temps = .{.{ .src = 0 }},
2641 .each = .{ .once = &.{
2642 .{ ._, mir_tag, .edst0, .esrc1, .none, .none },
2643 } },
2644 }, .{
2645 .required_features = .{ .@"64bit", null },
2646 .constraints = .{ .{ .int = .qword }, .{ .int = .qword } },
2647 .patterns = &.{
2648 .{ .src = .{ .mut_mem, .simm32 } },
2649 .{ .src = .{ .simm32, .mut_mem }, .commute = .{ 0, 1 } },
2650 .{ .src = .{ .mut_gpr, .simm32 } },
2651 .{ .src = .{ .simm32, .mut_gpr }, .commute = .{ 0, 1 } },
2652 .{ .src = .{ .mut_mem, .gpr } },
2653 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
2654 .{ .src = .{ .mut_gpr, .mem } },
2655 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
2656 .{ .src = .{ .mut_gpr, .gpr } },
2657 },
2658 .clobbers = .{ .eflags = true },
2659 .dst_temps = .{.{ .src = 0 }},
2660 .each = .{ .once = &.{
2661 .{ ._, mir_tag, .rdst0, .rsrc1, .none, .none },
2662 } },
2663 }, .{
2664 .required_features = .{ .avx2, null },
2665 .patterns = &.{
2666 .{ .src = .{ .to_mem, .to_mem } },
2667 },
2668 .extra_temps = .{
2669 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2670 .{ .kind = .{ .rc = .sse } },
2671 .unused,
2672 },
2673 .dst_temps = .{.mem},
2674 .each = .{ .limb = .{
2675 .of = .ysrc0,
2676 .body = &.{
2677 .{ .v_, .movdqu, .ytmp1, .{ .src_limb = 0 }, .none, .none },
2678 .{ .vp_, mir_tag, .ytmp1, .ytmp1, .{ .src_limb = 1 }, .none },
2679 .{ .v_, .movdqu, .{ .dst_limb = 0 }, .ytmp1, .none, .none },
2572 },2680 },
2573 .{2681 } },
2574 .clobbers = .{ .eflags = true },2682 }, .{
2575 .mir_tag = .{ ._, mir_tag },2683 .required_features = .{ .avx, null },
2576 .patterns = &.{2684 .patterns = &.{
2577 .{ .ops = &.{ .mem, .{ .implicit = 0 }, .simm32 } },2685 .{ .src = .{ .to_mem, .to_mem } },
2578 .{ .ops = &.{ .mem, .simm32, .{ .implicit = 0 } } },2686 },
2579 .{ .ops = &.{ .mem, .{ .implicit = 0 }, .gpr } },2687 .extra_temps = .{
2580 .{ .ops = &.{ .mem, .gpr, .{ .implicit = 0 } } },2688 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2581 .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .simm32 } },2689 .{ .kind = .{ .rc = .sse } },
2582 .{ .ops = &.{ .gpr, .simm32, .{ .implicit = 0 } } },2690 .unused,
2583 .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .mem } },2691 },
2584 .{ .ops = &.{ .gpr, .mem, .{ .implicit = 0 } } },2692 .dst_temps = .{.mem},
2585 .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .gpr } },2693 .each = .{ .limb = .{
2586 .{ .ops = &.{ .gpr, .gpr, .{ .implicit = 0 } } },2694 .of = .ysrc0,
2587 },2695 .body = &.{
2696 .{ .v_pd, .movu, .ytmp1, .{ .src_limb = 0 }, .none, .none },
2697 .{ .v_pd, mir_tag, .ytmp1, .ytmp1, .{ .src_limb = 1 }, .none },
2698 .{ .v_pd, .movu, .{ .dst_limb = 0 }, .ytmp1, .none, .none },
2588 },2699 },
25892700 } },
2590 .{2701 }, .{
2591 .required_features = &.{.avx2},2702 .required_features = .{ .avx, null },
2592 .loop = .bitwise,2703 .patterns = &.{
2593 .mir_tag = .{ .vp_, mir_tag },2704 .{ .src = .{ .to_mem, .to_mem } },
2594 .patterns = &.{2705 },
2595 .{ .ops = &.{ .ymm_limb, .{ .explicit = 0 }, .mem_limb } },2706 .extra_temps = .{
2596 .{ .ops = &.{ .ymm_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },2707 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2597 .{ .ops = &.{ .ymm_limb, .ymm_limb, .mem_limb } },2708 .{ .kind = .{ .rc = .sse } },
2598 .{ .ops = &.{ .ymm_limb, .ymm_limb, .ymm_limb } },2709 .unused,
2599 },2710 },
2711 .dst_temps = .{.mem},
2712 .each = .{ .limb = .{
2713 .of = .xsrc0,
2714 .body = &.{
2715 .{ .v_, .movdqu, .xtmp1, .{ .src_limb = 0 }, .none, .none },
2716 .{ .vp_, mir_tag, .xtmp1, .xtmp1, .{ .src_limb = 1 }, .none },
2717 .{ .v_, .movdqu, .{ .dst_limb = 0 }, .xtmp1, .none, .none },
2600 },2718 },
2601 .{2719 } },
2602 .required_features = &.{.avx},2720 }, .{
2603 .loop = .bitwise,2721 .required_features = .{ .sse2, null },
2604 .mir_tag = .{ .vp_, mir_tag },2722 .patterns = &.{
2605 .patterns = &.{2723 .{ .src = .{ .to_mem, .to_mem } },
2606 .{ .ops = &.{ .xmm_limb, .{ .explicit = 0 }, .mem_limb } },2724 },
2607 .{ .ops = &.{ .xmm_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },2725 .extra_temps = .{
2608 .{ .ops = &.{ .xmm_limb, .xmm_limb, .mem_limb } },2726 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2609 .{ .ops = &.{ .xmm_limb, .xmm_limb, .xmm_limb } },2727 .{ .kind = .{ .rc = .sse } },
2610 },2728 .unused,
2729 },
2730 .dst_temps = .{.mem},
2731 .each = .{ .limb = .{
2732 .of = .xsrc0,
2733 .body = &.{
2734 .{ ._, .movdqu, .xtmp1, .{ .src_limb = 0 }, .none, .none },
2735 .{ .p_, mir_tag, .xtmp1, .{ .src_limb = 1 }, .none, .none },
2736 .{ ._, .movdqu, .{ .dst_limb = 0 }, .xtmp1, .none, .none },
2611 },2737 },
2612 .{2738 } },
2613 .required_features = &.{.sse2},2739 }, .{
2614 .loop = .bitwise,2740 .required_features = .{ .sse, null },
2615 .mir_tag = .{ .p_, mir_tag },2741 .patterns = &.{
2616 .patterns = &.{2742 .{ .src = .{ .to_mem, .to_mem } },
2617 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .mem_limb } },2743 },
2618 .{ .ops = &.{ .xmm_limb, .mem_limb, .{ .implicit = 0 } } },2744 .extra_temps = .{
2619 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .xmm_limb } },2745 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2620 },2746 .{ .kind = .{ .rc = .sse } },
2747 .unused,
2748 },
2749 .dst_temps = .{.mem},
2750 .each = .{ .limb = .{
2751 .of = .xsrc0,
2752 .body = &.{
2753 .{ ._ps, .movu, .xtmp1, .{ .src_limb = 0 }, .none, .none },
2754 .{ ._ps, mir_tag, .xtmp1, .{ .src_limb = 1 }, .none, .none },
2755 .{ ._ps, .movu, .{ .dst_limb = 0 }, .xtmp1, .none, .none },
2621 },2756 },
2622 .{2757 } },
2623 .required_features = &.{.sse},2758 }, .{
2624 .loop = .bitwise,2759 .required_features = .{ .mmx, null },
2625 .mir_tag = .{ ._ps, mir_tag },2760 .patterns = &.{
2626 .patterns = &.{2761 .{ .src = .{ .to_mem, .to_mem } },
2627 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .mem_limb } },2762 },
2628 .{ .ops = &.{ .xmm_limb, .mem_limb, .{ .implicit = 0 } } },2763 .extra_temps = .{
2629 .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .xmm_limb } },2764 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2630 },2765 .{ .kind = .{ .rc = .mmx } },
2766 .unused,
2767 },
2768 .dst_temps = .{.mem},
2769 .each = .{ .limb = .{
2770 .of = .rsrc0,
2771 .body = &.{
2772 .{ ._q, .mov, .rtmp1, .{ .src_limb = 0 }, .none, .none },
2773 .{ .p_, mir_tag, .rtmp1, .{ .src_limb = 1 }, .none, .none },
2774 .{ ._q, .mov, .{ .dst_limb = 0 }, .rtmp1, .none, .none },
2631 },2775 },
2632 .{2776 } },
2633 .required_features = &.{.mmx},2777 }, .{
2634 .loop = .bitwise,2778 .required_features = .{ .@"64bit", null },
2635 .mir_tag = .{ .p_, mir_tag },2779 .patterns = &.{
2636 .patterns = &.{2780 .{ .src = .{ .to_mem, .to_mem } },
2637 .{ .ops = &.{ .mm_limb, .{ .implicit = 0 }, .mem_limb } },2781 },
2638 .{ .ops = &.{ .mm_limb, .mem_limb, .{ .implicit = 0 } } },2782 .extra_temps = .{
2639 .{ .ops = &.{ .mm_limb, .{ .implicit = 0 }, .mm_limb } },2783 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2640 },2784 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
2785 .unused,
2786 },
2787 .dst_temps = .{.mem},
2788 .each = .{ .limb = .{
2789 .of = .rsrc0,
2790 .body = &.{
2791 .{ ._, .mov, .rtmp1, .{ .src_limb = 0 }, .none, .none },
2792 .{ ._, mir_tag, .rtmp1, .{ .src_limb = 1 }, .none, .none },
2793 .{ ._, .mov, .{ .dst_limb = 0 }, .rtmp1, .none, .none },
2641 },2794 },
2642 .{2795 } },
2643 .clobbers = .{ .eflags = true },2796 }, .{
2644 .loop = .bitwise,2797 .patterns = &.{
2645 .mir_tag = .{ ._, mir_tag },2798 .{ .src = .{ .to_mem, .to_mem } },
2646 .patterns = &.{2799 },
2647 .{ .ops = &.{ .mem_limb, .{ .implicit = 0 }, .gpr_limb } },2800 .extra_temps = .{
2648 .{ .ops = &.{ .mem_limb, .gpr_limb, .{ .implicit = 0 } } },2801 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2649 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .mem_limb } },2802 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
2650 .{ .ops = &.{ .gpr_limb, .mem_limb, .{ .implicit = 0 } } },2803 .unused,
2651 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .gpr_limb } },2804 },
2652 },2805 .dst_temps = .{.mem},
2806 .each = .{ .limb = .{
2807 .of = .esrc0,
2808 .body = &.{
2809 .{ ._, .mov, .etmp1, .{ .src_limb = 0 }, .none, .none },
2810 .{ ._, mir_tag, .etmp1, .{ .src_limb = 1 }, .none, .none },
2811 .{ ._, .mov, .{ .dst_limb = 0 }, .etmp1, .none, .none },
2653 },2812 },
2654 };2813 } },
2655 },2814 } },
2656 }, .{});2815 }) catch |err2| switch (err2) {
2816 error.Select2Failed => return cg.fail("failed to select2 {s} {} {} {}", .{
2817 @tagName(air_tag),
2818 cg.typeOf(bin_op.lhs).fmt(pt),
2819 ops[0].tracking(cg),
2820 ops[1].tracking(cg),
2821 }),
2822 else => |e| return e,
2823 };
2657 if (ops[0].index != res[0].index) try ops[0].die(cg);2824 if (ops[0].index != res[0].index) try ops[0].die(cg);
2658 if (ops[1].index != res[0].index) try ops[1].die(cg);2825 if (ops[1].index != res[0].index) try ops[1].die(cg);
2659 try res[0].moveTo(inst, cg);2826 try res[0].moveTo(inst, cg);
...@@ -2720,425 +2887,1300 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2720,425 +2887,1300 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2720 switch (extra.compareOperator()) {2887 switch (extra.compareOperator()) {
2721 .lt => unreachable,2888 .lt => unreachable,
2722 .lte => unreachable,2889 .lte => unreachable,
2723 .eq, .neq => |cmp_op| try cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, &.{2890 .eq, .neq => |cmp_op| cg.select2(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Condition, switch (cmp_op) {
2724 .{2891 else => unreachable,
2725 .required_features = &.{.avx2},2892 .eq => .e,
2726 .scalar = .{ .any_int = .byte },2893 .neq => .ne,
2727 .mir_tag = .{ .vp_b, .cmpeq },2894 })) {
2895 else => unreachable,
2896 inline .e, .ne => |cc| comptime &.{ .{
2897 .required_features = .{ .avx2, null },
2898 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
2728 .patterns = &.{2899 .patterns = &.{
2729 .{ .ops = &.{ .ymm_mask, .ymm, .mem } },2900 .{ .src = .{ .ymm, .mem } },
2730 .{ .ops = &.{ .ymm_mask, .mem, .ymm }, .commute = .{ 1, 2 } },2901 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
2731 .{ .ops = &.{ .ymm_mask, .ymm, .ymm } },2902 .{ .src = .{ .ymm, .ymm } },
2732 },2903 },
2733 },2904 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
2734 .{2905 .kind = .all,
2735 .required_features = &.{.avx2},2906 .inverted = switch (cc) {
2736 .scalar = .{ .any_int = .word },2907 else => unreachable,
2737 .mir_tag = .{ .vp_w, .cmpeq },2908 .e => false,
2909 .ne => true,
2910 },
2911 .scalar = .byte,
2912 } } }},
2913 .each = .{ .once = &.{
2914 .{ .vp_b, .cmpeq, .ydst0, .ysrc0, .ysrc1, .none },
2915 } },
2916 }, .{
2917 .required_features = .{ .avx2, null },
2918 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
2738 .patterns = &.{2919 .patterns = &.{
2739 .{ .ops = &.{ .ymm_mask, .ymm, .mem } },2920 .{ .src = .{ .ymm, .mem } },
2740 .{ .ops = &.{ .ymm_mask, .mem, .ymm }, .commute = .{ 1, 2 } },2921 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
2741 .{ .ops = &.{ .ymm_mask, .ymm, .ymm } },2922 .{ .src = .{ .ymm, .ymm } },
2742 },2923 },
2743 },2924 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
2744 .{2925 .kind = .all,
2745 .required_features = &.{.avx2},2926 .inverted = switch (cc) {
2746 .scalar = .{ .any_int = .dword },2927 else => unreachable,
2747 .mir_tag = .{ .vp_d, .cmpeq },2928 .e => false,
2929 .ne => true,
2930 },
2931 .scalar = .word,
2932 } } }},
2933 .each = .{ .once = &.{
2934 .{ .vp_w, .cmpeq, .ydst0, .ysrc0, .ysrc1, .none },
2935 } },
2936 }, .{
2937 .required_features = .{ .avx2, null },
2938 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
2748 .patterns = &.{2939 .patterns = &.{
2749 .{ .ops = &.{ .ymm_mask, .ymm, .mem } },2940 .{ .src = .{ .ymm, .mem } },
2750 .{ .ops = &.{ .ymm_mask, .mem, .ymm }, .commute = .{ 1, 2 } },2941 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
2751 .{ .ops = &.{ .ymm_mask, .ymm, .ymm } },2942 .{ .src = .{ .ymm, .ymm } },
2752 },2943 },
2753 },2944 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
2754 .{2945 .kind = .all,
2755 .required_features = &.{.avx2},2946 .inverted = switch (cc) {
2756 .scalar = .{ .any_int = .qword },2947 else => unreachable,
2757 .mir_tag = .{ .vp_q, .cmpeq },2948 .e => false,
2949 .ne => true,
2950 },
2951 .scalar = .dword,
2952 } } }},
2953 .each = .{ .once = &.{
2954 .{ .vp_d, .cmpeq, .ydst0, .ysrc0, .ysrc1, .none },
2955 } },
2956 }, .{
2957 .required_features = .{ .avx2, null },
2958 .constraints = .{ .{ .int = .qword }, .{ .int = .qword } },
2758 .patterns = &.{2959 .patterns = &.{
2759 .{ .ops = &.{ .ymm_mask, .ymm, .mem } },2960 .{ .src = .{ .ymm, .mem } },
2760 .{ .ops = &.{ .ymm_mask, .mem, .ymm }, .commute = .{ 1, 2 } },2961 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
2761 .{ .ops = &.{ .ymm_mask, .ymm, .ymm } },2962 .{ .src = .{ .ymm, .ymm } },
2762 },2963 },
2763 },2964 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
2764 .{2965 .kind = .all,
2765 .required_features = &.{.avx},2966 .inverted = switch (cc) {
2766 .scalar = .{ .any_int = .byte },2967 else => unreachable,
2767 .mir_tag = .{ .vp_b, .cmpeq },2968 .e => false,
2969 .ne => true,
2970 },
2971 .scalar = .qword,
2972 } } }},
2973 .each = .{ .once = &.{
2974 .{ .vp_q, .cmpeq, .ydst0, .ysrc0, .ysrc1, .none },
2975 } },
2976 }, .{
2977 .required_features = .{ .avx, null },
2978 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
2768 .patterns = &.{2979 .patterns = &.{
2769 .{ .ops = &.{ .xmm_mask, .xmm, .mem } },2980 .{ .src = .{ .xmm, .mem } },
2770 .{ .ops = &.{ .xmm_mask, .mem, .xmm }, .commute = .{ 1, 2 } },2981 .{ .src = .{ .mem, .xmm }, .commute = .{ 0, 1 } },
2771 .{ .ops = &.{ .xmm_mask, .xmm, .xmm } },2982 .{ .src = .{ .xmm, .xmm } },
2772 },2983 },
2773 },2984 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
2774 .{2985 .kind = .all,
2775 .required_features = &.{.avx},2986 .inverted = switch (cc) {
2776 .scalar = .{ .any_int = .word },2987 else => unreachable,
2777 .mir_tag = .{ .vp_w, .cmpeq },2988 .e => false,
2989 .ne => true,
2990 },
2991 .scalar = .byte,
2992 } } }},
2993 .each = .{ .once = &.{
2994 .{ .vp_b, .cmpeq, .xdst0, .xsrc0, .xsrc1, .none },
2995 } },
2996 }, .{
2997 .required_features = .{ .avx, null },
2998 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
2778 .patterns = &.{2999 .patterns = &.{
2779 .{ .ops = &.{ .xmm_mask, .xmm, .mem } },3000 .{ .src = .{ .xmm, .mem } },
2780 .{ .ops = &.{ .xmm_mask, .mem, .xmm }, .commute = .{ 1, 2 } },3001 .{ .src = .{ .mem, .xmm }, .commute = .{ 0, 1 } },
2781 .{ .ops = &.{ .xmm_mask, .xmm, .xmm } },3002 .{ .src = .{ .xmm, .xmm } },
2782 },3003 },
2783 },3004 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
2784 .{3005 .kind = .all,
2785 .required_features = &.{.avx},3006 .inverted = switch (cc) {
2786 .scalar = .{ .any_int = .dword },3007 else => unreachable,
2787 .mir_tag = .{ .vp_d, .cmpeq },3008 .e => false,
3009 .ne => true,
3010 },
3011 .scalar = .word,
3012 } } }},
3013 .each = .{ .once = &.{
3014 .{ .vp_w, .cmpeq, .xdst0, .xsrc0, .xsrc1, .none },
3015 } },
3016 }, .{
3017 .required_features = .{ .avx, null },
3018 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
2788 .patterns = &.{3019 .patterns = &.{
2789 .{ .ops = &.{ .xmm_mask, .xmm, .mem } },3020 .{ .src = .{ .xmm, .mem } },
2790 .{ .ops = &.{ .xmm_mask, .mem, .xmm }, .commute = .{ 1, 2 } },3021 .{ .src = .{ .mem, .xmm }, .commute = .{ 0, 1 } },
2791 .{ .ops = &.{ .xmm_mask, .xmm, .xmm } },3022 .{ .src = .{ .xmm, .xmm } },
3023 },
3024 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
3025 .kind = .all,
3026 .inverted = switch (cc) {
3027 else => unreachable,
3028 .e => false,
3029 .ne => true,
3030 },
3031 .scalar = .dword,
3032 } } }},
3033 .each = .{ .once = &.{
3034 .{ .vp_d, .cmpeq, .xdst0, .xsrc0, .xsrc1, .none },
3035 } },
3036 }, .{
3037 .required_features = .{ .avx, null },
3038 .constraints = .{ .{ .int = .qword }, .{ .int = .qword } },
3039 .patterns = &.{
3040 .{ .src = .{ .xmm, .mem } },
3041 .{ .src = .{ .mem, .xmm }, .commute = .{ 0, 1 } },
3042 .{ .src = .{ .xmm, .xmm } },
3043 },
3044 .dst_temps = .{.{ .rc_mask = .{ .rc = .sse, .info = .{
3045 .kind = .all,
3046 .inverted = switch (cc) {
3047 else => unreachable,
3048 .e => false,
3049 .ne => true,
3050 },
3051 .scalar = .qword,
3052 } } }},
3053 .each = .{ .once = &.{
3054 .{ .vp_q, .cmpeq, .xdst0, .xsrc0, .xsrc1, .none },
3055 } },
3056 }, .{
3057 .required_features = .{ .sse2, null },
3058 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
3059 .patterns = &.{
3060 .{ .src = .{ .mut_xmm, .mem } },
3061 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
3062 .{ .src = .{ .mut_xmm, .xmm } },
3063 },
3064 .dst_temps = .{.{ .src_mask = .{ .src = 0, .info = .{
3065 .kind = .all,
3066 .inverted = switch (cc) {
3067 else => unreachable,
3068 .e => false,
3069 .ne => true,
3070 },
3071 .scalar = .byte,
3072 } } }},
3073 .each = .{ .once = &.{
3074 .{ .p_b, .cmpeq, .xdst0, .xsrc1, .none, .none },
3075 } },
3076 }, .{
3077 .required_features = .{ .sse2, null },
3078 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
3079 .patterns = &.{
3080 .{ .src = .{ .mut_xmm, .mem } },
3081 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
3082 .{ .src = .{ .mut_xmm, .xmm } },
3083 },
3084 .dst_temps = .{.{ .src_mask = .{ .src = 0, .info = .{
3085 .kind = .all,
3086 .inverted = switch (cc) {
3087 else => unreachable,
3088 .e => false,
3089 .ne => true,
3090 },
3091 .scalar = .word,
3092 } } }},
3093 .each = .{ .once = &.{
3094 .{ .p_w, .cmpeq, .xdst0, .xsrc1, .none, .none },
3095 } },
3096 }, .{
3097 .required_features = .{ .sse2, null },
3098 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
3099 .patterns = &.{
3100 .{ .src = .{ .mut_xmm, .mem } },
3101 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
3102 .{ .src = .{ .mut_xmm, .xmm } },
3103 },
3104 .dst_temps = .{.{ .src_mask = .{ .src = 0, .info = .{
3105 .kind = .all,
3106 .inverted = switch (cc) {
3107 else => unreachable,
3108 .e => false,
3109 .ne => true,
3110 },
3111 .scalar = .dword,
3112 } } }},
3113 .each = .{ .once = &.{
3114 .{ .p_d, .cmpeq, .xdst0, .xsrc1, .none, .none },
3115 } },
3116 }, .{
3117 .required_features = .{ .sse4_1, null },
3118 .constraints = .{ .{ .int = .qword }, .{ .int = .qword } },
3119 .patterns = &.{
3120 .{ .src = .{ .mut_xmm, .mem } },
3121 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
3122 .{ .src = .{ .mut_xmm, .xmm } },
3123 },
3124 .dst_temps = .{.{ .src_mask = .{ .src = 0, .info = .{
3125 .kind = .all,
3126 .inverted = switch (cc) {
3127 else => unreachable,
3128 .e => false,
3129 .ne => true,
3130 },
3131 .scalar = .qword,
3132 } } }},
3133 .each = .{ .once = &.{
3134 .{ .p_q, .cmpeq, .xdst0, .xsrc1, .none, .none },
3135 } },
3136 }, .{
3137 .required_features = .{ .mmx, null },
3138 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
3139 .patterns = &.{
3140 .{ .src = .{ .mut_mm, .mem } },
3141 .{ .src = .{ .mem, .mut_mm }, .commute = .{ 0, 1 } },
3142 .{ .src = .{ .mut_mm, .mm } },
3143 },
3144 .dst_temps = .{.{ .src_mask = .{ .src = 0, .info = .{
3145 .kind = .all,
3146 .inverted = switch (cc) {
3147 else => unreachable,
3148 .e => false,
3149 .ne => true,
3150 },
3151 .scalar = .byte,
3152 } } }},
3153 .each = .{ .once = &.{
3154 .{ .p_b, .cmpeq, .rdst0, .rsrc1, .none, .none },
3155 } },
3156 }, .{
3157 .required_features = .{ .mmx, null },
3158 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
3159 .patterns = &.{
3160 .{ .src = .{ .mut_mm, .mem } },
3161 .{ .src = .{ .mem, .mut_mm }, .commute = .{ 0, 1 } },
3162 .{ .src = .{ .mut_mm, .mm } },
3163 },
3164 .dst_temps = .{.{ .src_mask = .{ .src = 0, .info = .{
3165 .kind = .all,
3166 .inverted = switch (cc) {
3167 else => unreachable,
3168 .e => false,
3169 .ne => true,
3170 },
3171 .scalar = .word,
3172 } } }},
3173 .each = .{ .once = &.{
3174 .{ .p_w, .cmpeq, .rdst0, .rsrc1, .none, .none },
3175 } },
3176 }, .{
3177 .required_features = .{ .mmx, null },
3178 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
3179 .patterns = &.{
3180 .{ .src = .{ .mut_mm, .mem } },
3181 .{ .src = .{ .mem, .mut_mm }, .commute = .{ 0, 1 } },
3182 .{ .src = .{ .mut_mm, .mm } },
3183 },
3184 .dst_temps = .{.{ .src_mask = .{ .src = 0, .info = .{
3185 .kind = .all,
3186 .inverted = switch (cc) {
3187 else => unreachable,
3188 .e => false,
3189 .ne => true,
3190 },
3191 .scalar = .dword,
3192 } } }},
3193 .each = .{ .once = &.{
3194 .{ .p_d, .cmpeq, .rdst0, .rsrc1, .none, .none },
3195 } },
3196 }, .{
3197 .constraints = .{ .{ .bool_vec = .byte }, .{ .bool_vec = .byte } },
3198 .patterns = &.{
3199 .{ .src = .{ .mut_mem, .imm8 } },
3200 .{ .src = .{ .imm8, .mut_mem }, .commute = .{ 0, 1 } },
3201 .{ .src = .{ .mut_gpr, .imm8 } },
3202 .{ .src = .{ .imm8, .mut_gpr }, .commute = .{ 0, 1 } },
3203 .{ .src = .{ .mut_mem, .gpr } },
3204 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
3205 .{ .src = .{ .mut_gpr, .mem } },
3206 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
3207 .{ .src = .{ .mut_gpr, .gpr } },
3208 },
3209 .clobbers = .{ .eflags = true },
3210 .dst_temps = .{.{ .src = 0 }},
3211 .each = .{ .once = switch (cc) {
3212 else => unreachable,
3213 .e => &.{
3214 .{ ._, .xor, .dst0b, .src1b, .none, .none },
3215 .{ ._, .not, .dst0b, .none, .none, .none },
3216 },
3217 .ne => &.{
3218 .{ ._, .xor, .dst0b, .src1b, .none, .none },
3219 },
3220 } },
3221 }, .{
3222 .constraints = .{ .{ .bool_vec = .word }, .{ .bool_vec = .word } },
3223 .patterns = &.{
3224 .{ .src = .{ .mut_mem, .imm16 } },
3225 .{ .src = .{ .imm16, .mut_mem }, .commute = .{ 0, 1 } },
3226 .{ .src = .{ .mut_gpr, .imm16 } },
3227 .{ .src = .{ .imm16, .mut_gpr }, .commute = .{ 0, 1 } },
3228 .{ .src = .{ .mut_mem, .gpr } },
3229 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
3230 .{ .src = .{ .mut_gpr, .mem } },
3231 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
3232 .{ .src = .{ .mut_gpr, .gpr } },
3233 },
3234 .clobbers = .{ .eflags = true },
3235 .dst_temps = .{.{ .src = 0 }},
3236 .each = .{ .once = switch (cc) {
3237 else => unreachable,
3238 .e => &.{
3239 .{ ._, .xor, .dst0w, .src1w, .none, .none },
3240 .{ ._, .not, .dst0w, .none, .none, .none },
3241 },
3242 .ne => &.{
3243 .{ ._, .xor, .dst0w, .src1w, .none, .none },
3244 },
3245 } },
3246 }, .{
3247 .constraints = .{ .{ .bool_vec = .dword }, .{ .bool_vec = .dword } },
3248 .patterns = &.{
3249 .{ .src = .{ .mut_mem, .imm32 } },
3250 .{ .src = .{ .imm32, .mut_mem }, .commute = .{ 0, 1 } },
3251 .{ .src = .{ .mut_gpr, .imm32 } },
3252 .{ .src = .{ .imm32, .mut_gpr }, .commute = .{ 0, 1 } },
3253 .{ .src = .{ .mut_mem, .gpr } },
3254 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
3255 .{ .src = .{ .mut_gpr, .mem } },
3256 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
3257 .{ .src = .{ .mut_gpr, .gpr } },
3258 },
3259 .clobbers = .{ .eflags = true },
3260 .dst_temps = .{.{ .src = 0 }},
3261 .each = .{ .once = switch (cc) {
3262 else => unreachable,
3263 .e => &.{
3264 .{ ._, .xor, .edst0, .esrc1, .none, .none },
3265 .{ ._, .not, .edst0, .none, .none, .none },
3266 },
3267 .ne => &.{
3268 .{ ._, .xor, .edst0, .esrc1, .none, .none },
3269 },
3270 } },
3271 }, .{
3272 .required_features = .{ .@"64bit", null },
3273 .constraints = .{ .{ .bool_vec = .qword }, .{ .bool_vec = .qword } },
3274 .patterns = &.{
3275 .{ .src = .{ .mut_mem, .simm32 } },
3276 .{ .src = .{ .simm32, .mut_mem }, .commute = .{ 0, 1 } },
3277 .{ .src = .{ .mut_gpr, .simm32 } },
3278 .{ .src = .{ .simm32, .mut_gpr }, .commute = .{ 0, 1 } },
3279 .{ .src = .{ .mut_mem, .gpr } },
3280 .{ .src = .{ .gpr, .mut_mem }, .commute = .{ 0, 1 } },
3281 .{ .src = .{ .mut_gpr, .mem } },
3282 .{ .src = .{ .mem, .mut_gpr }, .commute = .{ 0, 1 } },
3283 .{ .src = .{ .mut_gpr, .gpr } },
3284 },
3285 .clobbers = .{ .eflags = true },
3286 .dst_temps = .{.{ .src = 0 }},
3287 .each = .{ .once = switch (cc) {
3288 else => unreachable,
3289 .e => &.{
3290 .{ ._, .xor, .rdst0, .rsrc1, .none, .none },
3291 .{ ._, .not, .rdst0, .none, .none, .none },
3292 },
3293 .ne => &.{
3294 .{ ._, .xor, .rdst0, .rsrc1, .none, .none },
3295 },
3296 } },
3297 } },
3298 }) catch |err2| switch (err2) {
3299 error.Select2Failed => cg.select(&res, &.{cg.typeOfIndex(inst)}, &ops, &.{
3300 .{
3301 .required_features = &.{.avx2},
3302 .scalar = .{ .any_int = .byte },
3303 .loop = .elementwise,
3304 .mir_tag = .{ .vp_b, .cmpeq },
3305 .patterns = &.{
3306 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3307 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3308 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
3309 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
3310 },
3311 },
3312 .{
3313 .required_features = &.{.avx2},
3314 .scalar = .{ .any_int = .word },
3315 .loop = .elementwise,
3316 .mir_tag = .{ .vp_w, .cmpeq },
3317 .patterns = &.{
3318 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3319 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3320 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
3321 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
3322 },
3323 },
3324 .{
3325 .required_features = &.{.avx2},
3326 .scalar = .{ .any_int = .dword },
3327 .loop = .elementwise,
3328 .mir_tag = .{ .vp_d, .cmpeq },
3329 .patterns = &.{
3330 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3331 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3332 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
3333 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
3334 },
3335 },
3336 .{
3337 .required_features = &.{.avx2},
3338 .scalar = .{ .any_int = .qword },
3339 .loop = .elementwise,
3340 .mir_tag = .{ .vp_q, .cmpeq },
3341 .patterns = &.{
3342 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3343 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3344 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
3345 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
3346 },
3347 },
3348 .{
3349 .required_features = &.{.avx},
3350 .scalar = .{ .any_int = .byte },
3351 .loop = .elementwise,
3352 .mir_tag = .{ .vp_b, .cmpeq },
3353 .patterns = &.{
3354 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3355 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3356 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
3357 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
3358 },
3359 },
3360 .{
3361 .required_features = &.{.avx},
3362 .scalar = .{ .any_int = .word },
3363 .loop = .elementwise,
3364 .mir_tag = .{ .vp_w, .cmpeq },
3365 .patterns = &.{
3366 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3367 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3368 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
3369 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
3370 },
3371 },
3372 .{
3373 .required_features = &.{.avx},
3374 .scalar = .{ .any_int = .dword },
3375 .loop = .elementwise,
3376 .mir_tag = .{ .vp_d, .cmpeq },
3377 .patterns = &.{
3378 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3379 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3380 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
3381 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
3382 },
3383 },
3384 .{
3385 .required_features = &.{.avx},
3386 .scalar = .{ .any_int = .qword },
3387 .loop = .elementwise,
3388 .mir_tag = .{ .vp_q, .cmpeq },
3389 .patterns = &.{
3390 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
3391 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
3392 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
3393 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
3394 },
3395 },
3396 .{
3397 .required_features = &.{.sse2},
3398 .scalar = .{ .any_int = .byte },
3399 .loop = .elementwise,
3400 .mir_tag = .{ .p_b, .cmpeq },
3401 .patterns = &.{
3402 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3403 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3404 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3405 },
3406 },
3407 .{
3408 .required_features = &.{.sse2},
3409 .scalar = .{ .any_int = .word },
3410 .loop = .elementwise,
3411 .mir_tag = .{ .p_w, .cmpeq },
3412 .patterns = &.{
3413 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3414 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3415 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3416 },
3417 },
3418 .{
3419 .required_features = &.{.sse2},
3420 .scalar = .{ .any_int = .dword },
3421 .loop = .elementwise,
3422 .mir_tag = .{ .p_d, .cmpeq },
3423 .patterns = &.{
3424 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3425 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3426 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3427 },
3428 },
3429 .{
3430 .required_features = &.{.sse4_1},
3431 .scalar = .{ .any_int = .qword },
3432 .loop = .elementwise,
3433 .mir_tag = .{ .p_q, .cmpeq },
3434 .patterns = &.{
3435 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3436 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3437 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3438 },
3439 },
3440 .{
3441 .required_features = &.{.mmx},
3442 .scalar = .{ .any_int = .byte },
3443 .loop = .elementwise,
3444 .mir_tag = .{ .p_b, .cmpeq },
3445 .patterns = &.{
3446 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3447 .{ .ops = &.{ .mm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3448 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mm_limb } },
3449 },
3450 },
3451 .{
3452 .required_features = &.{.mmx},
3453 .scalar = .{ .any_int = .word },
3454 .loop = .elementwise,
3455 .mir_tag = .{ .p_w, .cmpeq },
3456 .patterns = &.{
3457 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3458 .{ .ops = &.{ .mm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3459 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mm_limb } },
3460 },
3461 },
3462 .{
3463 .required_features = &.{.mmx},
3464 .scalar = .{ .any_int = .dword },
3465 .loop = .elementwise,
3466 .mir_tag = .{ .p_d, .cmpeq },
3467 .patterns = &.{
3468 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3469 .{ .ops = &.{ .mm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3470 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mm_limb } },
3471 },
3472 },
3473 .{
3474 .scalar = .bool,
3475 .clobbers = .{ .eflags = true },
3476 .invert_result = true,
3477 .loop = .elementwise,
3478 .mir_tag = .{ ._, .xor },
3479 .patterns = &.{
3480 .{ .ops = &.{ .mem_limb, .{ .implicit = 0 }, .gpr_limb } },
3481 .{ .ops = &.{ .mem_limb, .gpr_limb, .{ .implicit = 0 } } },
3482 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .mem_limb } },
3483 .{ .ops = &.{ .gpr_limb, .mem_limb, .{ .implicit = 0 } } },
3484 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .gpr_limb } },
3485 },
3486 },
3487 .{
3488 .scalar = .{ .any_int = .byte },
3489 .clobbers = .{ .eflags = true },
3490 .loop = .elementwise,
3491 .mir_tag = .{ ._, .cmp },
3492 .patterns = &.{
3493 .{ .ops = &.{ .cc_elem, .mem_elem, .gpr_elem } },
3494 .{ .ops = &.{ .cc_elem, .gpr_elem, .mem_elem } },
3495 .{ .ops = &.{ .cc_elem, .gpr_elem, .gpr_elem } },
3496 },
3497 },
3498 .{
3499 .scalar = .{ .any_int = .word },
3500 .clobbers = .{ .eflags = true },
3501 .loop = .elementwise,
3502 .mir_tag = .{ ._, .cmp },
3503 .patterns = &.{
3504 .{ .ops = &.{ .cc_elem, .mem_elem, .gpr_elem } },
3505 .{ .ops = &.{ .cc_elem, .gpr_elem, .mem_elem } },
3506 .{ .ops = &.{ .cc_elem, .gpr_elem, .gpr_elem } },
3507 },
3508 },
3509 .{
3510 .scalar = .{ .any_int = .dword },
3511 .clobbers = .{ .eflags = true },
3512 .loop = .elementwise,
3513 .mir_tag = .{ ._, .cmp },
3514 .patterns = &.{
3515 .{ .ops = &.{ .cc_elem, .mem_elem, .gpr_elem } },
3516 .{ .ops = &.{ .cc_elem, .gpr_elem, .mem_elem } },
3517 .{ .ops = &.{ .cc_elem, .gpr_elem, .gpr_elem } },
3518 },
3519 },
3520 .{
3521 .scalar = .{ .any_int = .qword },
3522 .clobbers = .{ .eflags = true },
3523 .loop = .elementwise,
3524 .mir_tag = .{ ._, .cmp },
3525 .patterns = &.{
3526 .{ .ops = &.{ .cc_elem, .mem_elem, .gpr_elem } },
3527 .{ .ops = &.{ .cc_elem, .gpr_elem, .mem_elem } },
3528 .{ .ops = &.{ .cc_elem, .gpr_elem, .gpr_elem } },
3529 },
3530 },
3531 }, .{
3532 .cc = .e,
3533 .invert_result = switch (cmp_op) {
3534 .eq => false,
3535 .neq => true,
3536 else => unreachable,
3537 },
3538 }) catch |err| switch (err) {
3539 error.SelectFailed => return cg.fail("failed to select", .{}),
3540 else => |e| return e,
3541 },
3542 else => |e| return e,
3543 },
3544 .gte => unreachable,
3545 .gt => unreachable,
3546 }
3547 if (ops[0].index != res[0].index) try ops[0].die(cg);
3548 if (ops[1].index != res[0].index) try ops[1].die(cg);
3549 try res[0].moveTo(inst, cg);
3550 },
3551
3552 .cmp_lt,
3553 .cmp_lt_optimized,
3554 .cmp_lte,
3555 .cmp_lte_optimized,
3556 .cmp_gte,
3557 .cmp_gte_optimized,
3558 .cmp_gt,
3559 .cmp_gt_optimized,
3560 => |air_tag| if (use_old) try cg.airCmp(inst, switch (air_tag) {
3561 else => unreachable,
3562 .cmp_lt, .cmp_lt_optimized => .lt,
3563 .cmp_lte, .cmp_lte_optimized => .lte,
3564 .cmp_gte, .cmp_gte_optimized => .gte,
3565 .cmp_gt, .cmp_gt_optimized => .gt,
3566 }) else {
3567 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
3568 const scalar_ty = cg.typeOf(bin_op.lhs).scalarType(zcu);
3569 const signedness = if (scalar_ty.isAbiInt(zcu))
3570 scalar_ty.intInfo(zcu).signedness
3571 else
3572 .unsigned;
3573 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
3574 var res: [1]Temp = undefined;
3575 cg.select2(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Condition, switch (signedness) {
3576 .signed => switch (air_tag) {
3577 else => unreachable,
3578 .cmp_lt, .cmp_lt_optimized => .l,
3579 .cmp_lte, .cmp_lte_optimized => .le,
3580 .cmp_gte, .cmp_gte_optimized => .ge,
3581 .cmp_gt, .cmp_gt_optimized => .g,
3582 },
3583 .unsigned => switch (air_tag) {
3584 else => unreachable,
3585 .cmp_lt, .cmp_lt_optimized => .b,
3586 .cmp_lte, .cmp_lte_optimized => .be,
3587 .cmp_gte, .cmp_gte_optimized => .ae,
3588 .cmp_gt, .cmp_gt_optimized => .a,
3589 },
3590 })) {
3591 else => unreachable,
3592 inline .l, .le, .ge, .g, .b, .be, .ae, .a => |cc| comptime &.{ .{
3593 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
3594 .patterns = &.{
3595 .{ .src = .{ .imm8, .mem }, .commute = .{ 0, 1 } },
3596 .{ .src = .{ .imm8, .gpr }, .commute = .{ 0, 1 } },
3597 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3598 },
3599 .clobbers = .{ .eflags = true },
3600 .dst_temps = .{.{ .cc = cc.commute() }},
3601 .each = .{ .once = &.{
3602 .{ ._, .cmp, .src0b, .src1b, .none, .none },
3603 } },
3604 }, .{
3605 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
3606 .patterns = &.{
3607 .{ .src = .{ .mem, .imm8 } },
3608 .{ .src = .{ .gpr, .imm8 } },
3609 .{ .src = .{ .gpr, .mem } },
3610 .{ .src = .{ .gpr, .gpr } },
3611 },
3612 .clobbers = .{ .eflags = true },
3613 .dst_temps = .{.{ .cc = cc }},
3614 .each = .{ .once = &.{
3615 .{ ._, .cmp, .src0b, .src1b, .none, .none },
3616 } },
3617 }, .{
3618 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
3619 .patterns = &.{
3620 .{ .src = .{ .imm16, .mem }, .commute = .{ 0, 1 } },
3621 .{ .src = .{ .imm16, .gpr }, .commute = .{ 0, 1 } },
3622 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3623 },
3624 .clobbers = .{ .eflags = true },
3625 .dst_temps = .{.{ .cc = cc.commute() }},
3626 .each = .{ .once = &.{
3627 .{ ._, .cmp, .src0w, .src1w, .none, .none },
3628 } },
3629 }, .{
3630 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
3631 .patterns = &.{
3632 .{ .src = .{ .mem, .imm16 } },
3633 .{ .src = .{ .gpr, .imm16 } },
3634 .{ .src = .{ .gpr, .mem } },
3635 .{ .src = .{ .gpr, .gpr } },
3636 },
3637 .clobbers = .{ .eflags = true },
3638 .dst_temps = .{.{ .cc = cc }},
3639 .each = .{ .once = &.{
3640 .{ ._, .cmp, .src0w, .src1w, .none, .none },
3641 } },
3642 }, .{
3643 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
3644 .patterns = &.{
3645 .{ .src = .{ .imm32, .mem }, .commute = .{ 0, 1 } },
3646 .{ .src = .{ .imm32, .gpr }, .commute = .{ 0, 1 } },
3647 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3648 },
3649 .clobbers = .{ .eflags = true },
3650 .dst_temps = .{.{ .cc = cc.commute() }},
3651 .each = .{ .once = &.{
3652 .{ ._, .cmp, .esrc0, .esrc1, .none, .none },
3653 } },
3654 }, .{
3655 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
3656 .patterns = &.{
3657 .{ .src = .{ .mem, .imm32 } },
3658 .{ .src = .{ .gpr, .imm32 } },
3659 .{ .src = .{ .gpr, .mem } },
3660 .{ .src = .{ .gpr, .gpr } },
3661 },
3662 .clobbers = .{ .eflags = true },
3663 .dst_temps = .{.{ .cc = cc }},
3664 .each = .{ .once = &.{
3665 .{ ._, .cmp, .esrc0, .esrc1, .none, .none },
3666 } },
3667 }, .{
3668 .required_features = .{ .@"64bit", null },
3669 .constraints = .{ .{ .int = .qword }, .{ .int = .qword } },
3670 .patterns = &.{
3671 .{ .src = .{ .simm32, .mem }, .commute = .{ 0, 1 } },
3672 .{ .src = .{ .simm32, .gpr }, .commute = .{ 0, 1 } },
3673 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3674 },
3675 .clobbers = .{ .eflags = true },
3676 .dst_temps = .{.{ .cc = cc.commute() }},
3677 .each = .{ .once = &.{
3678 .{ ._, .cmp, .rsrc0, .rsrc1, .none, .none },
3679 } },
3680 }, .{
3681 .required_features = .{ .@"64bit", null },
3682 .constraints = .{ .{ .int = .qword }, .{ .int = .qword } },
3683 .patterns = &.{
3684 .{ .src = .{ .mem, .simm32 } },
3685 .{ .src = .{ .gpr, .simm32 } },
3686 .{ .src = .{ .gpr, .mem } },
3687 .{ .src = .{ .gpr, .gpr } },
3688 },
3689 .clobbers = .{ .eflags = true },
3690 .dst_temps = .{.{ .cc = cc }},
3691 .each = .{ .once = &.{
3692 .{ ._, .cmp, .rsrc0, .rsrc1, .none, .none },
3693 } },
3694 }, .{
3695 .required_features = .{ .@"64bit", null },
3696 .patterns = &.{
3697 .{ .src = .{ .to_mem, .to_mem } },
3698 },
3699 .extra_temps = .{
3700 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
3701 .{ .type = .bool, .kind = .{ .rc = .general_purpose } },
3702 .unused,
3703 },
3704 .clobbers = .{ .eflags = true },
3705 .dst_temps = .{.{ .rc = .general_purpose }},
3706 .each = .{ .limb = .{
3707 .of = .rsrc0,
3708 .header = &.{
3709 .{ ._, .xor, .tmp1b, .tmp1b, .none, .none },
3710 },
3711 .body = &.{
3712 .{ ._, .mov, .rtmp0, .{ .src_limb = 0 }, .none, .none },
3713 .{ ._r, .sh, .tmp1b, .{ .simm32 = 1 }, .none, .none },
3714 .{ ._, .sbb, .rtmp0, .{ .src_limb = 1 }, .none, .none },
3715 .{ ._c, .set, .tmp1b, .none, .none, .none },
3716 .{ .fromCondition(cc), .set, .dst0b, .none, .none, .none },
3717 },
3718 } },
3719 }, .{
3720 .patterns = &.{
3721 .{ .src = .{ .to_mem, .to_mem } },
3722 },
3723 .extra_temps = .{
3724 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3725 .{ .type = .bool, .kind = .{ .rc = .general_purpose } },
3726 .unused,
3727 },
3728 .clobbers = .{ .eflags = true },
3729 .dst_temps = .{.{ .rc = .general_purpose }},
3730 .each = .{ .limb = .{
3731 .of = .esrc0,
3732 .header = &.{
3733 .{ ._, .xor, .tmp1b, .tmp1b, .none, .none },
3734 },
3735 .body = &.{
3736 .{ ._, .mov, .etmp0, .{ .src_limb = 0 }, .none, .none },
3737 .{ ._r, .sh, .tmp1b, .{ .simm32 = 1 }, .none, .none },
3738 .{ ._, .sbb, .etmp0, .{ .src_limb = 1 }, .none, .none },
3739 .{ ._c, .set, .tmp1b, .none, .none, .none },
3740 .{ .fromCondition(cc), .set, .dst0b, .none, .none, .none },
3741 },
3742 } },
3743 } },
3744 }) catch |err| switch (err) {
3745 error.Select2Failed => return cg.fail("failed to select2 {s} {} {} {}", .{
3746 @tagName(air_tag),
3747 cg.typeOf(bin_op.lhs).fmt(pt),
3748 ops[0].tracking(cg),
3749 ops[1].tracking(cg),
3750 }),
3751 else => |e| return e,
3752 };
3753 if (ops[0].index != res[0].index) try ops[0].die(cg);
3754 if (ops[1].index != res[0].index) try ops[1].die(cg);
3755 try res[0].moveTo(inst, cg);
3756 },
3757 .cmp_eq, .cmp_eq_optimized, .cmp_neq, .cmp_neq_optimized => |air_tag| if (use_old) try cg.airCmp(inst, switch (air_tag) {
3758 else => unreachable,
3759 .cmp_eq, .cmp_eq_optimized => .eq,
3760 .cmp_neq, .cmp_neq_optimized => .neq,
3761 }) else fallback: {
3762 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
3763 if (ip.isOptionalType(cg.typeOf(bin_op.lhs).toIntern())) break :fallback try cg.airCmp(inst, switch (air_tag) {
3764 else => unreachable,
3765 .cmp_eq, .cmp_eq_optimized => .eq,
3766 .cmp_neq, .cmp_neq_optimized => .neq,
3767 });
3768 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
3769 var res: [1]Temp = undefined;
3770 cg.select2(&res, &.{cg.typeOfIndex(inst)}, &ops, switch (@as(Condition, switch (air_tag) {
3771 else => unreachable,
3772 .cmp_eq, .cmp_eq_optimized => .e,
3773 .cmp_neq, .cmp_neq_optimized => .ne,
3774 })) {
3775 else => unreachable,
3776 inline .e, .ne => |cc| comptime &.{ .{
3777 .required_features = .{ .avx2, null },
3778 .constraints = .{ .any_int, .any_int },
3779 .patterns = &.{
3780 .{ .src = .{ .ymm, .mem } },
3781 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
3782 .{ .src = .{ .ymm, .ymm } },
3783 },
3784 .clobbers = .{ .eflags = true },
3785 .extra_temps = .{ .{ .kind = .{ .rc = .sse } }, .unused, .unused },
3786 .dst_temps = .{.{ .cc = cc }},
3787 .each = .{ .once = &.{
3788 .{ .vp_, .xor, .ytmp0, .ysrc0, .ysrc1, .none },
3789 .{ .vp_, .@"test", .ytmp0, .ytmp0, .none, .none },
3790 } },
3791 }, .{
3792 .required_features = .{ .avx, null },
3793 .constraints = .{ .any_int, .any_int },
3794 .patterns = &.{
3795 .{ .src = .{ .ymm, .mem } },
3796 .{ .src = .{ .mem, .ymm }, .commute = .{ 0, 1 } },
3797 .{ .src = .{ .ymm, .ymm } },
3798 },
3799 .clobbers = .{ .eflags = true },
3800 .extra_temps = .{ .{ .kind = .{ .rc = .sse } }, .unused, .unused },
3801 .dst_temps = .{.{ .cc = cc }},
3802 .each = .{ .once = &.{
3803 .{ .v_pd, .xor, .ytmp0, .ysrc0, .ysrc1, .none },
3804 .{ .vp_, .@"test", .ytmp0, .ytmp0, .none, .none },
3805 } },
3806 }, .{
3807 .required_features = .{ .avx, null },
3808 .constraints = .{ .any_int, .any_int },
3809 .patterns = &.{
3810 .{ .src = .{ .xmm, .mem } },
3811 .{ .src = .{ .mem, .xmm }, .commute = .{ 0, 1 } },
3812 .{ .src = .{ .xmm, .xmm } },
3813 },
3814 .clobbers = .{ .eflags = true },
3815 .extra_temps = .{ .{ .kind = .{ .rc = .sse } }, .unused, .unused },
3816 .dst_temps = .{.{ .cc = cc }},
3817 .each = .{ .once = &.{
3818 .{ .vp_, .xor, .xtmp0, .xsrc0, .xsrc1, .none },
3819 .{ .vp_, .@"test", .xtmp0, .xtmp0, .none, .none },
3820 } },
3821 }, .{
3822 .required_features = .{ .sse4_1, null },
3823 .constraints = .{ .any_int, .any_int },
3824 .patterns = &.{
3825 .{ .src = .{ .mut_xmm, .mem } },
3826 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
3827 .{ .src = .{ .mut_xmm, .xmm } },
3828 },
3829 .clobbers = .{ .eflags = true },
3830 .dst_temps = .{.{ .cc = cc }},
3831 .each = .{ .once = &.{
3832 .{ .p_, .xor, .xsrc0, .xsrc1, .none, .none },
3833 .{ .p_, .@"test", .xsrc0, .xsrc0, .none, .none },
3834 } },
3835 }, .{
3836 .required_features = .{ .sse2, null },
3837 .constraints = .{ .any_int, .any_int },
3838 .patterns = &.{
3839 .{ .src = .{ .mut_xmm, .mem } },
3840 .{ .src = .{ .mem, .mut_xmm }, .commute = .{ 0, 1 } },
3841 .{ .src = .{ .mut_xmm, .xmm } },
3842 },
3843 .clobbers = .{ .eflags = true },
3844 .extra_temps = .{
3845 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3846 .{ .kind = .{ .rc = .sse } },
3847 .unused,
3848 },
3849 .dst_temps = .{.{ .cc = cc }},
3850 .each = .{ .once = &.{
3851 .{ .p_, .xor, .xtmp1, .xtmp1, .none, .none },
3852 .{ .p_, .xor, .xsrc0, .xsrc1, .none, .none },
3853 .{ .p_b, .cmpeq, .xtmp1, .xsrc0, .none, .none },
3854 .{ .p_b, .movmsk, .etmp0, .xtmp1, .none, .none },
3855 .{ ._, .xor, .etmp0, .{ .simm32 = std.math.maxInt(u16) }, .none, .none },
3856 } },
3857 }, .{
3858 .required_features = .{ .sse2, .mmx },
3859 .constraints = .{ .any_int, .any_int },
3860 .patterns = &.{
3861 .{ .src = .{ .mut_mm, .mem } },
3862 .{ .src = .{ .mem, .mut_mm }, .commute = .{ 0, 1 } },
3863 .{ .src = .{ .mut_mm, .mm } },
3864 },
3865 .clobbers = .{ .eflags = true },
3866 .extra_temps = .{
3867 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
3868 .{ .kind = .{ .rc = .mmx } },
3869 .unused,
3870 },
3871 .dst_temps = .{.{ .cc = cc }},
3872 .each = .{ .once = &.{
3873 .{ .p_, .xor, .rtmp1, .rtmp1, .none, .none },
3874 .{ .p_, .xor, .rsrc0, .rsrc1, .none, .none },
3875 .{ .p_b, .cmpeq, .rtmp1, .rsrc0, .none, .none },
3876 .{ .p_b, .movmsk, .etmp0, .rtmp1, .none, .none },
3877 .{ ._, .xor, .etmp0, .{ .simm32 = std.math.maxInt(u8) }, .none, .none },
3878 } },
3879 }, .{
3880 .constraints = .{ .{ .int = .byte }, .{ .int = .byte } },
3881 .patterns = &.{
3882 .{ .src = .{ .mem, .imm8 } },
3883 .{ .src = .{ .imm8, .mem }, .commute = .{ 0, 1 } },
3884 .{ .src = .{ .gpr, .imm8 } },
3885 .{ .src = .{ .imm8, .gpr }, .commute = .{ 0, 1 } },
3886 .{ .src = .{ .gpr, .mem } },
3887 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3888 .{ .src = .{ .gpr, .gpr } },
3889 },
3890 .clobbers = .{ .eflags = true },
3891 .dst_temps = .{.{ .cc = cc }},
3892 .each = .{ .once = &.{
3893 .{ ._, .cmp, .src0b, .src1b, .none, .none },
3894 } },
3895 }, .{
3896 .constraints = .{ .{ .int = .word }, .{ .int = .word } },
3897 .patterns = &.{
3898 .{ .src = .{ .mem, .imm16 } },
3899 .{ .src = .{ .imm16, .mem }, .commute = .{ 0, 1 } },
3900 .{ .src = .{ .gpr, .imm16 } },
3901 .{ .src = .{ .imm16, .gpr }, .commute = .{ 0, 1 } },
3902 .{ .src = .{ .gpr, .mem } },
3903 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3904 .{ .src = .{ .gpr, .gpr } },
3905 },
3906 .clobbers = .{ .eflags = true },
3907 .dst_temps = .{.{ .cc = cc }},
3908 .each = .{ .once = &.{
3909 .{ ._, .cmp, .src0w, .src1w, .none, .none },
3910 } },
3911 }, .{
3912 .constraints = .{ .{ .int = .dword }, .{ .int = .dword } },
3913 .patterns = &.{
3914 .{ .src = .{ .mem, .imm32 } },
3915 .{ .src = .{ .imm32, .mem }, .commute = .{ 0, 1 } },
3916 .{ .src = .{ .gpr, .imm32 } },
3917 .{ .src = .{ .imm32, .gpr }, .commute = .{ 0, 1 } },
3918 .{ .src = .{ .gpr, .mem } },
3919 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3920 .{ .src = .{ .gpr, .gpr } },
3921 },
3922 .clobbers = .{ .eflags = true },
3923 .dst_temps = .{.{ .cc = cc }},
3924 .each = .{ .once = &.{
3925 .{ ._, .cmp, .esrc0, .esrc1, .none, .none },
3926 } },
3927 }, .{
3928 .required_features = .{ .@"64bit", null },
3929 .constraints = .{ .{ .int = .qword }, .{ .int = .qword } },
3930 .patterns = &.{
3931 .{ .src = .{ .mem, .simm32 } },
3932 .{ .src = .{ .simm32, .mem }, .commute = .{ 0, 1 } },
3933 .{ .src = .{ .gpr, .simm32 } },
3934 .{ .src = .{ .simm32, .gpr }, .commute = .{ 0, 1 } },
3935 .{ .src = .{ .gpr, .mem } },
3936 .{ .src = .{ .mem, .gpr }, .commute = .{ 0, 1 } },
3937 .{ .src = .{ .gpr, .gpr } },
3938 },
3939 .clobbers = .{ .eflags = true },
3940 .dst_temps = .{.{ .cc = cc }},
3941 .each = .{ .once = &.{
3942 .{ ._, .cmp, .rsrc0, .rsrc1, .none, .none },
3943 } },
3944 }, .{
3945 .required_features = .{ .avx2, null },
3946 .patterns = &.{
3947 .{ .src = .{ .to_mem, .to_mem } },
3948 },
3949 .extra_temps = .{
3950 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
3951 .{ .kind = .{ .rc = .sse } },
3952 .{ .kind = .{ .rc = .sse } },
3953 },
3954 .dst_temps = .{.{ .cc = cc }},
3955 .each = .{ .limb = .{
3956 .of = .ysrc0,
3957 .header = &.{
3958 .{ .vp_, .xor, .ytmp2, .ytmp2, .ytmp2, .none },
3959 },
3960 .body = &.{
3961 .{ .v_, .movdqu, .ytmp1, .{ .src_limb = 0 }, .none, .none },
3962 .{ .vp_, .xor, .ytmp1, .ytmp1, .{ .src_limb = 1 }, .none },
3963 .{ .vp_, .@"or", .ytmp2, .ytmp2, .ytmp1, .none },
2792 },3964 },
2793 },3965 .trailer = &.{
2794 .{3966 .{ .vp_, .@"test", .ytmp2, .ytmp2, .none, .none },
2795 .required_features = &.{.avx},
2796 .scalar = .{ .any_int = .qword },
2797 .mir_tag = .{ .vp_q, .cmpeq },
2798 .patterns = &.{
2799 .{ .ops = &.{ .xmm_mask, .xmm, .mem } },
2800 .{ .ops = &.{ .xmm_mask, .mem, .xmm }, .commute = .{ 1, 2 } },
2801 .{ .ops = &.{ .xmm_mask, .xmm, .xmm } },
2802 },3967 },
3968 } },
3969 }, .{
3970 .required_features = .{ .avx, null },
3971 .patterns = &.{
3972 .{ .src = .{ .to_mem, .to_mem } },
2803 },3973 },
2804 .{3974 .extra_temps = .{
2805 .required_features = &.{.sse2},3975 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2806 .scalar = .{ .any_int = .byte },3976 .{ .kind = .{ .rc = .sse } },
2807 .mir_tag = .{ .p_b, .cmpeq },3977 .{ .kind = .{ .rc = .sse } },
2808 .patterns = &.{
2809 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .mem } },
2810 .{ .ops = &.{ .xmm_mask, .mem, .{ .implicit = 0 } } },
2811 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .xmm } },
2812 .{ .ops = &.{ .xmm_mask, .xmm, .{ .implicit = 0 } } },
2813 },
2814 },3978 },
2815 .{3979 .dst_temps = .{.{ .cc = cc }},
2816 .required_features = &.{.sse2},3980 .each = .{ .limb = .{
2817 .scalar = .{ .any_int = .word },3981 .of = .ysrc0,
2818 .mir_tag = .{ .p_w, .cmpeq },3982 .header = &.{
2819 .patterns = &.{3983 .{ .v_pd, .xor, .ytmp2, .ytmp2, .ytmp2, .none },
2820 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .mem } },
2821 .{ .ops = &.{ .xmm_mask, .mem, .{ .implicit = 0 } } },
2822 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .xmm } },
2823 .{ .ops = &.{ .xmm_mask, .xmm, .{ .implicit = 0 } } },
2824 },3984 },
2825 },3985 .body = &.{
2826 .{3986 .{ .v_pd, .movu, .ytmp1, .{ .src_limb = 0 }, .none, .none },
2827 .required_features = &.{.sse2},3987 .{ .v_pd, .xor, .ytmp1, .ytmp1, .{ .src_limb = 1 }, .none },
2828 .scalar = .{ .any_int = .dword },3988 .{ .v_pd, .@"or", .ytmp2, .ytmp2, .ytmp1, .none },
2829 .mir_tag = .{ .p_d, .cmpeq },
2830 .patterns = &.{
2831 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .mem } },
2832 .{ .ops = &.{ .xmm_mask, .mem, .{ .implicit = 0 } } },
2833 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .xmm } },
2834 .{ .ops = &.{ .xmm_mask, .xmm, .{ .implicit = 0 } } },
2835 },3989 },
2836 },3990 .trailer = &.{
2837 .{3991 .{ .vp_, .@"test", .ytmp2, .ytmp2, .none, .none },
2838 .required_features = &.{.sse4_1},
2839 .scalar = .{ .any_int = .qword },
2840 .mir_tag = .{ .p_q, .cmpeq },
2841 .patterns = &.{
2842 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .mem } },
2843 .{ .ops = &.{ .xmm_mask, .mem, .{ .implicit = 0 } } },
2844 .{ .ops = &.{ .xmm_mask, .{ .implicit = 0 }, .xmm } },
2845 .{ .ops = &.{ .xmm_mask, .xmm, .{ .implicit = 0 } } },
2846 },3992 },
3993 } },
3994 }, .{
3995 .required_features = .{ .avx, null },
3996 .patterns = &.{
3997 .{ .src = .{ .to_mem, .to_mem } },
2847 },3998 },
2848 .{3999 .extra_temps = .{
2849 .required_features = &.{.mmx},4000 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2850 .scalar = .{ .any_int = .byte },4001 .{ .kind = .{ .rc = .sse } },
2851 .mir_tag = .{ .p_b, .cmpeq },4002 .{ .kind = .{ .rc = .sse } },
2852 .patterns = &.{
2853 .{ .ops = &.{ .mm_mask, .{ .implicit = 0 }, .mem } },
2854 .{ .ops = &.{ .mm_mask, .mem, .{ .implicit = 0 } } },
2855 .{ .ops = &.{ .mm_mask, .{ .implicit = 0 }, .mm } },
2856 .{ .ops = &.{ .mm_mask, .mm, .{ .implicit = 0 } } },
2857 },
2858 },4003 },
2859 .{4004 .dst_temps = .{.{ .cc = cc }},
2860 .required_features = &.{.mmx},4005 .each = .{ .limb = .{
2861 .scalar = .{ .any_int = .word },4006 .of = .xsrc0,
2862 .mir_tag = .{ .p_w, .cmpeq },4007 .header = &.{
2863 .patterns = &.{4008 .{ .vp_, .xor, .xtmp2, .xtmp2, .xtmp2, .none },
2864 .{ .ops = &.{ .mm_mask, .{ .implicit = 0 }, .mem } },
2865 .{ .ops = &.{ .mm_mask, .mem, .{ .implicit = 0 } } },
2866 .{ .ops = &.{ .mm_mask, .{ .implicit = 0 }, .mm } },
2867 .{ .ops = &.{ .mm_mask, .mm, .{ .implicit = 0 } } },
2868 },4009 },
2869 },4010 .body = &.{
2870 .{4011 .{ .v_, .movdqu, .xtmp1, .{ .src_limb = 0 }, .none, .none },
2871 .required_features = &.{.mmx},4012 .{ .vp_, .xor, .xtmp1, .xtmp1, .{ .src_limb = 1 }, .none },
2872 .scalar = .{ .any_int = .dword },4013 .{ .vp_, .@"or", .xtmp2, .xtmp2, .xtmp1, .none },
2873 .mir_tag = .{ .p_d, .cmpeq },
2874 .patterns = &.{
2875 .{ .ops = &.{ .mm_mask, .{ .implicit = 0 }, .mem } },
2876 .{ .ops = &.{ .mm_mask, .mem, .{ .implicit = 0 } } },
2877 .{ .ops = &.{ .mm_mask, .{ .implicit = 0 }, .mm } },
2878 .{ .ops = &.{ .mm_mask, .mm, .{ .implicit = 0 } } },
2879 },4014 },
2880 },4015 .trailer = &.{
2881 .{4016 .{ .vp_, .@"test", .xtmp2, .xtmp2, .none, .none },
2882 .scalar = .bool,
2883 .clobbers = .{ .eflags = true },
2884 .invert_result = true,
2885 .mir_tag = .{ ._, .xor },
2886 .patterns = &.{
2887 .{ .ops = &.{ .mem, .{ .implicit = 0 }, .simm32 } },
2888 .{ .ops = &.{ .mem, .simm32, .{ .implicit = 0 } } },
2889 .{ .ops = &.{ .mem, .{ .implicit = 0 }, .gpr } },
2890 .{ .ops = &.{ .mem, .gpr, .{ .implicit = 0 } } },
2891 .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .simm32 } },
2892 .{ .ops = &.{ .gpr, .simm32, .{ .implicit = 0 } } },
2893 .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .mem } },
2894 .{ .ops = &.{ .gpr, .mem, .{ .implicit = 0 } } },
2895 .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .gpr } },
2896 .{ .ops = &.{ .gpr, .gpr, .{ .implicit = 0 } } },
2897 },4017 },
4018 } },
4019 }, .{
4020 .required_features = .{ .avx, null },
4021 .patterns = &.{
4022 .{ .src = .{ .to_mem, .to_mem } },
2898 },4023 },
28994024 .extra_temps = .{
2900 .{4025 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2901 .required_features = &.{.avx2},4026 .{ .kind = .{ .rc = .sse } },
2902 .scalar = .{ .any_int = .byte },4027 .{ .kind = .{ .rc = .sse } },
2903 .loop = .elementwise,
2904 .mir_tag = .{ .vp_b, .cmpeq },
2905 .patterns = &.{
2906 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2907 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2908 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
2909 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
2910 },
2911 },4028 },
2912 .{4029 .dst_temps = .{.{ .cc = cc }},
2913 .required_features = &.{.avx2},4030 .each = .{ .limb = .{
2914 .scalar = .{ .any_int = .word },4031 .of = .xsrc0,
2915 .loop = .elementwise,4032 .header = &.{
2916 .mir_tag = .{ .vp_w, .cmpeq },4033 .{ .vp_, .xor, .xtmp2, .xtmp2, .xtmp2, .none },
2917 .patterns = &.{
2918 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2919 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2920 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
2921 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
2922 },4034 },
2923 },4035 .body = &.{
2924 .{4036 .{ .v_, .movdqu, .xtmp1, .{ .src_limb = 0 }, .none, .none },
2925 .required_features = &.{.avx2},4037 .{ .vp_, .xor, .xtmp1, .xtmp1, .{ .src_limb = 1 }, .none },
2926 .scalar = .{ .any_int = .dword },4038 .{ .vp_, .@"or", .xtmp2, .xtmp2, .xtmp1, .none },
2927 .loop = .elementwise,
2928 .mir_tag = .{ .vp_d, .cmpeq },
2929 .patterns = &.{
2930 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2931 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2932 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
2933 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
2934 },4039 },
2935 },4040 .trailer = &.{
2936 .{4041 .{ .vp_, .@"test", .xtmp2, .xtmp2, .none, .none },
2937 .required_features = &.{.avx2},
2938 .scalar = .{ .any_int = .qword },
2939 .loop = .elementwise,
2940 .mir_tag = .{ .vp_q, .cmpeq },
2941 .patterns = &.{
2942 .{ .ops = &.{ .ymm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2943 .{ .ops = &.{ .ymm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2944 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .mem_limb } },
2945 .{ .ops = &.{ .ymm_mask_limb, .ymm_limb, .ymm_limb } },
2946 },4042 },
4043 } },
4044 }, .{
4045 .required_features = .{ .sse4_1, null },
4046 .patterns = &.{
4047 .{ .src = .{ .to_mem, .to_mem } },
2947 },4048 },
2948 .{4049 .extra_temps = .{
2949 .required_features = &.{.avx},4050 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2950 .scalar = .{ .any_int = .byte },4051 .{ .kind = .{ .rc = .sse } },
2951 .loop = .elementwise,4052 .{ .kind = .{ .rc = .sse } },
2952 .mir_tag = .{ .vp_b, .cmpeq },
2953 .patterns = &.{
2954 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2955 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2956 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
2957 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
2958 },
2959 },4053 },
2960 .{4054 .dst_temps = .{.{ .cc = cc }},
2961 .required_features = &.{.avx},4055 .each = .{ .limb = .{
2962 .scalar = .{ .any_int = .word },4056 .of = .xsrc0,
2963 .loop = .elementwise,4057 .header = &.{
2964 .mir_tag = .{ .vp_w, .cmpeq },4058 .{ .p_, .xor, .xtmp2, .xtmp2, .none, .none },
2965 .patterns = &.{
2966 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2967 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2968 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
2969 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
2970 },4059 },
2971 },4060 .body = &.{
2972 .{4061 .{ ._, .movdqu, .xtmp1, .{ .src_limb = 0 }, .none, .none },
2973 .required_features = &.{.avx},4062 .{ .p_, .xor, .xtmp1, .{ .src_limb = 1 }, .none, .none },
2974 .scalar = .{ .any_int = .dword },4063 .{ .p_, .@"or", .xtmp2, .xtmp1, .none, .none },
2975 .loop = .elementwise,
2976 .mir_tag = .{ .vp_d, .cmpeq },
2977 .patterns = &.{
2978 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2979 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2980 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
2981 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
2982 },4064 },
2983 },4065 .trailer = &.{
2984 .{4066 .{ .p_, .@"test", .xtmp2, .xtmp2, .none, .none },
2985 .required_features = &.{.avx},
2986 .scalar = .{ .any_int = .qword },
2987 .loop = .elementwise,
2988 .mir_tag = .{ .vp_q, .cmpeq },
2989 .patterns = &.{
2990 .{ .ops = &.{ .xmm_mask_limb, .{ .explicit = 0 }, .mem_limb } },
2991 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } },
2992 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .mem_limb } },
2993 .{ .ops = &.{ .xmm_mask_limb, .xmm_limb, .xmm_limb } },
2994 },4067 },
4068 } },
4069 }, .{
4070 .required_features = .{ .sse2, null },
4071 .patterns = &.{
4072 .{ .src = .{ .to_mem, .to_mem } },
2995 },4073 },
2996 .{4074 .extra_temps = .{
2997 .required_features = &.{.sse2},4075 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
2998 .scalar = .{ .any_int = .byte },4076 .{ .kind = .{ .rc = .sse } },
2999 .loop = .elementwise,4077 .{ .kind = .{ .rc = .sse } },
3000 .mir_tag = .{ .p_b, .cmpeq },
3001 .patterns = &.{
3002 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3003 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3004 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3005 },
3006 },4078 },
3007 .{4079 .dst_temps = .{.{ .cc = cc }},
3008 .required_features = &.{.sse2},4080 .each = .{ .limb = .{
3009 .scalar = .{ .any_int = .word },4081 .of = .xsrc0,
3010 .loop = .elementwise,4082 .header = &.{
3011 .mir_tag = .{ .p_w, .cmpeq },4083 .{ .p_, .xor, .xtmp2, .xtmp2, .none, .none },
3012 .patterns = &.{
3013 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3014 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3015 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3016 },4084 },
3017 },4085 .body = &.{
3018 .{4086 .{ ._, .movdqu, .xtmp1, .{ .src_limb = 0 }, .none, .none },
3019 .required_features = &.{.sse2},4087 .{ .p_, .xor, .xtmp1, .{ .src_limb = 1 }, .none, .none },
3020 .scalar = .{ .any_int = .dword },4088 .{ .p_, .@"or", .xtmp2, .xtmp1, .none, .none },
3021 .loop = .elementwise,
3022 .mir_tag = .{ .p_d, .cmpeq },
3023 .patterns = &.{
3024 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3025 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3026 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3027 },4089 },
3028 },4090 .trailer = &.{
3029 .{4091 .{ .p_, .xor, .xtmp1, .xtmp1, .none, .none },
3030 .required_features = &.{.sse4_1},4092 .{ .p_b, .cmpeq, .xtmp2, .xtmp1, .none, .none },
3031 .scalar = .{ .any_int = .qword },4093 .{ .p_b, .movmsk, .etmp0, .xtmp2, .none, .none },
3032 .loop = .elementwise,4094 .{ ._, .xor, .etmp0, .{ .simm32 = std.math.maxInt(u16) }, .none, .none },
3033 .mir_tag = .{ .p_q, .cmpeq },
3034 .patterns = &.{
3035 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3036 .{ .ops = &.{ .xmm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3037 .{ .ops = &.{ .xmm_mask_limb, .{ .implicit = 0 }, .xmm_limb } },
3038 },4095 },
4096 } },
4097 }, .{
4098 .required_features = .{ .sse, .mmx },
4099 .patterns = &.{
4100 .{ .src = .{ .to_mem, .to_mem } },
3039 },4101 },
3040 .{4102 .extra_temps = .{
3041 .required_features = &.{.mmx},4103 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
3042 .scalar = .{ .any_int = .byte },4104 .{ .kind = .{ .rc = .mmx } },
3043 .loop = .elementwise,4105 .{ .kind = .{ .rc = .mmx } },
3044 .mir_tag = .{ .p_b, .cmpeq },
3045 .patterns = &.{
3046 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3047 .{ .ops = &.{ .mm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3048 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mm_limb } },
3049 },
3050 },4106 },
3051 .{4107 .dst_temps = .{.{ .cc = cc }},
3052 .required_features = &.{.mmx},4108 .each = .{ .limb = .{
3053 .scalar = .{ .any_int = .word },4109 .of = .rsrc0,
3054 .loop = .elementwise,4110 .header = &.{
3055 .mir_tag = .{ .p_w, .cmpeq },4111 .{ .p_, .xor, .rtmp2, .rtmp2, .none, .none },
3056 .patterns = &.{
3057 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3058 .{ .ops = &.{ .mm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3059 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mm_limb } },
3060 },4112 },
3061 },4113 .body = &.{
3062 .{4114 .{ ._q, .mov, .rtmp1, .{ .src_limb = 0 }, .none, .none },
3063 .required_features = &.{.mmx},4115 .{ .p_, .xor, .rtmp1, .{ .src_limb = 1 }, .none, .none },
3064 .scalar = .{ .any_int = .dword },4116 .{ .p_, .@"or", .rtmp2, .rtmp1, .none, .none },
3065 .loop = .elementwise,
3066 .mir_tag = .{ .p_d, .cmpeq },
3067 .patterns = &.{
3068 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mem_limb } },
3069 .{ .ops = &.{ .mm_mask_limb, .mem_limb, .{ .implicit = 0 } } },
3070 .{ .ops = &.{ .mm_mask_limb, .{ .implicit = 0 }, .mm_limb } },
3071 },4117 },
3072 },4118 .trailer = &.{
3073 .{4119 .{ .p_, .xor, .rtmp1, .rtmp1, .none, .none },
3074 .scalar = .bool,4120 .{ .p_b, .cmpeq, .rtmp2, .rtmp1, .none, .none },
3075 .clobbers = .{ .eflags = true },4121 .{ .p_b, .movmsk, .etmp0, .rtmp2, .none, .none },
3076 .invert_result = true,4122 .{ ._, .xor, .etmp0, .{ .simm32 = std.math.maxInt(u8) }, .none, .none },
3077 .loop = .elementwise,
3078 .mir_tag = .{ ._, .xor },
3079 .patterns = &.{
3080 .{ .ops = &.{ .mem_limb, .{ .implicit = 0 }, .gpr_limb } },
3081 .{ .ops = &.{ .mem_limb, .gpr_limb, .{ .implicit = 0 } } },
3082 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .mem_limb } },
3083 .{ .ops = &.{ .gpr_limb, .mem_limb, .{ .implicit = 0 } } },
3084 .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .gpr_limb } },
3085 },4123 },
4124 } },
4125 }, .{
4126 .required_features = .{ .@"64bit", null },
4127 .patterns = &.{
4128 .{ .src = .{ .to_mem, .to_mem } },
3086 },4129 },
3087 .{4130 .extra_temps = .{
3088 .scalar = .{ .any_int = .byte },4131 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
3089 .clobbers = .{ .eflags = true },4132 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
3090 .loop = .elementwise,4133 .{ .type = .u64, .kind = .{ .rc = .general_purpose } },
3091 .mir_tag = .{ ._, .cmp },
3092 .patterns = &.{
3093 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3094 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3095 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3096 },
3097 },4134 },
3098 .{4135 .dst_temps = .{.{ .cc = cc }},
3099 .scalar = .{ .any_int = .word },4136 .each = .{ .limb = .{
3100 .clobbers = .{ .eflags = true },4137 .of = .rsrc0,
3101 .loop = .elementwise,4138 .header = &.{
3102 .mir_tag = .{ ._, .cmp },4139 .{ ._, .xor, .rtmp2, .rtmp2, .none, .none },
3103 .patterns = &.{
3104 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3105 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3106 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3107 },4140 },
3108 },4141 .body = &.{
3109 .{4142 .{ ._, .mov, .rtmp1, .{ .src_limb = 0 }, .none, .none },
3110 .scalar = .{ .any_int = .dword },4143 .{ ._, .xor, .rtmp1, .{ .src_limb = 1 }, .none, .none },
3111 .clobbers = .{ .eflags = true },4144 .{ ._, .@"or", .rtmp2, .rtmp1, .none, .none },
3112 .loop = .elementwise,
3113 .mir_tag = .{ ._, .cmp },
3114 .patterns = &.{
3115 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3116 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3117 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3118 },4145 },
3119 },4146 .trailer = &.{
3120 .{4147 .{ ._, .@"test", .rtmp2, .rtmp2, .none, .none },
3121 .scalar = .{ .any_int = .qword },
3122 .clobbers = .{ .eflags = true },
3123 .loop = .elementwise,
3124 .mir_tag = .{ ._, .cmp },
3125 .patterns = &.{
3126 .{ .ops = &.{ .cc_mask_limb, .mem_limb, .gpr_limb } },
3127 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .mem_limb } },
3128 .{ .ops = &.{ .cc_mask_limb, .gpr_limb, .gpr_limb } },
3129 },4148 },
3130 },4149 } },
3131 }, .{4150 }, .{
3132 .cc = .e,4151 .patterns = &.{
3133 .invert_result = switch (cmp_op) {4152 .{ .src = .{ .to_mem, .to_mem } },
3134 .eq => false,
3135 .neq => true,
3136 else => unreachable,
3137 },4153 },
4154 .extra_temps = .{
4155 .{ .type = .usize, .kind = .{ .rc = .general_purpose } },
4156 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4157 .{ .type = .u32, .kind = .{ .rc = .general_purpose } },
4158 },
4159 .dst_temps = .{.{ .cc = cc }},
4160 .each = .{ .limb = .{
4161 .of = .esrc0,
4162 .header = &.{
4163 .{ ._, .xor, .etmp2, .etmp2, .none, .none },
4164 },
4165 .body = &.{
4166 .{ ._, .mov, .etmp1, .{ .src_limb = 0 }, .none, .none },
4167 .{ ._, .xor, .etmp1, .{ .src_limb = 1 }, .none, .none },
4168 .{ ._, .@"or", .etmp2, .etmp1, .none, .none },
4169 },
4170 .trailer = &.{
4171 .{ ._, .@"test", .etmp2, .etmp2, .none, .none },
4172 },
4173 } },
4174 } },
4175 }) catch |err| switch (err) {
4176 error.Select2Failed => return cg.fail("failed to select2 {s} {} {} {}", .{
4177 @tagName(air_tag),
4178 cg.typeOf(bin_op.lhs).fmt(pt),
4179 ops[0].tracking(cg),
4180 ops[1].tracking(cg),
3138 }),4181 }),
3139 .gte => unreachable,4182 else => |e| return e,
3140 .gt => unreachable,4183 };
3141 }
3142 if (ops[0].index != res[0].index) try ops[0].die(cg);4184 if (ops[0].index != res[0].index) try ops[0].die(cg);
3143 if (ops[1].index != res[0].index) try ops[1].die(cg);4185 if (ops[1].index != res[0].index) try ops[1].die(cg);
3144 try res[0].moveTo(inst, cg);4186 try res[0].moveTo(inst, cg);
...@@ -13850,7 +14892,6 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -13850,7 +14892,6 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
13850 .undef,14892 .undef,
13851 .immediate,14893 .immediate,
13852 .eflags,14894 .eflags,
13853 .register,
13854 .register_offset,14895 .register_offset,
13855 .register_overflow,14896 .register_overflow,
13856 .register_mask,14897 .register_mask,
...@@ -13864,7 +14905,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -13864,7 +14905,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
13864 .reserved_frame,14905 .reserved_frame,
13865 .air_ref,14906 .air_ref,
13866 => unreachable,14907 => unreachable,
13867 .register_pair, .register_triple, .register_quadruple, .load_frame => null,14908 .register, .register_pair, .register_triple, .register_quadruple, .load_frame => null,
13868 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: {14909 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: {
13869 switch (resolved_dst_mcv) {14910 switch (resolved_dst_mcv) {
13870 .memory => |addr| if (std.math.cast(14911 .memory => |addr| if (std.math.cast(
...@@ -13893,8 +14934,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v...@@ -13893,8 +14934,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v
13893 };14934 };
13894 },14935 },
13895 };14936 };
13896 defer if (dst_info) |info|14937 defer if (dst_info) |info| self.register_manager.unlockReg(info.addr_lock);
13897 self.register_manager.unlockReg(info.addr_lock);
1389814938
13899 const resolved_src_mcv = switch (src_mcv) {14939 const resolved_src_mcv = switch (src_mcv) {
13900 else => src_mcv,14940 else => src_mcv,
...@@ -16299,15 +17339,15 @@ fn genSetReg(...@@ -16299,15 +17339,15 @@ fn genSetReg(
16299 const bits_lock = self.register_manager.lockReg(bits_reg);17339 const bits_lock = self.register_manager.lockReg(bits_reg);
16300 defer if (bits_lock) |lock| self.register_manager.unlockReg(lock);17340 defer if (bits_lock) |lock| self.register_manager.unlockReg(lock);
1630117341
16302 const pack_reg = switch (src_reg_mask.scalar) {17342 const pack_reg = switch (src_reg_mask.info.scalar) {
16303 else => src_reg_mask.reg,17343 else => src_reg_mask.reg,
16304 .word => try self.register_manager.allocReg(null, abi.RegisterClass.sse),17344 .word => try self.register_manager.allocReg(null, abi.RegisterClass.sse),
16305 };17345 };
16306 const pack_lock = self.register_manager.lockReg(pack_reg);17346 const pack_lock = self.register_manager.lockReg(pack_reg);
16307 defer if (pack_lock) |lock| self.register_manager.unlockReg(lock);17347 defer if (pack_lock) |lock| self.register_manager.unlockReg(lock);
1630817348
16309 var mask_size: u32 = @intCast(ty.vectorLen(zcu) * @divExact(src_reg_mask.scalar.bitSize(), 8));17349 var mask_size: u32 = @intCast(ty.vectorLen(zcu) * @divExact(src_reg_mask.info.scalar.bitSize(), 8));
16310 switch (src_reg_mask.scalar) {17350 switch (src_reg_mask.info.scalar) {
16311 else => {},17351 else => {},
16312 .word => {17352 .word => {
16313 const src_alias = registerAlias(src_reg_mask.reg, mask_size);17353 const src_alias = registerAlias(src_reg_mask.reg, mask_size);
...@@ -16321,13 +17361,13 @@ fn genSetReg(...@@ -16321,13 +17361,13 @@ fn genSetReg(
16321 mask_size = std.math.divCeil(u32, mask_size, 2) catch unreachable;17361 mask_size = std.math.divCeil(u32, mask_size, 2) catch unreachable;
16322 },17362 },
16323 }17363 }
16324 try self.asmRegisterRegister(.{ switch (src_reg_mask.scalar) {17364 try self.asmRegisterRegister(.{ switch (src_reg_mask.info.scalar) {
16325 .byte, .word => if (has_avx) .vp_b else .p_b,17365 .byte, .word => if (has_avx) .vp_b else .p_b,
16326 .dword => if (has_avx) .v_ps else ._ps,17366 .dword => if (has_avx) .v_ps else ._ps,
16327 .qword => if (has_avx) .v_pd else ._pd,17367 .qword => if (has_avx) .v_pd else ._pd,
16328 else => unreachable,17368 else => unreachable,
16329 }, .movmsk }, bits_reg.to32(), registerAlias(pack_reg, mask_size));17369 }, .movmsk }, bits_reg.to32(), registerAlias(pack_reg, mask_size));
16330 if (src_reg_mask.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size));17370 if (src_reg_mask.info.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size));
16331 try self.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{});17371 try self.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{});
16332 },17372 },
16333 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {17373 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
...@@ -21239,18 +22279,14 @@ const Temp = struct {...@@ -21239,18 +22279,14 @@ const Temp = struct {
21239 return true;22279 return true;
21240 }22280 }
2124122281
21242 fn toRegClass(temp: *Temp, rc: Register.Class, cg: *CodeGen) !bool {22282 fn toRegClass(temp: *Temp, mut: bool, rc: Register.Class, cg: *CodeGen) !bool {
21243 const val, const ty = switch (temp.unwrap(cg)) {22283 const val = temp.tracking(cg).short;
21244 .ref => |ref| .{ temp.tracking(cg).short, cg.typeOf(ref) },22284 if (!mut or temp.isMut(cg)) switch (val) {
21245 .temp => |temp_index| val: {22285 else => {},
21246 const temp_tracking = temp_index.tracking(cg);22286 .register => |reg| if (reg.class() == rc) return false,
21247 switch (temp_tracking.short) {22287 .register_offset => |reg_off| if (reg_off.reg.class() == rc and reg_off.off == 0) return false,
21248 else => {},
21249 .register => |reg| if (reg.class() == rc) return false,
21250 }
21251 break :val .{ temp_tracking.short, temp_index.typeOf(cg) };
21252 },
21253 };22288 };
22289 const ty = temp.typeOf(cg);
21254 const new_temp_index = cg.next_temp_index;22290 const new_temp_index = cg.next_temp_index;
21255 cg.temp_type[@intFromEnum(new_temp_index)] = ty;22291 cg.temp_type[@intFromEnum(new_temp_index)] = ty;
21256 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), regSetForRegClass(rc));22292 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), regSetForRegClass(rc));
...@@ -21281,15 +22317,11 @@ const Temp = struct {...@@ -21281,15 +22317,11 @@ const Temp = struct {
21281 first_temp.* = result_temp;22317 first_temp.* = result_temp;
21282 }22318 }
2128322319
21284 fn asMask(temp: Temp, kind: MaskKind, inverted: bool, scalar: Memory.Size, cg: *CodeGen) void {22320 fn asMask(temp: Temp, info: MaskInfo, cg: *CodeGen) void {
21285 assert(scalar != .none);22321 assert(info.scalar != .none);
21286 const mcv = &temp.unwrap(cg).temp.tracking(cg).short;22322 const mcv = &temp.unwrap(cg).temp.tracking(cg).short;
21287 mcv.* = .{ .register_mask = .{22323 const reg = mcv.register;
21288 .reg = mcv.register,22324 mcv.* = .{ .register_mask = .{ .reg = reg, .info = info } };
21289 .kind = kind,
21290 .inverted = inverted,
21291 .scalar = scalar,
21292 } };
21293 }22325 }
2129422326
21295 fn toLea(temp: *Temp, cg: *CodeGen) !bool {22327 fn toLea(temp: *Temp, cg: *CodeGen) !bool {
...@@ -21335,9 +22367,25 @@ const Temp = struct {...@@ -21335,9 +22367,25 @@ const Temp = struct {
21335 }22367 }
21336 }22368 }
2133722369
22370 fn toMemory(temp: *Temp, cg: *CodeGen) !bool {
22371 const temp_tracking = temp.tracking(cg);
22372 if (temp_tracking.short.isMemory()) return false;
22373 const new_temp_index = cg.next_temp_index;
22374 const ty = temp.typeOf(cg);
22375 cg.temp_type[@intFromEnum(new_temp_index)] = ty;
22376 const new_frame_index = try cg.allocFrameIndex(.initSpill(ty, cg.pt.zcu));
22377 try cg.genSetMem(.{ .frame = new_frame_index }, 0, ty, temp_tracking.short, .{});
22378 new_temp_index.tracking(cg).* = .init(.{ .load_frame = .{ .index = new_frame_index } });
22379 try temp.die(cg);
22380 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
22381 temp.* = .{ .index = new_temp_index.toIndex() };
22382 return true;
22383 }
22384
21338 fn toBase(temp: *Temp, cg: *CodeGen) !bool {22385 fn toBase(temp: *Temp, cg: *CodeGen) !bool {
21339 const temp_tracking = temp.tracking(cg);22386 const temp_tracking = temp.tracking(cg);
21340 if (temp_tracking.short.isBase()) return false;22387 if (temp_tracking.short.isBase()) return false;
22388 if (try temp.toMemory(cg)) return true;
21341 const new_temp_index = cg.next_temp_index;22389 const new_temp_index = cg.next_temp_index;
21342 cg.temp_type[@intFromEnum(new_temp_index)] = temp.typeOf(cg);22390 cg.temp_type[@intFromEnum(new_temp_index)] = temp.typeOf(cg);
21343 const new_reg =22391 const new_reg =
...@@ -21561,20 +22609,20 @@ fn tempAlloc(cg: *CodeGen, ty: Type) !Temp {...@@ -21561,20 +22609,20 @@ fn tempAlloc(cg: *CodeGen, ty: Type) !Temp {
21561 return .{ .index = temp_index.toIndex() };22609 return .{ .index = temp_index.toIndex() };
21562}22610}
2156322611
21564fn tempAllocReg(cg: *CodeGen, ty: Type, rc: RegisterManager.RegisterBitSet) !Temp {22612fn tempAllocReg(cg: *CodeGen, ty: Type, rs: RegisterManager.RegisterBitSet) !Temp {
21565 const temp_index = cg.next_temp_index;22613 const temp_index = cg.next_temp_index;
21566 temp_index.tracking(cg).* = .init(22614 temp_index.tracking(cg).* = .init(
21567 .{ .register = try cg.register_manager.allocReg(temp_index.toIndex(), rc) },22615 .{ .register = try cg.register_manager.allocReg(temp_index.toIndex(), rs) },
21568 );22616 );
21569 cg.temp_type[@intFromEnum(temp_index)] = ty;22617 cg.temp_type[@intFromEnum(temp_index)] = ty;
21570 cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);22618 cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
21571 return .{ .index = temp_index.toIndex() };22619 return .{ .index = temp_index.toIndex() };
21572}22620}
2157322621
21574fn tempAllocRegPair(cg: *CodeGen, ty: Type, rc: RegisterManager.RegisterBitSet) !Temp {22622fn tempAllocRegPair(cg: *CodeGen, ty: Type, rs: RegisterManager.RegisterBitSet) !Temp {
21575 const temp_index = cg.next_temp_index;22623 const temp_index = cg.next_temp_index;
21576 temp_index.tracking(cg).* = .init(22624 temp_index.tracking(cg).* = .init(
21577 .{ .register_pair = try cg.register_manager.allocRegs(2, temp_index.toIndex(), rc) },22625 .{ .register_pair = try cg.register_manager.allocRegs(2, temp_index.toIndex(), rs) },
21578 );22626 );
21579 cg.temp_type[@intFromEnum(temp_index)] = ty;22627 cg.temp_type[@intFromEnum(temp_index)] = ty;
21580 cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);22628 cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
...@@ -21696,18 +22744,21 @@ const Pattern = struct {...@@ -21696,18 +22744,21 @@ const Pattern = struct {
21696 once,22744 once,
21697 /// execute the instruction on all groups of non-overlapping bits in the entire value22745 /// execute the instruction on all groups of non-overlapping bits in the entire value
21698 bitwise,22746 bitwise,
21699 /// for each element, execute the instruction on each limb, propogating the carry flag22747 /// for each element, execute the instruction on each limb, propagating the carry flag
21700 limbwise_carry,22748 limbwise_carry,
22749 /// for each element, execute the instruction on each limb, propagating a register
22750 limbwise_reduce,
21701 /// for each element, execute the instruction on pairs of limbs, starting from the22751 /// for each element, execute the instruction on pairs of limbs, starting from the
21702 /// least significant, propogating a limb22752 /// least significant, propagating a limb
21703 limbwise_pairs_forward,22753 limbwise_pairs_forward,
21704 /// for each element, execute the instruction on pairs of limbs, starting from the22754 /// for each element, execute the instruction on pairs of limbs, starting from the
21705 /// most significant, propogating a limb22755 /// most significant, propagating a limb
21706 limbwise_pairs_reverse,22756 limbwise_pairs_reverse,
21707 /// for each element, execute the instruction22757 /// for each element, execute the instruction
21708 elementwise,22758 elementwise,
21709 } = .once,22759 } = .once,
21710 mir_tag: Mir.Inst.FixedTag,22760 mir_tag: Mir.Inst.FixedTag,
22761 final_mir_tag: ?Mir.Inst.FixedTag = null,
21711 patterns: []const Pattern,22762 patterns: []const Pattern,
21712 };22763 };
2171322764
...@@ -21740,7 +22791,7 @@ const Pattern = struct {...@@ -21740,7 +22791,7 @@ const Pattern = struct {
21740 ymm_sign_mask,22791 ymm_sign_mask,
21741 /// any memory22792 /// any memory
21742 mem,22793 mem,
21743 /// a limb stored in a gpr22794 /// a limb stored in a general purpose register
21744 gpr_limb,22795 gpr_limb,
21745 /// a limb stored in a 64-bit mmx register22796 /// a limb stored in a 64-bit mmx register
21746 mm_limb,22797 mm_limb,
...@@ -21750,8 +22801,16 @@ const Pattern = struct {...@@ -21750,8 +22801,16 @@ const Pattern = struct {
21750 ymm_limb,22801 ymm_limb,
21751 /// a limb stored in memory22802 /// a limb stored in memory
21752 mem_limb,22803 mem_limb,
21753 /// a limb stored in a condition code22804 /// a mutable limb stored in a general purpose register
21754 cc_mask_limb,22805 mut_gpr_limb,
22806 /// a mutable limb stored in memory
22807 mut_mem_limb,
22808 /// an element stored in a condition code
22809 cc_elem,
22810 /// an element stored in a general purpose register
22811 gpr_elem,
22812 /// an element stored in memory
22813 mem_elem,
21755 /// a limb stored in a 64-bit mmx register mask22814 /// a limb stored in a 64-bit mmx register mask
21756 mm_mask_limb,22815 mm_mask_limb,
21757 /// a limb stored in a 128-bit sse register masuk22816 /// a limb stored in a 128-bit sse register masuk
...@@ -21773,7 +22832,7 @@ const Pattern = struct {...@@ -21773,7 +22832,7 @@ const Pattern = struct {
2177322832
21774 fn matches(op: Op, is_mut: bool, temp: Temp, cg: *CodeGen) bool {22833 fn matches(op: Op, is_mut: bool, temp: Temp, cg: *CodeGen) bool {
21775 switch (op) {22834 switch (op) {
21776 .implicit, .explicit, .cc, .cc_mask_limb => unreachable,22835 .implicit, .explicit, .cc, .cc_elem => unreachable,
21777 else => {},22836 else => {},
21778 // temp is undefined22837 // temp is undefined
21779 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => return true,22838 .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => return true,
...@@ -21781,7 +22840,7 @@ const Pattern = struct {...@@ -21781,7 +22840,7 @@ const Pattern = struct {
21781 const temp_ty = temp.typeOf(cg);22840 const temp_ty = temp.typeOf(cg);
21782 const abi_size = temp_ty.abiSize(cg.pt.zcu);22841 const abi_size = temp_ty.abiSize(cg.pt.zcu);
21783 return switch (op) {22842 return switch (op) {
21784 .implicit, .explicit, .cc, .cc_mask_limb, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable,22843 .implicit, .explicit, .cc, .cc_elem, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable,
21785 .gpr => abi_size <= 8 and switch (temp.tracking(cg).short) {22844 .gpr => abi_size <= 8 and switch (temp.tracking(cg).short) {
21786 .register => |reg| reg.class() == .general_purpose,22845 .register => |reg| reg.class() == .general_purpose,
21787 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and22846 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and
...@@ -21803,8 +22862,8 @@ const Pattern = struct {...@@ -21803,8 +22862,8 @@ const Pattern = struct {
21803 .register_offset => |reg_off| reg_off.reg.class() == .sse and reg_off.off == 0,22862 .register_offset => |reg_off| reg_off.reg.class() == .sse and reg_off.off == 0,
21804 else => cg.regClassForType(temp_ty) == .sse,22863 else => cg.regClassForType(temp_ty) == .sse,
21805 },22864 },
21806 .mem, .mem_limb => (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(),22865 .mem, .mem_limb, .mut_mem_limb, .mem_elem => (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(),
21807 .gpr_limb => abi_size > 8 and switch (temp.tracking(cg).short) {22866 .gpr_limb, .mut_gpr_limb, .gpr_elem => abi_size > 8 and switch (temp.tracking(cg).short) {
21808 .register, .register_pair, .register_triple, .register_quadruple => true,22867 .register, .register_pair, .register_triple, .register_quadruple => true,
21809 else => |mcv| mcv.isMemory(),22868 else => |mcv| mcv.isMemory(),
21810 },22869 },
...@@ -21837,6 +22896,20 @@ const Pattern = struct {...@@ -21837,6 +22896,20 @@ const Pattern = struct {
21837 };22896 };
21838 }22897 }
21839 };22898 };
22899
22900 const Instruction = struct {
22901 mir_tag: Mir.Inst.FixedTag,
22902 operands: [4]Instruction.Operand,
22903
22904 const Operand = union(enum) {
22905 regb: u8,
22906 regw: u8,
22907 ereg: u8,
22908 rreg: u8,
22909 xmm: u8,
22910 ymm: u8,
22911 };
22912 };
21840};22913};
21841const SelectOptions = struct {22914const SelectOptions = struct {
21842 cc: ?Condition = null,22915 cc: ?Condition = null,
...@@ -21932,6 +23005,7 @@ fn select(...@@ -21932,6 +23005,7 @@ fn select(
21932 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {23005 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {
21933 const ref_src_op, const is_mut = switch (src_op) {23006 const ref_src_op, const is_mut = switch (src_op) {
21934 .implicit, .explicit => |linked_index| .{ pattern.ops[linked_index], true },23007 .implicit, .explicit => |linked_index| .{ pattern.ops[linked_index], true },
23008 .mut_mem_limb, .mut_gpr_limb => .{ src_op, true },
21935 else => .{ src_op, false },23009 else => .{ src_op, false },
21936 };23010 };
21937 if (!ref_src_op.matches(is_mut, src_temp, cg)) continue :patterns;23011 if (!ref_src_op.matches(is_mut, src_temp, cg)) continue :patterns;
...@@ -21939,7 +23013,7 @@ fn select(...@@ -21939,7 +23013,7 @@ fn select(
2193923013
21940 for (pattern.ops) |op| switch (op) {23014 for (pattern.ops) |op| switch (op) {
21941 else => {},23015 else => {},
21942 .cc_mask_limb,23016 .cc_elem,
21943 .mm_mask_limb,23017 .mm_mask_limb,
21944 .xmm_mask_limb,23018 .xmm_mask_limb,
21945 .ymm_mask_limb,23019 .ymm_mask_limb,
...@@ -21953,16 +23027,16 @@ fn select(...@@ -21953,16 +23027,16 @@ fn select(
21953 .implicit, .explicit => |linked_index| pattern.ops[linked_index],23027 .implicit, .explicit => |linked_index| pattern.ops[linked_index],
21954 else => src_op,23028 else => src_op,
21955 }) {23029 }) {
21956 .implicit, .explicit, .cc, .cc_mask_limb => unreachable,23030 .implicit, .explicit, .cc, .cc_elem => unreachable,
21957 .gpr => try src_temp.toRegClass(.general_purpose, cg),23031 .gpr => try src_temp.toRegClass(true, .general_purpose, cg),
21958 .mm, .mm_mask, .mm_sign_mask => try src_temp.toRegClass(.mmx, cg),23032 .mm, .mm_mask, .mm_sign_mask => try src_temp.toRegClass(true, .mmx, cg),
21959 .xmm,23033 .xmm,
21960 .ymm,23034 .ymm,
21961 .xmm_mask,23035 .xmm_mask,
21962 .ymm_mask,23036 .ymm_mask,
21963 .xmm_sign_mask,23037 .xmm_sign_mask,
21964 .ymm_sign_mask,23038 .ymm_sign_mask,
21965 => try src_temp.toRegClass(.sse, cg),23039 => try src_temp.toRegClass(true, .sse, cg),
21966 .mem => try src_temp.toBase(cg),23040 .mem => try src_temp.toBase(cg),
21967 .imm, .simm32 => false,23041 .imm, .simm32 => false,
21968 .gpr_limb,23042 .gpr_limb,
...@@ -21970,6 +23044,10 @@ fn select(...@@ -21970,6 +23044,10 @@ fn select(
21970 .xmm_limb,23044 .xmm_limb,
21971 .ymm_limb,23045 .ymm_limb,
21972 .mem_limb,23046 .mem_limb,
23047 .mut_gpr_limb,
23048 .mut_mem_limb,
23049 .gpr_elem,
23050 .mem_elem,
21973 => switch (src_temp.tracking(cg).short) {23051 => switch (src_temp.tracking(cg).short) {
21974 .register, .register_pair, .register_triple, .register_quadruple => false,23052 .register, .register_pair, .register_triple, .register_quadruple => false,
21975 else => try src_temp.toBase(cg),23053 else => try src_temp.toBase(cg),
...@@ -21984,7 +23062,7 @@ fn select(...@@ -21984,7 +23062,7 @@ fn select(
21984 var mir_ops_len: usize = 0;23062 var mir_ops_len: usize = 0;
21985 for (pattern.ops[0..dst_temps.len]) |dst_op| switch (dst_op) {23063 for (pattern.ops[0..dst_temps.len]) |dst_op| switch (dst_op) {
21986 else => mir_ops_len += 1,23064 else => mir_ops_len += 1,
21987 .cc, .cc_mask_limb => {},23065 .cc, .cc_elem => {},
21988 };23066 };
21989 const dst_mir_ops_len = mir_ops_len;23067 const dst_mir_ops_len = mir_ops_len;
21990 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {23068 for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| {
...@@ -22001,11 +23079,11 @@ fn select(...@@ -22001,11 +23079,11 @@ fn select(
22001 };23079 };
22002 const limb_size: u8, const rc = switch (linked_src_op) {23080 const limb_size: u8, const rc = switch (linked_src_op) {
22003 else => continue,23081 else => continue,
22004 .gpr_limb => .{ @intCast(@divExact(@as(Memory.Size, switch (pattern_set.scalar) {23082 .gpr_limb, .mut_gpr_limb, .gpr_elem => .{ @intCast(@divExact(Memory.Size.bitSize(switch (pattern_set.scalar) {
22005 .any => .qword,23083 .any => .qword,
22006 .bool => unreachable,23084 .bool => unreachable,
22007 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,23085 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22008 }).bitSize(), 8)), abi.RegisterClass.gp },23086 }), 8)), abi.RegisterClass.gp },
22009 .mm_limb, .mm_mask_limb => .{ 8, @panic("TODO") },23087 .mm_limb, .mm_mask_limb => .{ 8, @panic("TODO") },
22010 .xmm_limb, .xmm_mask_limb => .{ 16, abi.RegisterClass.sse },23088 .xmm_limb, .xmm_mask_limb => .{ 16, abi.RegisterClass.sse },
22011 .ymm_limb, .ymm_mask_limb => .{ 32, abi.RegisterClass.sse },23089 .ymm_limb, .ymm_mask_limb => .{ 32, abi.RegisterClass.sse },
...@@ -22030,7 +23108,10 @@ fn select(...@@ -22030,7 +23108,10 @@ fn select(
22030 .unused, .temp => loop.limb_offset = .{ .known = 0 },23108 .unused, .temp => loop.limb_offset = .{ .known = 0 },
22031 .known => {},23109 .known => {},
22032 }23110 }
22033 if (!rc.isSet(RegisterManager.indexOfRegIntoTracked(src_mcv.getRegs()[0]).?)) {23111 if (switch (linked_src_op) {
23112 .mut_gpr_limb => true,
23113 else => !rc.isSet(RegisterManager.indexOfRegIntoTracked(src_mcv.getRegs()[0]).?),
23114 }) {
22034 if (loop.shuffle_temp == null) loop.shuffle_temp = try cg.tempAllocReg(.noreturn, abi.RegisterClass.sse);23115 if (loop.shuffle_temp == null) loop.shuffle_temp = try cg.tempAllocReg(.noreturn, abi.RegisterClass.sse);
22035 assert(extra_temp.* == null);23116 assert(extra_temp.* == null);
22036 extra_temp.* = try cg.tempAllocReg(.usize, rc);23117 extra_temp.* = try cg.tempAllocReg(.usize, rc);
...@@ -22066,25 +23147,26 @@ fn select(...@@ -22066,25 +23147,26 @@ fn select(
22066 .xmm, .xmm_mask, .xmm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),23147 .xmm, .xmm_mask, .xmm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),
22067 .ymm, .ymm_mask, .ymm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),23148 .ymm, .ymm_mask, .ymm_sign_mask => try cg.tempAllocReg(dst_ty, abi.RegisterClass.sse),
22068 .mem => @panic("TODO"),23149 .mem => @panic("TODO"),
22069 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => {23150 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb, .mut_gpr_limb, .gpr_elem => {
22070 if (extra_temp.* == null) extra_temp.* = try cg.tempAllocReg(.noreturn, switch (dst_op) {23151 if (extra_temp.* == null) extra_temp.* = try cg.tempAllocReg(.noreturn, switch (dst_op) {
22071 else => unreachable,23152 else => unreachable,
22072 .gpr_limb => abi.RegisterClass.gp,23153 .gpr_limb, .mut_gpr_limb, .gpr_elem => abi.RegisterClass.gp,
22073 .mm_limb => @panic("TODO"),23154 .mm_limb => @panic("TODO"),
22074 .xmm_limb, .ymm_limb => abi.RegisterClass.sse,23155 .xmm_limb, .ymm_limb => abi.RegisterClass.sse,
22075 });23156 });
22076 break :dst_temp try cg.tempAlloc(dst_ty);23157 break :dst_temp try cg.tempAlloc(dst_ty);
22077 },23158 },
22078 .mem_limb => try cg.tempAlloc(dst_ty),23159 .mem_limb, .mut_mem_limb, .mem_elem => try cg.tempAlloc(dst_ty),
22079 .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => unreachable, // already checked23160 .cc_elem, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => unreachable, // already checked
22080 .imm, .simm32, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable, // unmodifiable destination23161 .imm, .simm32, .umax_gpr, .umax_mm, .umax_xmm, .umax_ymm => unreachable, // unmodifiable destination
22081 };23162 };
22082 },23163 },
22083 .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {23164 .cc_elem, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {
22084 const scalar_size = @divExact(switch (pattern_set.scalar) {23165 const scalar_size = @divExact(Memory.Size.bitSize(switch (pattern_set.scalar) {
22085 .any, .bool => unreachable,23166 .any => .qword,
23167 .bool => unreachable,
22086 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,23168 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22087 }.bitSize(), 8);23169 }), 8);
22088 const mask_bit_size = @divExact(loop.remaining_size.?, scalar_size);23170 const mask_bit_size = @divExact(loop.remaining_size.?, scalar_size);
22089 const mask_limb_bit_size: u7 = @intCast(@divExact(loop.limb_size.?, scalar_size));23171 const mask_limb_bit_size: u7 = @intCast(@divExact(loop.limb_size.?, scalar_size));
22090 assert(loop.mask_limb_bit_size == null or loop.mask_limb_bit_size == mask_limb_bit_size);23172 assert(loop.mask_limb_bit_size == null or loop.mask_limb_bit_size == mask_limb_bit_size);
...@@ -22104,7 +23186,7 @@ fn select(...@@ -22104,7 +23186,7 @@ fn select(
22104 loop.mask_limb_offset = loop.limb_offset;23186 loop.mask_limb_offset = loop.limb_offset;
22105 if (loop.mask_limb_temp == null) {23187 if (loop.mask_limb_temp == null) {
22106 loop.mask_limb_temp = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);23188 loop.mask_limb_temp = try cg.tempAllocReg(.usize, abi.RegisterClass.gp);
22107 if (dst_op == .cc_mask_limb and mask_store_bit_size > 8) {23189 if (dst_op == .cc_elem and mask_store_bit_size > 8) {
22108 // setcc only clears 8 bits23190 // setcc only clears 8 bits
22109 const mask_limb_alias = loop.mask_limb_temp.?.tracking(cg).short.register.to32();23191 const mask_limb_alias = loop.mask_limb_temp.?.tracking(cg).short.register.to32();
22110 try cg.spillEflagsIfOccupied();23192 try cg.spillEflagsIfOccupied();
...@@ -22195,6 +23277,8 @@ fn select(...@@ -22195,6 +23277,8 @@ fn select(
22195 .mm_limb,23277 .mm_limb,
22196 .xmm_limb,23278 .xmm_limb,
22197 .ymm_limb,23279 .ymm_limb,
23280 .mut_gpr_limb,
23281 .gpr_elem,
22198 .mm_mask_limb,23282 .mm_mask_limb,
22199 .xmm_mask_limb,23283 .xmm_mask_limb,
22200 .ymm_mask_limb,23284 .ymm_mask_limb,
...@@ -22304,7 +23388,7 @@ fn select(...@@ -22304,7 +23388,7 @@ fn select(
22304 else => try cg.asmRegisterMemory(23388 else => try cg.asmRegisterMemory(
22305 switch (linked_src_op) {23389 switch (linked_src_op) {
22306 else => unreachable,23390 else => unreachable,
22307 .gpr_limb => .{ ._, .mov },23391 .gpr_limb, .mut_gpr_limb, .gpr_elem => .{ ._, .mov },
22308 .mm_limb, .mm_mask_limb => .{ ._q, .mov },23392 .mm_limb, .mm_mask_limb => .{ ._q, .mov },
22309 .xmm_limb,23393 .xmm_limb,
22310 .ymm_limb,23394 .ymm_limb,
...@@ -22328,7 +23412,7 @@ fn select(...@@ -22328,7 +23412,7 @@ fn select(
22328 },23412 },
22329 }23413 }
22330 mir_op.* = switch (linked_src_op) {23414 mir_op.* = switch (linked_src_op) {
22331 .implicit, .explicit, .cc, .cc_mask_limb => unreachable,23415 .implicit, .explicit, .cc, .cc_elem => unreachable,
22332 .gpr => .{ .reg = registerAlias(23416 .gpr => .{ .reg = registerAlias(
22333 src_mcv.register,23417 src_mcv.register,
22334 @intCast(src_temp.typeOf(cg).abiSize(cg.pt.zcu)),23418 @intCast(src_temp.typeOf(cg).abiSize(cg.pt.zcu)),
...@@ -22342,6 +23426,8 @@ fn select(...@@ -22342,6 +23426,8 @@ fn select(
22342 .mm_limb,23426 .mm_limb,
22343 .xmm_limb,23427 .xmm_limb,
22344 .ymm_limb,23428 .ymm_limb,
23429 .mut_gpr_limb,
23430 .gpr_elem,
22345 .mm_mask_limb,23431 .mm_mask_limb,
22346 .xmm_mask_limb,23432 .xmm_mask_limb,
22347 .ymm_mask_limb,23433 .ymm_mask_limb,
...@@ -22349,7 +23435,7 @@ fn select(...@@ -22349,7 +23435,7 @@ fn select(
22349 limb_temp.tracking(cg).short.register23435 limb_temp.tracking(cg).short.register
22350 else23436 else
22351 src_mcv.getRegs()[@divExact(loop.limb_offset.known, loop.limb_size.?)], loop.limb_size.?) },23437 src_mcv.getRegs()[@divExact(loop.limb_offset.known, loop.limb_size.?)], loop.limb_size.?) },
22352 .mem_limb => .{ .mem = switch (src_mcv) {23438 .mem_limb, .mut_mem_limb, .mem_elem => .{ .mem = switch (src_mcv) {
22353 .register, .register_pair, .register_triple, .register_quadruple => unreachable,23439 .register, .register_pair, .register_triple, .register_quadruple => unreachable,
22354 else => switch (loop.limb_offset) {23440 else => switch (loop.limb_offset) {
22355 .unused => unreachable,23441 .unused => unreachable,
...@@ -22394,7 +23480,7 @@ fn select(...@@ -22394,7 +23480,7 @@ fn select(
22394 ) |*mir_op, dst_op, dst_temp, dst_ty, extra_temp| {23480 ) |*mir_op, dst_op, dst_temp, dst_ty, extra_temp| {
22395 if (mir_op.* != .none) continue;23481 if (mir_op.* != .none) continue;
22396 mir_op.* = switch (dst_op) {23482 mir_op.* = switch (dst_op) {
22397 .implicit, .cc, .cc_mask_limb => unreachable,23483 .implicit, .cc, .cc_elem => unreachable,
22398 .explicit => |linked_index| mir_ops[linked_index],23484 .explicit => |linked_index| mir_ops[linked_index],
22399 .gpr => .{ .reg = registerAlias(23485 .gpr => .{ .reg = registerAlias(
22400 dst_temp.tracking(cg).short.register,23486 dst_temp.tracking(cg).short.register,
...@@ -22404,18 +23490,18 @@ fn select(...@@ -22404,18 +23490,18 @@ fn select(
22404 .xmm, .xmm_mask, .xmm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to128() },23490 .xmm, .xmm_mask, .xmm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to128() },
22405 .ymm, .ymm_mask, .ymm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to256() },23491 .ymm, .ymm_mask, .ymm_sign_mask => .{ .reg = dst_temp.tracking(cg).short.register.to256() },
22406 .mem => @panic("TODO"),23492 .mem => @panic("TODO"),
22407 .gpr_limb => .{ .reg = registerAlias(23493 .gpr_limb, .mut_gpr_limb, .gpr_elem => .{ .reg = registerAlias(
22408 extra_temp.?.tracking(cg).short.register,23494 extra_temp.?.tracking(cg).short.register,
22409 @intCast(@divExact(@as(Memory.Size, switch (pattern_set.scalar) {23495 @intCast(@divExact(Memory.Size.bitSize(switch (pattern_set.scalar) {
22410 .any => .qword,23496 .any => .qword,
22411 .bool => unreachable,23497 .bool => unreachable,
22412 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,23498 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22413 }).bitSize(), 8)),23499 }), 8)),
22414 ) },23500 ) },
22415 .mm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register },23501 .mm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register },
22416 .xmm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to128() },23502 .xmm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to128() },
22417 .ymm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to256() },23503 .ymm_limb => .{ .reg = extra_temp.?.tracking(cg).short.register.to256() },
22418 .mem_limb => .{ .mem = try dst_temp.tracking(cg).short.mem(cg, switch (loop.limb_offset) {23504 .mem_limb, .mut_mem_limb, .mem_elem => .{ .mem = try dst_temp.tracking(cg).short.mem(cg, switch (loop.limb_offset) {
22419 .unused => unreachable,23505 .unused => unreachable,
22420 .known => |limb_offset| .{23506 .known => |limb_offset| .{
22421 .size = .fromSize(loop.limb_size.?),23507 .size = .fromSize(loop.limb_size.?),
...@@ -22434,7 +23520,11 @@ fn select(...@@ -22434,7 +23520,11 @@ fn select(
22434 }23520 }
22435 std.mem.swap(Operand, &mir_ops[pattern.commute[0]], &mir_ops[pattern.commute[1]]);23521 std.mem.swap(Operand, &mir_ops[pattern.commute[0]], &mir_ops[pattern.commute[1]]);
22436 if (pattern_set.clobbers.eflags) try cg.spillEflagsIfOccupied();23522 if (pattern_set.clobbers.eflags) try cg.spillEflagsIfOccupied();
22437 cg.asmOps(pattern_set.mir_tag, mir_ops) catch |err| switch (err) {23523 cg.asmOps((if (loop.remaining_size != null and loop.limb_size != null and
23524 loop.remaining_size.? <= loop.limb_size.?)
23525 pattern_set.final_mir_tag
23526 else
23527 null) orelse pattern_set.mir_tag, mir_ops) catch |err| switch (err) {
22438 error.InvalidInstruction => {23528 error.InvalidInstruction => {
22439 const fixes = @tagName(pattern_set.mir_tag[0]);23529 const fixes = @tagName(pattern_set.mir_tag[0]);
22440 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;23530 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
...@@ -22478,15 +23568,19 @@ fn select(...@@ -22478,15 +23568,19 @@ fn select(
22478 .mm_sign_mask,23568 .mm_sign_mask,
22479 .xmm_sign_mask,23569 .xmm_sign_mask,
22480 .ymm_sign_mask,23570 .ymm_sign_mask,
22481 => dst_temp.asMask(switch (dst_op) {23571 => dst_temp.asMask(.{
22482 else => unreachable,23572 .kind = switch (dst_op) {
22483 .mm_mask, .xmm_mask, .ymm_mask => .all,23573 else => unreachable,
22484 .mm_sign_mask, .xmm_sign_mask, .ymm_sign_mask => .sign,23574 .mm_mask, .xmm_mask, .ymm_mask => .all,
22485 }, invert_result, switch (pattern_set.scalar) {23575 .mm_sign_mask, .xmm_sign_mask, .ymm_sign_mask => .sign,
22486 .any, .bool => unreachable,23576 },
22487 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,23577 .inverted = invert_result,
23578 .scalar = switch (pattern_set.scalar) {
23579 .any, .bool => unreachable,
23580 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
23581 },
22488 }, cg),23582 }, cg),
22489 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => if (extra_temp) |limb_temp| {23583 .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb, .mut_gpr_limb, .gpr_elem => if (extra_temp) |limb_temp| {
22490 const dst_mcv = dst_temp.tracking(cg).short;23584 const dst_mcv = dst_temp.tracking(cg).short;
22491 switch (dst_mcv) {23585 switch (dst_mcv) {
22492 .register_pair, .register_triple, .register_quadruple => try cg.asmRegisterRegister(23586 .register_pair, .register_triple, .register_quadruple => try cg.asmRegisterRegister(
...@@ -22497,7 +23591,7 @@ fn select(...@@ -22497,7 +23591,7 @@ fn select(
22497 else => try cg.asmMemoryRegister(23591 else => try cg.asmMemoryRegister(
22498 switch (dst_op) {23592 switch (dst_op) {
22499 else => unreachable,23593 else => unreachable,
22500 .gpr_limb => .{ ._, .mov },23594 .gpr_limb, .mut_gpr_limb, .gpr_elem => .{ ._, .mov },
22501 .mm_limb => .{ ._q, .mov },23595 .mm_limb => .{ ._q, .mov },
22502 .xmm_limb, .ymm_limb => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu },23596 .xmm_limb, .ymm_limb => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu },
22503 },23597 },
...@@ -22516,9 +23610,10 @@ fn select(...@@ -22516,9 +23610,10 @@ fn select(
22516 ),23610 ),
22517 }23611 }
22518 },23612 },
22519 .cc_mask_limb, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {23613 .cc_elem, .mm_mask_limb, .xmm_mask_limb, .ymm_mask_limb => {
22520 const scalar_size = switch (pattern_set.scalar) {23614 const scalar_size = switch (pattern_set.scalar) {
22521 .any, .bool => unreachable,23615 .any => .qword,
23616 .bool => unreachable,
22522 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,23617 .float, .any_int, .signed_int, .unsigned_int, .any_float_or_int => |size| size,
22523 };23618 };
22524 const mask_store_size: u4 =23619 const mask_store_size: u4 =
...@@ -22534,7 +23629,7 @@ fn select(...@@ -22534,7 +23629,7 @@ fn select(
22534 loop.mask_store_reg.?, mask_store_size);23629 loop.mask_store_reg.?, mask_store_size);
22535 switch (dst_op) {23630 switch (dst_op) {
22536 else => unreachable,23631 else => unreachable,
22537 .cc_mask_limb => try cg.asmSetccRegister(switch (invert_result) {23632 .cc_elem => try cg.asmSetccRegister(switch (invert_result) {
22538 false => opts.cc.?,23633 false => opts.cc.?,
22539 true => opts.cc.?.negate(),23634 true => opts.cc.?.negate(),
22540 }, mask_limb_reg.to8()),23635 }, mask_limb_reg.to8()),
...@@ -22678,6 +23773,7 @@ fn select(...@@ -22678,6 +23773,7 @@ fn select(
22678 .once => break :pattern_sets,23773 .once => break :pattern_sets,
22679 .bitwise => {},23774 .bitwise => {},
22680 .limbwise_carry => @panic("TODO"),23775 .limbwise_carry => @panic("TODO"),
23776 .limbwise_reduce => @panic("TODO"),
22681 .limbwise_pairs_forward => @panic("TODO"),23777 .limbwise_pairs_forward => @panic("TODO"),
22682 .limbwise_pairs_reverse => @panic("TODO"),23778 .limbwise_pairs_reverse => @panic("TODO"),
22683 .elementwise => {},23779 .elementwise => {},
...@@ -22743,9 +23839,433 @@ fn select(...@@ -22743,9 +23839,433 @@ fn select(
22743 }23839 }
22744 }23840 }
22745 } else {23841 } else {
22746 log.err("failed to select:", .{});23842 log.err("failed to select {s}:", .{@tagName(pattern_sets[0].mir_tag[1])});
22747 for (src_temps) |src_temp| log.err("{}", .{src_temp.tracking(cg)});23843 for (src_temps) |src_temp| log.err("{}", .{src_temp.tracking(cg)});
22748 return cg.fail("failed to select", .{});23844 return error.SelectFailed;
22749 }23845 }
22750 for (extra_temps) |extra_temp| if (extra_temp) |temp| try temp.die(cg);23846 for (extra_temps) |extra_temp| if (extra_temp) |temp| try temp.die(cg);
22751}23847}
23848
23849const Select2 = struct {
23850 cg: *CodeGen,
23851 case: *const Case,
23852 pattern: *const Select2.Pattern,
23853 extra_temps: [3]Temp,
23854 dst_temps: []const Temp,
23855 src_temps: []const Temp,
23856 commute: struct { u8, u8 },
23857 limb: Memory.Mod.Rm,
23858
23859 fn emit(s: Select2, inst: Instruction) !void {
23860 const mir_tag: Mir.Inst.FixedTag = .{ inst[0], inst[1] };
23861 var mir_ops: [4]CodeGen.Operand = undefined;
23862 inline for (&mir_ops, 2..) |*mir_op, inst_index| mir_op.* = try inst[inst_index].lower(s);
23863 s.cg.asmOps(mir_tag, mir_ops) catch |err| switch (err) {
23864 error.InvalidInstruction => {
23865 const fixes = @tagName(mir_tag[0]);
23866 const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
23867 return s.cg.fail(
23868 "invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'",
23869 .{
23870 fixes[0..fixes_blank],
23871 @tagName(mir_tag[1]),
23872 fixes[fixes_blank + 1 ..],
23873 @tagName(mir_ops[0]),
23874 @tagName(mir_ops[1]),
23875 @tagName(mir_ops[2]),
23876 @tagName(mir_ops[3]),
23877 },
23878 );
23879 },
23880 else => |e| return e,
23881 };
23882 }
23883
23884 fn lowerLimb(s: Select2, temp: Temp) !CodeGen.Operand {
23885 return .{ .mem = try temp.tracking(s.cg).short.mem(s.cg, s.limb) };
23886 }
23887
23888 fn srcTemp(s: Select2, index: u8) Temp {
23889 return s.src_temps[
23890 if (index == s.commute[0])
23891 s.commute[1]
23892 else if (index == s.commute[1])
23893 s.commute[0]
23894 else
23895 index
23896 ];
23897 }
23898
23899 const Case = struct {
23900 required_features: [2]?std.Target.x86.Feature = @splat(null),
23901 constraints: [2]Constraint = @splat(.any),
23902 patterns: []const Select2.Pattern,
23903 clobbers: struct { eflags: bool = false } = .{},
23904 extra_temps: [3]TempSpec = @splat(.unused),
23905 dst_temps: [1]TempSpec.Kind = @splat(.unused),
23906 each: union(enum) {
23907 once: []const Instruction,
23908 limb: struct {
23909 of: Select2.Operand,
23910 header: []const Instruction = &.{},
23911 first: ?[]const Instruction = null,
23912 body: []const Instruction,
23913 last: ?[]const Instruction = null,
23914 trailer: []const Instruction = &.{},
23915 },
23916 },
23917 };
23918
23919 const Constraint = union(enum) {
23920 any,
23921 any_int,
23922 any_float,
23923 bool_vec: Memory.Size,
23924 int: Memory.Size,
23925 signed_int: Memory.Size,
23926 unsigned_int: Memory.Size,
23927
23928 fn accepts(constraint: Constraint, temp: Temp, cg: *CodeGen) bool {
23929 const zcu = cg.pt.zcu;
23930 switch (constraint) {
23931 .any => return true,
23932 .any_int => {
23933 const scalar_ty = temp.typeOf(cg).scalarType(zcu);
23934 return scalar_ty.isAbiInt(zcu) or scalar_ty.isPtrAtRuntime(zcu);
23935 },
23936 .any_float => return temp.typeOf(cg).scalarType(zcu).isRuntimeFloat(),
23937 .bool_vec => |size| {
23938 const ty = temp.typeOf(cg);
23939 return ty.isVector(zcu) and ty.scalarType(zcu).toIntern() == .bool_type and
23940 ty.vectorLen(zcu) <= size.bitSize();
23941 },
23942 .int => |size| {
23943 const scalar_ty = temp.typeOf(cg).scalarType(zcu);
23944 if (scalar_ty.isPtrAtRuntime(zcu)) return cg.target.ptrBitWidth() <= size.bitSize();
23945 return scalar_ty.isAbiInt(zcu) and scalar_ty.intInfo(zcu).bits <= size.bitSize();
23946 },
23947 .signed_int => |size| {
23948 const scalar_ty = temp.typeOf(cg).scalarType(zcu);
23949 if (!scalar_ty.isAbiInt(zcu)) return false;
23950 const info = scalar_ty.intInfo(zcu);
23951 return info.signedness == .signed and info.bits <= size.bitSize();
23952 },
23953 .unsigned_int => |size| {
23954 const scalar_ty = temp.typeOf(cg).scalarType(zcu);
23955 if (scalar_ty.isPtrAtRuntime(zcu)) return cg.target.ptrBitWidth() <= size.bitSize();
23956 if (!scalar_ty.isAbiInt(zcu)) return false;
23957 const info = scalar_ty.intInfo(zcu);
23958 return info.signedness == .unsigned and info.bits <= size.bitSize();
23959 },
23960 }
23961 }
23962 };
23963
23964 const Pattern = struct {
23965 src: [2]Src,
23966 commute: struct { u8, u8 } = .{ 0, 0 },
23967
23968 const Src = enum {
23969 none,
23970 any,
23971 imm8,
23972 imm16,
23973 imm32,
23974 simm32,
23975 mem,
23976 mut_mem,
23977 to_mem,
23978 gpr,
23979 mut_gpr,
23980 mm,
23981 mut_mm,
23982 xmm,
23983 mut_xmm,
23984 ymm,
23985 mut_ymm,
23986
23987 fn matches(src: Src, temp: Temp, cg: *CodeGen) bool {
23988 switch (src) {
23989 .none => unreachable,
23990 .any => return true,
23991 .imm8 => return switch (temp.tracking(cg).short) {
23992 .immediate => |imm| std.math.cast(u8, imm) != null,
23993 else => false,
23994 },
23995 .imm16 => return switch (temp.tracking(cg).short) {
23996 .immediate => |imm| std.math.cast(u16, imm) != null,
23997 else => false,
23998 },
23999 .imm32 => return switch (temp.tracking(cg).short) {
24000 .immediate => |imm| std.math.cast(u32, imm) != null,
24001 else => false,
24002 },
24003 .simm32 => return switch (temp.tracking(cg).short) {
24004 .immediate => |imm| std.math.cast(i32, @as(i64, @bitCast(imm))) != null,
24005 else => false,
24006 },
24007 .mem => return temp.tracking(cg).short.isMemory(),
24008 .mut_mem => return temp.isMut(cg) and temp.tracking(cg).short.isMemory(),
24009 .to_mem => return true,
24010 .gpr, .mut_gpr => {
24011 const mcv = temp.tracking(cg).short;
24012 const abi_size = temp.typeOf(cg).abiSize(cg.pt.zcu);
24013 return abi_size <= 8 and switch (mcv) {
24014 .register => |reg| reg.class() == .general_purpose,
24015 .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and
24016 reg_off.off == 0,
24017 .register_pair, .register_triple, .register_quadruple => false,
24018 else => true,
24019 };
24020 },
24021 .mm, .mut_mm => {
24022 const mcv = temp.tracking(cg).short;
24023 const abi_size = temp.typeOf(cg).abiSize(cg.pt.zcu);
24024 return abi_size <= 8 and switch (mcv) {
24025 .register => |reg| reg.class() == .mmx,
24026 .register_offset => |reg_off| reg_off.reg.class() == .mmx and
24027 reg_off.off == 0,
24028 else => false,
24029 };
24030 },
24031 .xmm, .mut_xmm => {
24032 const mcv = temp.tracking(cg).short;
24033 const abi_size = temp.typeOf(cg).abiSize(cg.pt.zcu);
24034 return abi_size > 8 and abi_size <= 16 and switch (mcv) {
24035 .register => |reg| reg.class() == .sse,
24036 .register_offset => |reg_off| reg_off.reg.class() == .sse and
24037 reg_off.off == 0,
24038 .register_pair, .register_triple, .register_quadruple => false,
24039 else => true,
24040 };
24041 },
24042 .ymm, .mut_ymm => {
24043 const mcv = temp.tracking(cg).short;
24044 const abi_size = temp.typeOf(cg).abiSize(cg.pt.zcu);
24045 return abi_size > 16 and abi_size <= 32 and switch (mcv) {
24046 .register => |reg| reg.class() == .sse,
24047 .register_offset => |reg_off| reg_off.reg.class() == .sse and
24048 reg_off.off == 0,
24049 .register_pair, .register_triple, .register_quadruple => false,
24050 else => true,
24051 };
24052 },
24053 }
24054 }
24055
24056 fn convert(src: Src, temp: *Temp, cg: *CodeGen) !bool {
24057 return switch (src) {
24058 .none => unreachable,
24059 .any, .imm8, .imm16, .imm32, .simm32 => false,
24060 .mem, .mut_mem, .to_mem => try temp.toBase(cg),
24061 .gpr => try temp.toRegClass(false, .general_purpose, cg),
24062 .mut_gpr => try temp.toRegClass(true, .general_purpose, cg),
24063 .mm => try temp.toRegClass(false, .mmx, cg),
24064 .mut_mm => try temp.toRegClass(true, .mmx, cg),
24065 .xmm, .ymm => try temp.toRegClass(false, .sse, cg),
24066 .mut_xmm, .mut_ymm => try temp.toRegClass(true, .sse, cg),
24067 };
24068 }
24069 };
24070 };
24071
24072 const TempSpec = struct {
24073 type: Type = .noreturn,
24074 kind: Kind,
24075
24076 const unused: TempSpec = .{ .kind = .unused };
24077
24078 const Kind = union(enum) {
24079 unused,
24080 any,
24081 cc: Condition,
24082 reg: Register,
24083 rc: Register.Class,
24084 rc_mask: struct { rc: Register.Class, info: MaskInfo },
24085 mem,
24086 src: u8,
24087 src_mask: struct { src: u8, info: MaskInfo },
24088
24089 fn finish(kind: Kind, temp: Temp, s: Select2) void {
24090 switch (kind) {
24091 else => {},
24092 inline .rc_mask, .src_mask => |mask| temp.asMask(mask.info, s.cg),
24093 }
24094 }
24095 };
24096
24097 fn create(spec: TempSpec, s: Select2) !?Temp {
24098 return switch (spec.kind) {
24099 .unused => null,
24100 .any => try s.cg.tempAlloc(spec.type),
24101 .cc => |cc| try s.cg.tempFromValue(spec.type, .{ .eflags = cc }),
24102 .reg => |reg| try s.cg.tempFromValue(spec.type, .{ .register = reg }),
24103 .rc => |rc| try s.cg.tempAllocReg(spec.type, regSetForRegClass(rc)),
24104 .rc_mask => |mask| try s.cg.tempAllocReg(spec.type, regSetForRegClass(mask.rc)),
24105 .mem => try s.cg.tempAllocMem(spec.type),
24106 .src => |src| s.srcTemp(src),
24107 .src_mask => |mask| s.srcTemp(mask.src),
24108 };
24109 }
24110 };
24111
24112 const Instruction = struct {
24113 Mir.Inst.Fixes,
24114 Mir.Inst.Tag,
24115 Select2.Operand,
24116 Select2.Operand,
24117 Select2.Operand,
24118 Select2.Operand,
24119 };
24120 const Operand = union(enum) {
24121 none,
24122 extra: struct { Memory.Size, u8 },
24123 dst: struct { Memory.Size, u8 },
24124 src: struct { Memory.Size, u8 },
24125 dst_limb: u8,
24126 src_limb: u8,
24127 simm32: i32,
24128
24129 const tmp0b: Select2.Operand = .{ .extra = .{ .byte, 0 } };
24130 const tmp0w: Select2.Operand = .{ .extra = .{ .word, 0 } };
24131 const etmp0: Select2.Operand = .{ .extra = .{ .dword, 0 } };
24132 const rtmp0: Select2.Operand = .{ .extra = .{ .qword, 0 } };
24133 const xtmp0: Select2.Operand = .{ .extra = .{ .xword, 0 } };
24134 const ytmp0: Select2.Operand = .{ .extra = .{ .yword, 0 } };
24135
24136 const tmp1b: Select2.Operand = .{ .extra = .{ .byte, 1 } };
24137 const tmp1w: Select2.Operand = .{ .extra = .{ .word, 1 } };
24138 const etmp1: Select2.Operand = .{ .extra = .{ .dword, 1 } };
24139 const rtmp1: Select2.Operand = .{ .extra = .{ .qword, 1 } };
24140 const xtmp1: Select2.Operand = .{ .extra = .{ .xword, 1 } };
24141 const ytmp1: Select2.Operand = .{ .extra = .{ .yword, 1 } };
24142
24143 const tmp2b: Select2.Operand = .{ .extra = .{ .byte, 2 } };
24144 const tmp2w: Select2.Operand = .{ .extra = .{ .word, 2 } };
24145 const etmp2: Select2.Operand = .{ .extra = .{ .dword, 2 } };
24146 const rtmp2: Select2.Operand = .{ .extra = .{ .qword, 2 } };
24147 const xtmp2: Select2.Operand = .{ .extra = .{ .xword, 2 } };
24148 const ytmp2: Select2.Operand = .{ .extra = .{ .yword, 2 } };
24149
24150 const dst0b: Select2.Operand = .{ .dst = .{ .byte, 0 } };
24151 const dst0w: Select2.Operand = .{ .dst = .{ .word, 0 } };
24152 const edst0: Select2.Operand = .{ .dst = .{ .dword, 0 } };
24153 const rdst0: Select2.Operand = .{ .dst = .{ .qword, 0 } };
24154 const xdst0: Select2.Operand = .{ .dst = .{ .xword, 0 } };
24155 const ydst0: Select2.Operand = .{ .dst = .{ .yword, 0 } };
24156
24157 const src0b: Select2.Operand = .{ .src = .{ .byte, 0 } };
24158 const src0w: Select2.Operand = .{ .src = .{ .word, 0 } };
24159 const esrc0: Select2.Operand = .{ .src = .{ .dword, 0 } };
24160 const rsrc0: Select2.Operand = .{ .src = .{ .qword, 0 } };
24161 const xsrc0: Select2.Operand = .{ .src = .{ .xword, 0 } };
24162 const ysrc0: Select2.Operand = .{ .src = .{ .yword, 0 } };
24163
24164 const src1b: Select2.Operand = .{ .src = .{ .byte, 1 } };
24165 const src1w: Select2.Operand = .{ .src = .{ .word, 1 } };
24166 const esrc1: Select2.Operand = .{ .src = .{ .dword, 1 } };
24167 const rsrc1: Select2.Operand = .{ .src = .{ .qword, 1 } };
24168 const xsrc1: Select2.Operand = .{ .src = .{ .xword, 1 } };
24169 const ysrc1: Select2.Operand = .{ .src = .{ .yword, 1 } };
24170
24171 fn unwrap(op: Select2.Operand, s: Select2) struct { Memory.Size, Temp } {
24172 return switch (op) {
24173 else => unreachable,
24174 .extra => |extra| .{ extra[0], s.extra_temps[extra[1]] },
24175 .dst => |dst| .{ dst[0], s.dst_temps[dst[1]] },
24176 .src => |src| .{ src[0], s.srcTemp(src[1]) },
24177 };
24178 }
24179
24180 fn lower(op: Select2.Operand, s: Select2) !CodeGen.Operand {
24181 switch (op) {
24182 .none => return .none,
24183 else => {},
24184 .dst_limb => |dst| return s.lowerLimb(s.dst_temps[dst]),
24185 .src_limb => |src| return s.lowerLimb(s.srcTemp(src)),
24186 .simm32 => |imm| return .{ .imm = .s(imm) },
24187 }
24188 const size, const temp = op.unwrap(s);
24189 return switch (temp.tracking(s.cg).short) {
24190 .immediate => |imm| .{ .imm = switch (size) {
24191 .byte => if (std.math.cast(i8, @as(i64, @bitCast(imm)))) |simm| .s(simm) else .u(@as(u8, @intCast(imm))),
24192 .word => if (std.math.cast(i16, @as(i64, @bitCast(imm)))) |simm| .s(simm) else .u(@as(u16, @intCast(imm))),
24193 .dword => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |simm| .s(simm) else .u(@as(u32, @intCast(imm))),
24194 .qword => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |simm| .s(simm) else .u(imm),
24195 else => unreachable,
24196 } },
24197 else => |mcv| .{ .mem = try mcv.mem(s.cg, .{ .size = size }) },
24198 .register => |reg| .{ .reg = registerAlias(reg, @intCast(@divExact(size.bitSize(), 8))) },
24199 };
24200 }
24201 };
24202};
24203fn select2(
24204 cg: *CodeGen,
24205 dst_temps: []Temp,
24206 dst_tys: []const Type,
24207 src_temps: []Temp,
24208 cases: []const Select2.Case,
24209) !void {
24210 cases: for (cases) |*case| {
24211 for (case.required_features) |required_feature| if (required_feature) |feature| if (!switch (feature) {
24212 .@"64bit" => cg.target.cpu.arch == .x86_64,
24213 .mmx => false,
24214 else => cg.hasFeature(feature),
24215 }) continue :cases;
24216 for (case.constraints[0..src_temps.len], src_temps) |src_constraint, src_temp| if (!src_constraint.accepts(src_temp, cg)) continue :cases;
24217 patterns: for (case.patterns) |*pattern| {
24218 for (pattern.src, src_temps) |src_pattern, src_temp| if (!src_pattern.matches(src_temp, cg)) continue :patterns;
24219
24220 var s: Select2 = .{
24221 .cg = cg,
24222 .case = case,
24223 .pattern = pattern,
24224 .extra_temps = undefined,
24225 .dst_temps = dst_temps,
24226 .src_temps = src_temps,
24227 .commute = pattern.commute,
24228 .limb = undefined,
24229 };
24230 for (&s.extra_temps, case.extra_temps) |*temp, spec| temp.* = try spec.create(s) orelse continue;
24231
24232 while (true) for (pattern.src, src_temps) |src_pattern, *src_temp| {
24233 if (try src_pattern.convert(src_temp, cg)) break;
24234 } else break;
24235
24236 if (case.clobbers.eflags or case.each != .once) try cg.spillEflagsIfOccupied();
24237
24238 for (dst_temps, dst_tys, case.dst_temps[0..dst_temps.len]) |*dst_temp, dst_ty, dst_kind|
24239 dst_temp.* = (try Select2.TempSpec.create(.{ .type = dst_ty, .kind = dst_kind }, s)).?;
24240
24241 switch (case.each) {
24242 .once => |body| for (body) |inst| try s.emit(inst),
24243 .limb => |limb| {
24244 const limb_size, const limb_of_temp = limb.of.unwrap(s);
24245 const limb_of_size: u31 = @intCast(limb_of_temp.typeOf(cg).abiSize(cg.pt.zcu));
24246 s.limb = .{
24247 .size = limb_size,
24248 .index = s.extra_temps[0].tracking(cg).short.register.to64(),
24249 .disp = limb_of_size,
24250 };
24251 for (limb.header) |inst| try s.emit(inst);
24252 try cg.asmRegisterImmediate(.{ ._, .mov }, s.limb.index, .s(-@as(i32, limb_of_size)));
24253 const limb_loop_reloc: u32 = @intCast(cg.mir_instructions.len);
24254 for (limb.body) |inst| try s.emit(inst);
24255 try cg.asmRegisterImmediate(
24256 .{ ._, .add },
24257 s.limb.index,
24258 .s(@intCast(@divExact(limb_size.bitSize(), 8))),
24259 );
24260 _ = try cg.asmJccReloc(.nc, limb_loop_reloc);
24261 for (limb.trailer) |inst| try s.emit(inst);
24262 },
24263 }
24264
24265 for (dst_temps, case.dst_temps[0..dst_temps.len]) |dst_temp, dst_kind| dst_kind.finish(dst_temp, s);
24266 for (case.extra_temps, s.extra_temps) |spec, temp| if (spec.kind != .unused) try temp.die(cg);
24267 return;
24268 }
24269 }
24270 return error.Select2Failed;
24271}
src/arch/x86_64/Encoding.zig+3
...@@ -353,6 +353,7 @@ pub const Mnemonic = enum {...@@ -353,6 +353,7 @@ pub const Mnemonic = enum {
353 pmovsxbd, pmovsxbq, pmovsxbw, pmovsxdq, pmovsxwd, pmovsxwq,353 pmovsxbd, pmovsxbq, pmovsxbw, pmovsxdq, pmovsxwd, pmovsxwq,
354 pmovzxbd, pmovzxbq, pmovzxbw, pmovzxdq, pmovzxwd, pmovzxwq,354 pmovzxbd, pmovzxbq, pmovzxbw, pmovzxdq, pmovzxwd, pmovzxwq,
355 pmulld,355 pmulld,
356 ptest,
356 roundpd, roundps, roundsd, roundss,357 roundpd, roundps, roundsd, roundss,
357 // SSE4.2358 // SSE4.2
358 pcmpgtq,359 pcmpgtq,
...@@ -413,6 +414,7 @@ pub const Mnemonic = enum {...@@ -413,6 +414,7 @@ pub const Mnemonic = enum {
413 vpsrad, vpsraq, vpsraw,414 vpsrad, vpsraq, vpsraw,
414 vpsrld, vpsrldq, vpsrlq, vpsrlw,415 vpsrld, vpsrldq, vpsrlq, vpsrlw,
415 vpsubb, vpsubd, vpsubq, vpsubsb, vpsubsw, vpsubusb, vpsubusw, vpsubw,416 vpsubb, vpsubd, vpsubq, vpsubsb, vpsubsw, vpsubusb, vpsubusw, vpsubw,
417 vptest,
416 vpunpckhbw, vpunpckhdq, vpunpckhqdq, vpunpckhwd,418 vpunpckhbw, vpunpckhdq, vpunpckhqdq, vpunpckhwd,
417 vpunpcklbw, vpunpckldq, vpunpcklqdq, vpunpcklwd,419 vpunpcklbw, vpunpckldq, vpunpcklqdq, vpunpcklwd,
418 vpxor,420 vpxor,
...@@ -421,6 +423,7 @@ pub const Mnemonic = enum {...@@ -421,6 +423,7 @@ pub const Mnemonic = enum {
421 vsqrtpd, vsqrtps, vsqrtsd, vsqrtss,423 vsqrtpd, vsqrtps, vsqrtsd, vsqrtss,
422 vstmxcsr,424 vstmxcsr,
423 vsubpd, vsubps, vsubsd, vsubss,425 vsubpd, vsubps, vsubsd, vsubss,
426 vtestpd, vtestps,
424 vxorpd, vxorps,427 vxorpd, vxorps,
425 // F16C428 // F16C
426 vcvtph2ps, vcvtps2ph,429 vcvtph2ps, vcvtps2ph,
src/arch/x86_64/bits.zig+25
...@@ -150,6 +150,31 @@ pub const Condition = enum(u5) {...@@ -150,6 +150,31 @@ pub const Condition = enum(u5) {
150 .nz_or_p => .z_and_np,150 .nz_or_p => .z_and_np,
151 };151 };
152 }152 }
153
154 /// Returns the equivalent condition when the operands are swapped.
155 pub fn commute(cond: Condition) Condition {
156 return switch (cond) {
157 else => cond,
158 .a => .b,
159 .ae => .be,
160 .b => .a,
161 .be => .ae,
162 .c => .a,
163 .g => .l,
164 .ge => .le,
165 .l => .g,
166 .le => .ge,
167 .na => .nb,
168 .nae => .nbe,
169 .nb => .na,
170 .nbe => .nae,
171 .nc => .na,
172 .ng => .nl,
173 .nge => .nle,
174 .nl => .ng,
175 .nle => .nge,
176 };
177 }
153};178};
154179
155pub const Register = enum(u7) {180pub const Register = enum(u7) {
src/arch/x86_64/encodings.zig+10
...@@ -1251,6 +1251,8 @@ pub const table = [_]Entry{...@@ -1251,6 +1251,8 @@ pub const table = [_]Entry{
12511251
1252 .{ .pmulld, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x40 }, 0, .none, .sse4_1 },1252 .{ .pmulld, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x40 }, 0, .none, .sse4_1 },
12531253
1254 .{ .ptest, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x17 }, 0, .none, .sse4_1 },
1255
1254 .{ .roundpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .none, .sse4_1 },1256 .{ .roundpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .none, .sse4_1 },
12551257
1256 .{ .roundps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x08 }, 0, .none, .sse4_1 },1258 .{ .roundps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x08 }, 0, .none, .sse4_1 },
...@@ -1676,6 +1678,9 @@ pub const table = [_]Entry{...@@ -1676,6 +1678,9 @@ pub const table = [_]Entry{
1676 .{ .vpsubusb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd8 }, 0, .vex_128_wig, .avx },1678 .{ .vpsubusb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd8 }, 0, .vex_128_wig, .avx },
1677 .{ .vpsubusw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd9 }, 0, .vex_128_wig, .avx },1679 .{ .vpsubusw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0xd9 }, 0, .vex_128_wig, .avx },
16781680
1681 .{ .vptest, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x17 }, 0, .vex_128_wig, .avx },
1682 .{ .vptest, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x17 }, 0, .vex_256_wig, .avx },
1683
1679 .{ .vpunpckhbw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x68 }, 0, .vex_128_wig, .avx },1684 .{ .vpunpckhbw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x68 }, 0, .vex_128_wig, .avx },
1680 .{ .vpunpckhwd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x69 }, 0, .vex_128_wig, .avx },1685 .{ .vpunpckhwd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x69 }, 0, .vex_128_wig, .avx },
1681 .{ .vpunpckhdq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6a }, 0, .vex_128_wig, .avx },1686 .{ .vpunpckhdq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6a }, 0, .vex_128_wig, .avx },
...@@ -1726,6 +1731,11 @@ pub const table = [_]Entry{...@@ -1726,6 +1731,11 @@ pub const table = [_]Entry{
17261731
1727 .{ .vsubss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .vex_lig_wig, .avx },1732 .{ .vsubss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .vex_lig_wig, .avx },
17281733
1734 .{ .vtestps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x0e }, 0, .vex_128_w0, .avx },
1735 .{ .vtestps, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x0e }, 0, .vex_256_w0, .avx },
1736 .{ .vtestpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x0f }, 0, .vex_128_w0, .avx },
1737 .{ .vtestpd, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x0f }, 0, .vex_256_w0, .avx },
1738
1729 .{ .vxorpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_128_wig, .avx },1739 .{ .vxorpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_128_wig, .avx },
1730 .{ .vxorpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_256_wig, .avx },1740 .{ .vxorpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x57 }, 0, .vex_256_wig, .avx },
17311741
test/behavior/x86_64/math.zig+6
...@@ -263,6 +263,12 @@ fn testBinary(comptime op: anytype) !void {...@@ -263,6 +263,12 @@ fn testBinary(comptime op: anytype) !void {
263 0xbfd88aee1d82ed32, 0x20e91c15b701059a,263 0xbfd88aee1d82ed32, 0x20e91c15b701059a,
264 0xed533d18f8657f3f, 0x1ddd7cd7f6bab957,264 0xed533d18f8657f3f, 0x1ddd7cd7f6bab957,
265 });265 });
266
267 if (false) try testType(@Vector(1, u128), .{
268 0x5f11e16b0ca3392f907a857881455d2e,
269 }, .{
270 0xf9142d73b408fd6955922f9fc147f7d7,
271 });
266}272}
267273
268inline fn bitAnd(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs & rhs) {274inline fn bitAnd(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs & rhs) {