authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-05-31 18:54:01-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-01 08:24:01+01:00
logec579aa0f372b2054ad659aaacd190c1a986d7f2
tree193cca8db61e7885b94639e18319b4d98e586552
parentadd2976a9ba76ec661ae5668eb2a8dca2ccfad42
signaturelock-open Commit is signed but in an unrecognized format.

Legalize: implement scalarization of `@shuffle`


11 files changed, 328 insertions(+), 138 deletions(-)

lib/std/Target.zig+6-21
...@@ -1246,11 +1246,7 @@ pub const Cpu = struct {...@@ -1246,11 +1246,7 @@ pub const Cpu = struct {
12461246
1247 /// Adds the specified feature set but not its dependencies.1247 /// Adds the specified feature set but not its dependencies.
1248 pub fn addFeatureSet(set: *Set, other_set: Set) void {1248 pub fn addFeatureSet(set: *Set, other_set: Set) void {
1249 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) {1249 set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints);
1250 for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* |= other_set_int;
1251 } else {
1252 set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints);
1253 }
1254 }1250 }
12551251
1256 /// Removes the specified feature but not its dependents.1252 /// Removes the specified feature but not its dependents.
...@@ -1262,11 +1258,7 @@ pub const Cpu = struct {...@@ -1262,11 +1258,7 @@ pub const Cpu = struct {
12621258
1263 /// Removes the specified feature but not its dependents.1259 /// Removes the specified feature but not its dependents.
1264 pub fn removeFeatureSet(set: *Set, other_set: Set) void {1260 pub fn removeFeatureSet(set: *Set, other_set: Set) void {
1265 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) {1261 set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints);
1266 for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* &= ~other_set_int;
1267 } else {
1268 set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints);
1269 }
1270 }1262 }
12711263
1272 pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void {1264 pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void {
...@@ -1295,17 +1287,10 @@ pub const Cpu = struct {...@@ -1295,17 +1287,10 @@ pub const Cpu = struct {
1295 }1287 }
12961288
1297 pub fn isSuperSetOf(set: Set, other_set: Set) bool {1289 pub fn isSuperSetOf(set: Set, other_set: Set) bool {
1298 if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) {1290 const V = @Vector(usize_count, usize);
1299 var result = true;1291 const set_v: V = set.ints;
1300 for (&set.ints, other_set.ints) |*set_int, other_set_int|1292 const other_v: V = other_set.ints;
1301 result = result and (set_int.* & other_set_int) == other_set_int;1293 return @reduce(.And, (set_v & other_v) == other_v);
1302 return result;
1303 } else {
1304 const V = @Vector(usize_count, usize);
1305 const set_v: V = set.ints;
1306 const other_v: V = other_set.ints;
1307 return @reduce(.And, (set_v & other_v) == other_v);
1308 }
1309 }1294 }
1310 };1295 };
13111296
lib/std/array_hash_map.zig+4-13
...@@ -889,19 +889,10 @@ pub fn ArrayHashMapUnmanaged(...@@ -889,19 +889,10 @@ pub fn ArrayHashMapUnmanaged(
889 self.pointer_stability.lock();889 self.pointer_stability.lock();
890 defer self.pointer_stability.unlock();890 defer self.pointer_stability.unlock();
891891
892 if (new_capacity <= linear_scan_max) {
893 try self.entries.ensureTotalCapacity(gpa, new_capacity);
894 return;
895 }
896
897 if (self.index_header) |header| {
898 if (new_capacity <= header.capacity()) {
899 try self.entries.ensureTotalCapacity(gpa, new_capacity);
900 return;
901 }
902 }
903
904 try self.entries.ensureTotalCapacity(gpa, new_capacity);892 try self.entries.ensureTotalCapacity(gpa, new_capacity);
893 if (new_capacity <= linear_scan_max) return;
894 if (self.index_header) |header| if (new_capacity <= header.capacity()) return;
895
905 const new_bit_index = try IndexHeader.findBitIndex(new_capacity);896 const new_bit_index = try IndexHeader.findBitIndex(new_capacity);
906 const new_header = try IndexHeader.alloc(gpa, new_bit_index);897 const new_header = try IndexHeader.alloc(gpa, new_bit_index);
907898
...@@ -2116,7 +2107,7 @@ const IndexHeader = struct {...@@ -2116,7 +2107,7 @@ const IndexHeader = struct {
21162107
2117 fn findBitIndex(desired_capacity: usize) Allocator.Error!u8 {2108 fn findBitIndex(desired_capacity: usize) Allocator.Error!u8 {
2118 if (desired_capacity > max_capacity) return error.OutOfMemory;2109 if (desired_capacity > max_capacity) return error.OutOfMemory;
2119 var new_bit_index = @as(u8, @intCast(std.math.log2_int_ceil(usize, desired_capacity)));2110 var new_bit_index: u8 = @intCast(std.math.log2_int_ceil(usize, desired_capacity));
2120 if (desired_capacity > index_capacities[new_bit_index]) new_bit_index += 1;2111 if (desired_capacity > index_capacities[new_bit_index]) new_bit_index += 1;
2121 if (new_bit_index < min_bit_index) new_bit_index = min_bit_index;2112 if (new_bit_index < min_bit_index) new_bit_index = min_bit_index;
2122 assert(desired_capacity <= index_capacities[new_bit_index]);2113 assert(desired_capacity <= index_capacities[new_bit_index]);
lib/std/crypto/chacha20.zig+3-6
...@@ -499,15 +499,12 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type {...@@ -499,15 +499,12 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type {
499fn ChaChaImpl(comptime rounds_nb: usize) type {499fn ChaChaImpl(comptime rounds_nb: usize) type {
500 switch (builtin.cpu.arch) {500 switch (builtin.cpu.arch) {
501 .x86_64 => {501 .x86_64 => {
502 const has_avx2 = std.Target.x86.featureSetHas(builtin.cpu.features, .avx2);502 if (builtin.zig_backend != .stage2_x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f)) return ChaChaVecImpl(rounds_nb, 4);
503 const has_avx512f = std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f);503 if (std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) return ChaChaVecImpl(rounds_nb, 2);
504 if (builtin.zig_backend != .stage2_x86_64 and has_avx512f) return ChaChaVecImpl(rounds_nb, 4);
505 if (has_avx2) return ChaChaVecImpl(rounds_nb, 2);
506 return ChaChaVecImpl(rounds_nb, 1);504 return ChaChaVecImpl(rounds_nb, 1);
507 },505 },
508 .aarch64 => {506 .aarch64 => {
509 const has_neon = std.Target.aarch64.featureSetHas(builtin.cpu.features, .neon);507 if (builtin.zig_backend != .stage2_aarch64 and std.Target.aarch64.featureSetHas(builtin.cpu.features, .neon)) return ChaChaVecImpl(rounds_nb, 4);
510 if (has_neon) return ChaChaVecImpl(rounds_nb, 4);
511 return ChaChaNonVecImpl(rounds_nb);508 return ChaChaNonVecImpl(rounds_nb);
512 },509 },
513 else => return ChaChaNonVecImpl(rounds_nb),510 else => return ChaChaNonVecImpl(rounds_nb),
lib/std/hash/xxhash.zig-3
...@@ -780,7 +780,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64)...@@ -780,7 +780,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64)
780}780}
781781
782test "xxhash3" {782test "xxhash3" {
783 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
784 if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807783 if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807
785784
786 const H = XxHash3;785 const H = XxHash3;
...@@ -814,7 +813,6 @@ test "xxhash3" {...@@ -814,7 +813,6 @@ test "xxhash3" {
814}813}
815814
816test "xxhash3 smhasher" {815test "xxhash3 smhasher" {
817 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
818 if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807816 if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807
819817
820 const Test = struct {818 const Test = struct {
...@@ -828,7 +826,6 @@ test "xxhash3 smhasher" {...@@ -828,7 +826,6 @@ test "xxhash3 smhasher" {
828}826}
829827
830test "xxhash3 iterative api" {828test "xxhash3 iterative api" {
831 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
832 if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807829 if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807
833830
834 const Test = struct {831 const Test = struct {
lib/std/simd.zig-4
...@@ -231,8 +231,6 @@ pub fn extract(...@@ -231,8 +231,6 @@ pub fn extract(
231}231}
232232
233test "vector patterns" {233test "vector patterns" {
234 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
235
236 const base = @Vector(4, u32){ 10, 20, 30, 40 };234 const base = @Vector(4, u32){ 10, 20, 30, 40 };
237 const other_base = @Vector(4, u32){ 55, 66, 77, 88 };235 const other_base = @Vector(4, u32){ 55, 66, 77, 88 };
238236
...@@ -302,8 +300,6 @@ pub fn reverseOrder(vec: anytype) @TypeOf(vec) {...@@ -302,8 +300,6 @@ pub fn reverseOrder(vec: anytype) @TypeOf(vec) {
302}300}
303301
304test "vector shifting" {302test "vector shifting" {
305 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
306
307 const base = @Vector(4, u32){ 10, 20, 30, 40 };303 const base = @Vector(4, u32){ 10, 20, 30, 40 };
308304
309 try std.testing.expectEqual([4]u32{ 30, 40, 999, 999 }, shiftElementsLeft(base, 2, 999));305 try std.testing.expectEqual([4]u32{ 30, 40, 999, 999 }, shiftElementsLeft(base, 2, 999));
src/Air.zig+2-2
...@@ -704,7 +704,7 @@ pub const Inst = struct {...@@ -704,7 +704,7 @@ pub const Inst = struct {
704 /// Uses the `ty_pl` field, where the payload index points to:704 /// Uses the `ty_pl` field, where the payload index points to:
705 /// 1. mask_elem: ShuffleOneMask // for each `mask_len`, which comes from `ty_pl.ty`705 /// 1. mask_elem: ShuffleOneMask // for each `mask_len`, which comes from `ty_pl.ty`
706 /// 2. operand: Ref // guaranteed not to be an interned value706 /// 2. operand: Ref // guaranteed not to be an interned value
707 /// See `unwrapShufleOne`.707 /// See `unwrapShuffleOne`.
708 shuffle_one,708 shuffle_one,
709 /// Constructs a vector by selecting elements from two vectors based on a mask. Each mask709 /// Constructs a vector by selecting elements from two vectors based on a mask. Each mask
710 /// element is either an index into one of the vectors, or "undef".710 /// element is either an index into one of the vectors, or "undef".
...@@ -712,7 +712,7 @@ pub const Inst = struct {...@@ -712,7 +712,7 @@ pub const Inst = struct {
712 /// 1. mask_elem: ShuffleOneMask // for each `mask_len`, which comes from `ty_pl.ty`712 /// 1. mask_elem: ShuffleOneMask // for each `mask_len`, which comes from `ty_pl.ty`
713 /// 2. operand_a: Ref // guaranteed not to be an interned value713 /// 2. operand_a: Ref // guaranteed not to be an interned value
714 /// 3. operand_b: Ref // guaranteed not to be an interned value714 /// 3. operand_b: Ref // guaranteed not to be an interned value
715 /// See `unwrapShufleTwo`.715 /// See `unwrapShuffleTwo`.
716 shuffle_two,716 shuffle_two,
717 /// Constructs a vector element-wise from `a` or `b` based on `pred`.717 /// Constructs a vector element-wise from `a` or `b` based on `pred`.
718 /// Uses the `pl_op` field with `pred` as operand, and payload `Bin`.718 /// Uses the `pl_op` field with `pred` as operand, and payload `Bin`.
src/Air/Legalize.zig+280-70
...@@ -74,6 +74,8 @@ pub const Feature = enum {...@@ -74,6 +74,8 @@ pub const Feature = enum {
74 scalarize_int_from_float,74 scalarize_int_from_float,
75 scalarize_int_from_float_optimized,75 scalarize_int_from_float_optimized,
76 scalarize_float_from_int,76 scalarize_float_from_int,
77 scalarize_shuffle_one,
78 scalarize_shuffle_two,
77 scalarize_select,79 scalarize_select,
78 scalarize_mul_add,80 scalarize_mul_add,
7981
...@@ -168,7 +170,9 @@ pub const Feature = enum {...@@ -168,7 +170,9 @@ pub const Feature = enum {
168 .int_from_float => .scalarize_int_from_float,170 .int_from_float => .scalarize_int_from_float,
169 .int_from_float_optimized => .scalarize_int_from_float_optimized,171 .int_from_float_optimized => .scalarize_int_from_float_optimized,
170 .float_from_int => .scalarize_float_from_int,172 .float_from_int => .scalarize_float_from_int,
171 .select => .scalarize_select,173 .shuffle_one => .scalarize_shuffle_one,
174 .shuffle_two => .scalarize_shuffle_two,
175 .select => .scalarize_selects,
172 .mul_add => .scalarize_mul_add,176 .mul_add => .scalarize_mul_add,
173 };177 };
174 }178 }
...@@ -521,11 +525,10 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -521,11 +525,10 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
521 }525 }
522 },526 },
523 .splat,527 .splat,
524 .shuffle_one,
525 .shuffle_two,
526 => {},528 => {},
527 .select,529 .shuffle_one => if (l.features.contains(.scalarize_shuffle_one)) continue :inst try l.scalarize(inst, .shuffle_one),
528 => if (l.features.contains(.scalarize_select)) continue :inst try l.scalarize(inst, .select_pl_op_bin),530 .shuffle_two => if (l.features.contains(.scalarize_shuffle_two)) continue :inst try l.scalarize(inst, .shuffle_two),
531 .select => if (l.features.contains(.scalarize_select)) continue :inst try l.scalarize(inst, .select),
529 .memset,532 .memset,
530 .memset_safe,533 .memset_safe,
531 .memcpy,534 .memcpy,
...@@ -573,25 +576,26 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -573,25 +576,26 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
573 }576 }
574}577}
575578
576const ScalarizeDataTag = enum { un_op, ty_op, bin_op, ty_pl_vector_cmp, pl_op_bin, select_pl_op_bin };579const ScalarizeForm = enum { un_op, ty_op, bin_op, ty_pl_vector_cmp, pl_op_bin, shuffle_one, shuffle_two, select };
577inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag: ScalarizeDataTag) Error!Air.Inst.Tag {580inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime form: ScalarizeForm) Error!Air.Inst.Tag {
578 return l.replaceInst(orig_inst, .block, try l.scalarizeBlockPayload(orig_inst, data_tag));581 return l.replaceInst(orig_inst, .block, try l.scalarizeBlockPayload(orig_inst, form));
579}582}
580fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag: ScalarizeDataTag) Error!Air.Inst.Data {583fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form: ScalarizeForm) Error!Air.Inst.Data {
581 const pt = l.pt;584 const pt = l.pt;
582 const zcu = pt.zcu;585 const zcu = pt.zcu;
583586
584 const orig = l.air_instructions.get(@intFromEnum(orig_inst));587 const orig = l.air_instructions.get(@intFromEnum(orig_inst));
585 const res_ty = l.typeOfIndex(orig_inst);588 const res_ty = l.typeOfIndex(orig_inst);
589 const res_len = res_ty.vectorLen(zcu);
586590
587 var inst_buf: [591 const extra_insts = switch (form) {
588 5 + switch (data_tag) {592 .un_op, .ty_op => 1,
589 .un_op, .ty_op => 1,593 .bin_op, .ty_pl_vector_cmp => 2,
590 .bin_op, .ty_pl_vector_cmp => 2,594 .pl_op_bin => 3,
591 .pl_op_bin => 3,595 .shuffle_one, .shuffle_two => 13,
592 .select_pl_op_bin => 6,596 .select => 6,
593 } + 9597 };
594 ]Air.Inst.Index = undefined;598 var inst_buf: [5 + extra_insts + 9]Air.Inst.Index = undefined;
595 try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);599 try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
596600
597 var res_block: Block = .init(&inst_buf);601 var res_block: Block = .init(&inst_buf);
...@@ -628,7 +632,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -628,7 +632,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
628 .vector_ptr = res_alloc_inst.toRef(),632 .vector_ptr = res_alloc_inst.toRef(),
629 .payload = try l.addExtra(Air.Bin, .{633 .payload = try l.addExtra(Air.Bin, .{
630 .lhs = cur_index_inst.toRef(),634 .lhs = cur_index_inst.toRef(),
631 .rhs = res_elem: switch (data_tag) {635 .rhs = res_elem: switch (form) {
632 .un_op => loop.block.add(l, .{636 .un_op => loop.block.add(l, .{
633 .tag = orig.tag,637 .tag = orig.tag,
634 .data = .{ .un_op = loop.block.add(l, .{638 .data = .{ .un_op = loop.block.add(l, .{
...@@ -638,7 +642,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -638,7 +642,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
638 .rhs = cur_index_inst.toRef(),642 .rhs = cur_index_inst.toRef(),
639 } },643 } },
640 }).toRef() },644 }).toRef() },
641 }),645 }).toRef(),
642 .ty_op => loop.block.add(l, .{646 .ty_op => loop.block.add(l, .{
643 .tag = orig.tag,647 .tag = orig.tag,
644 .data = .{ .ty_op = .{648 .data = .{ .ty_op = .{
...@@ -651,7 +655,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -651,7 +655,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
651 } },655 } },
652 }).toRef(),656 }).toRef(),
653 } },657 } },
654 }),658 }).toRef(),
655 .bin_op => loop.block.add(l, .{659 .bin_op => loop.block.add(l, .{
656 .tag = orig.tag,660 .tag = orig.tag,
657 .data = .{ .bin_op = .{661 .data = .{ .bin_op = .{
...@@ -670,10 +674,10 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -670,10 +674,10 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
670 } },674 } },
671 }).toRef(),675 }).toRef(),
672 } },676 } },
673 }),677 }).toRef(),
674 .ty_pl_vector_cmp => {678 .ty_pl_vector_cmp => {
675 const extra = l.extraData(Air.VectorCmp, orig.data.ty_pl.payload).data;679 const extra = l.extraData(Air.VectorCmp, orig.data.ty_pl.payload).data;
676 break :res_elem try loop.block.addCmp(680 break :res_elem (try loop.block.addCmp(
677 l,681 l,
678 extra.compareOperator(),682 extra.compareOperator(),
679 loop.block.add(l, .{683 loop.block.add(l, .{
...@@ -695,7 +699,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -695,7 +699,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
695 .cmp_vector => false,699 .cmp_vector => false,
696 .cmp_vector_optimized => true,700 .cmp_vector_optimized => true,
697 } },701 } },
698 );702 )).toRef();
699 },703 },
700 .pl_op_bin => {704 .pl_op_bin => {
701 const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data;705 const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data;
...@@ -726,58 +730,265 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -726,58 +730,265 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
726 } },730 } },
727 }).toRef(),731 }).toRef(),
728 } },732 } },
729 });733 }).toRef();
730 },734 },
731 .select_pl_op_bin => {735 .shuffle_one, .shuffle_two => {
732 const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data;736 const ip = &zcu.intern_pool;
733 var res_elem: Result = .init(l, l.typeOf(extra.lhs).scalarType(zcu), &loop.block);737 const unwrapped = switch (form) {
734 res_elem.block = .init(loop.block.stealCapacity(6));738 else => comptime unreachable,
739 .shuffle_one => l.getTmpAir().unwrapShuffleOne(zcu, orig_inst),
740 .shuffle_two => l.getTmpAir().unwrapShuffleTwo(zcu, orig_inst),
741 };
742 const operand_a = switch (form) {
743 else => comptime unreachable,
744 .shuffle_one => unwrapped.operand,
745 .shuffle_two => unwrapped.operand_a,
746 };
747 const operand_a_len = l.typeOf(operand_a).vectorLen(zcu);
748 const elem_ty = unwrapped.result_ty.scalarType(zcu);
749 var res_elem: Result = .init(l, elem_ty, &loop.block);
750 res_elem.block = .init(loop.block.stealCapacity(extra_insts));
735 {751 {
736 var select_cond_br: CondBr = .init(l, res_elem.block.add(l, .{752 const ExpectedContents = extern struct {
737 .tag = .array_elem_val,753 mask_elems: [128]InternPool.Index,
754 ct_elems: switch (form) {
755 else => unreachable,
756 .shuffle_one => extern struct {
757 keys: [152]InternPool.Index,
758 header: u8 align(@alignOf(u32)),
759 index: [256][2]u8,
760 },
761 .shuffle_two => void,
762 },
763 };
764 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
765 std.heap.stackFallback(@sizeOf(ExpectedContents), zcu.gpa);
766 const gpa = stack.get();
767
768 const mask_elems = try gpa.alloc(InternPool.Index, res_len);
769 defer gpa.free(mask_elems);
770
771 var ct_elems: switch (form) {
772 else => unreachable,
773 .shuffle_one => std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
774 .shuffle_two => struct {
775 const empty: @This() = .{};
776 inline fn deinit(_: @This(), _: std.mem.Allocator) void {}
777 inline fn ensureTotalCapacity(_: @This(), _: std.mem.Allocator, _: usize) error{}!void {}
778 },
779 } = .empty;
780 defer ct_elems.deinit(gpa);
781 try ct_elems.ensureTotalCapacity(gpa, res_len);
782
783 const mask_elem_ty = try pt.intType(.signed, 1 + Type.smallestUnsignedBits(@max(operand_a_len, switch (form) {
784 else => comptime unreachable,
785 .shuffle_one => res_len,
786 .shuffle_two => l.typeOf(unwrapped.operand_b).vectorLen(zcu),
787 })));
788 for (mask_elems, unwrapped.mask) |*mask_elem_val, mask_elem| mask_elem_val.* = (try pt.intValue(mask_elem_ty, switch (form) {
789 else => comptime unreachable,
790 .shuffle_one => switch (mask_elem.unwrap()) {
791 .elem => |index| index,
792 .value => |elem_val| if (ip.isUndef(elem_val))
793 operand_a_len
794 else
795 ~@as(i33, @intCast((ct_elems.getOrPutAssumeCapacity(elem_val)).index)),
796 },
797 .shuffle_two => switch (mask_elem.unwrap()) {
798 .a_elem => |a_index| a_index,
799 .b_elem => |b_index| ~@as(i33, b_index),
800 .undef => operand_a_len,
801 },
802 })).toIntern();
803 const mask_ty = try pt.arrayType(.{
804 .len = res_len,
805 .child = mask_elem_ty.toIntern(),
806 });
807 const mask_elem_inst = res_elem.block.add(l, .{
808 .tag = .ptr_elem_val,
738 .data = .{ .bin_op = .{809 .data = .{ .bin_op = .{
739 .lhs = orig.data.pl_op.operand,810 .lhs = Air.internedToRef(try pt.intern(.{ .ptr = .{
811 .ty = (try pt.manyConstPtrType(mask_elem_ty)).toIntern(),
812 .base_addr = .{ .uav = .{
813 .val = try pt.intern(.{ .aggregate = .{
814 .ty = mask_ty.toIntern(),
815 .storage = .{ .elems = mask_elems },
816 } }),
817 .orig_ty = (try pt.singleConstPtrType(mask_ty)).toIntern(),
818 } },
819 .byte_offset = 0,
820 } })),
740 .rhs = cur_index_inst.toRef(),821 .rhs = cur_index_inst.toRef(),
741 } },822 } },
742 }).toRef(), &res_elem.block, .{});823 });
743 select_cond_br.then_block = .init(res_elem.block.stealRemainingCapacity());824 var def_cond_br: CondBr = .init(l, (try res_elem.block.addCmp(
825 l,
826 .lt,
827 mask_elem_inst.toRef(),
828 try pt.intRef(mask_elem_ty, operand_a_len),
829 .{},
830 )).toRef(), &res_elem.block, .{});
831 def_cond_br.then_block = .init(res_elem.block.stealRemainingCapacity());
744 {832 {
745 _ = select_cond_br.then_block.add(l, .{833 const operand_b_used = switch (form) {
834 else => comptime unreachable,
835 .shuffle_one => ct_elems.count() > 0,
836 .shuffle_two => true,
837 };
838 var operand_cond_br: CondBr = undefined;
839 operand_cond_br.then_block = if (operand_b_used) then_block: {
840 operand_cond_br = .init(l, (try def_cond_br.then_block.addCmp(
841 l,
842 .gte,
843 mask_elem_inst.toRef(),
844 try pt.intRef(mask_elem_ty, 0),
845 .{},
846 )).toRef(), &def_cond_br.then_block, .{});
847 break :then_block .init(def_cond_br.then_block.stealRemainingCapacity());
848 } else def_cond_br.then_block;
849 _ = operand_cond_br.then_block.add(l, .{
746 .tag = .br,850 .tag = .br,
747 .data = .{ .br = .{851 .data = .{ .br = .{
748 .block_inst = res_elem.inst,852 .block_inst = res_elem.inst,
749 .operand = select_cond_br.then_block.add(l, .{853 .operand = operand_cond_br.then_block.add(l, .{
750 .tag = .array_elem_val,854 .tag = .array_elem_val,
751 .data = .{ .bin_op = .{855 .data = .{ .bin_op = .{
752 .lhs = extra.lhs,856 .lhs = operand_a,
753 .rhs = cur_index_inst.toRef(),857 .rhs = operand_cond_br.then_block.add(l, .{
858 .tag = .intcast,
859 .data = .{ .ty_op = .{
860 .ty = .usize_type,
861 .operand = mask_elem_inst.toRef(),
862 } },
863 }).toRef(),
754 } },864 } },
755 }).toRef(),865 }).toRef(),
756 } },866 } },
757 });867 });
868 if (operand_b_used) {
869 operand_cond_br.else_block = .init(operand_cond_br.then_block.stealRemainingCapacity());
870 _ = operand_cond_br.else_block.add(l, .{
871 .tag = .br,
872 .data = .{ .br = .{
873 .block_inst = res_elem.inst,
874 .operand = if (switch (form) {
875 else => comptime unreachable,
876 .shuffle_one => ct_elems.count() > 1,
877 .shuffle_two => true,
878 }) operand_cond_br.else_block.add(l, .{
879 .tag = switch (form) {
880 else => comptime unreachable,
881 .shuffle_one => .ptr_elem_val,
882 .shuffle_two => .array_elem_val,
883 },
884 .data = .{ .bin_op = .{
885 .lhs = operand_b: switch (form) {
886 else => comptime unreachable,
887 .shuffle_one => {
888 const ct_elems_ty = try pt.arrayType(.{
889 .len = ct_elems.count(),
890 .child = elem_ty.toIntern(),
891 });
892 break :operand_b Air.internedToRef(try pt.intern(.{ .ptr = .{
893 .ty = (try pt.manyConstPtrType(elem_ty)).toIntern(),
894 .base_addr = .{ .uav = .{
895 .val = try pt.intern(.{ .aggregate = .{
896 .ty = ct_elems_ty.toIntern(),
897 .storage = .{ .elems = ct_elems.keys() },
898 } }),
899 .orig_ty = (try pt.singleConstPtrType(ct_elems_ty)).toIntern(),
900 } },
901 .byte_offset = 0,
902 } }));
903 },
904 .shuffle_two => unwrapped.operand_b,
905 },
906 .rhs = operand_cond_br.else_block.add(l, .{
907 .tag = .intcast,
908 .data = .{ .ty_op = .{
909 .ty = .usize_type,
910 .operand = operand_cond_br.else_block.add(l, .{
911 .tag = .not,
912 .data = .{ .ty_op = .{
913 .ty = Air.internedToRef(mask_elem_ty.toIntern()),
914 .operand = mask_elem_inst.toRef(),
915 } },
916 }).toRef(),
917 } },
918 }).toRef(),
919 } },
920 }).toRef() else res_elem_br: {
921 _ = operand_cond_br.else_block.stealCapacity(3);
922 break :res_elem_br Air.internedToRef(ct_elems.keys()[0]);
923 },
924 } },
925 });
926 def_cond_br.else_block = .init(operand_cond_br.else_block.stealRemainingCapacity());
927 try operand_cond_br.finish(l);
928 } else {
929 def_cond_br.then_block = operand_cond_br.then_block;
930 _ = def_cond_br.then_block.stealCapacity(6);
931 def_cond_br.else_block = .init(def_cond_br.then_block.stealRemainingCapacity());
932 }
758 }933 }
934 _ = def_cond_br.else_block.add(l, .{
935 .tag = .br,
936 .data = .{ .br = .{
937 .block_inst = res_elem.inst,
938 .operand = try pt.undefRef(elem_ty),
939 } },
940 });
941 try def_cond_br.finish(l);
942 }
943 try res_elem.finish(l);
944 break :res_elem res_elem.inst.toRef();
945 },
946 .select => {
947 const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data;
948 var res_elem: Result = .init(l, l.typeOf(extra.lhs).scalarType(zcu), &loop.block);
949 res_elem.block = .init(loop.block.stealCapacity(extra_insts));
950 {
951 var select_cond_br: CondBr = .init(l, res_elem.block.add(l, .{
952 .tag = .array_elem_val,
953 .data = .{ .bin_op = .{
954 .lhs = orig.data.pl_op.operand,
955 .rhs = cur_index_inst.toRef(),
956 } },
957 }).toRef(), &res_elem.block, .{});
958 select_cond_br.then_block = .init(res_elem.block.stealRemainingCapacity());
959 _ = select_cond_br.then_block.add(l, .{
960 .tag = .br,
961 .data = .{ .br = .{
962 .block_inst = res_elem.inst,
963 .operand = select_cond_br.then_block.add(l, .{
964 .tag = .array_elem_val,
965 .data = .{ .bin_op = .{
966 .lhs = extra.lhs,
967 .rhs = cur_index_inst.toRef(),
968 } },
969 }).toRef(),
970 } },
971 });
759 select_cond_br.else_block = .init(select_cond_br.then_block.stealRemainingCapacity());972 select_cond_br.else_block = .init(select_cond_br.then_block.stealRemainingCapacity());
760 {973 _ = select_cond_br.else_block.add(l, .{
761 _ = select_cond_br.else_block.add(l, .{974 .tag = .br,
762 .tag = .br,975 .data = .{ .br = .{
763 .data = .{ .br = .{976 .block_inst = res_elem.inst,
764 .block_inst = res_elem.inst,977 .operand = select_cond_br.else_block.add(l, .{
765 .operand = select_cond_br.else_block.add(l, .{978 .tag = .array_elem_val,
766 .tag = .array_elem_val,979 .data = .{ .bin_op = .{
767 .data = .{ .bin_op = .{980 .lhs = extra.rhs,
768 .lhs = extra.rhs,981 .rhs = cur_index_inst.toRef(),
769 .rhs = cur_index_inst.toRef(),982 } },
770 } },983 }).toRef(),
771 }).toRef(),984 } },
772 } },985 });
773 });
774 }
775 try select_cond_br.finish(l);986 try select_cond_br.finish(l);
776 }987 }
777 try res_elem.finish(l);988 try res_elem.finish(l);
778 break :res_elem res_elem.inst;989 break :res_elem res_elem.inst.toRef();
779 },990 },
780 }.toRef(),991 },
781 }),992 }),
782 } },993 } },
783 });994 });
...@@ -786,7 +997,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -786,7 +997,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
786 l,997 l,
787 .lt,998 .lt,
788 cur_index_inst.toRef(),999 cur_index_inst.toRef(),
789 try pt.intRef(.usize, res_ty.vectorLen(zcu) - 1),1000 try pt.intRef(.usize, res_len - 1),
790 .{},1001 .{},
791 )).toRef(), &loop.block, .{});1002 )).toRef(), &loop.block, .{});
792 loop_cond_br.then_block = .init(loop.block.stealRemainingCapacity());1003 loop_cond_br.then_block = .init(loop.block.stealRemainingCapacity());
...@@ -810,21 +1021,19 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -810,21 +1021,19 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
810 });1021 });
811 }1022 }
812 loop_cond_br.else_block = .init(loop_cond_br.then_block.stealRemainingCapacity());1023 loop_cond_br.else_block = .init(loop_cond_br.then_block.stealRemainingCapacity());
813 {1024 _ = loop_cond_br.else_block.add(l, .{
814 _ = loop_cond_br.else_block.add(l, .{1025 .tag = .br,
815 .tag = .br,1026 .data = .{ .br = .{
816 .data = .{ .br = .{1027 .block_inst = orig_inst,
817 .block_inst = orig_inst,1028 .operand = loop_cond_br.else_block.add(l, .{
818 .operand = loop_cond_br.else_block.add(l, .{1029 .tag = .load,
819 .tag = .load,1030 .data = .{ .ty_op = .{
820 .data = .{ .ty_op = .{1031 .ty = Air.internedToRef(res_ty.toIntern()),
821 .ty = Air.internedToRef(res_ty.toIntern()),1032 .operand = res_alloc_inst.toRef(),
822 .operand = res_alloc_inst.toRef(),1033 } },
823 } },1034 }).toRef(),
824 }).toRef(),1035 } },
825 } },1036 });
826 });
827 }
828 try loop_cond_br.finish(l);1037 try loop_cond_br.finish(l);
829 }1038 }
830 try loop.finish(l);1039 try loop.finish(l);
...@@ -1337,6 +1546,7 @@ inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, dat...@@ -1337,6 +1546,7 @@ inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, dat
1337const Air = @import("../Air.zig");1546const Air = @import("../Air.zig");
1338const assert = std.debug.assert;1547const assert = std.debug.assert;
1339const dev = @import("../dev.zig");1548const dev = @import("../dev.zig");
1549const InternPool = @import("../InternPool.zig");
1340const Legalize = @This();1550const Legalize = @This();
1341const std = @import("std");1551const std = @import("std");
1342const Type = @import("../Type.zig");1552const Type = @import("../Type.zig");
src/arch/wasm/CodeGen.zig+6-1
...@@ -5195,6 +5195,8 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5195,6 +5195,8 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51955195
5196 // TODO: this is incorrect if either operand or the result is *not* by-ref, which is possible.5196 // TODO: this is incorrect if either operand or the result is *not* by-ref, which is possible.
5197 // I tried to fix it, but I couldn't make much sense of how this backend handles memory.5197 // I tried to fix it, but I couldn't make much sense of how this backend handles memory.
5198 if (!isByRef(result_ty, zcu, cg.target) or
5199 !isByRef(cg.typeOf(unwrapped.operand), zcu, cg.target)) return cg.fail("TODO: handle mixed by-ref shuffle", .{});
51985200
5199 const dest_alloc = try cg.allocStack(result_ty);5201 const dest_alloc = try cg.allocStack(result_ty);
5200 for (mask, 0..) |mask_elem, out_idx| {5202 for (mask, 0..) |mask_elem, out_idx| {
...@@ -5232,7 +5234,7 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5232,7 +5234,7 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5232 elem_ty.bitSize(zcu) % 8 == 0)5234 elem_ty.bitSize(zcu) % 8 == 0)
5233 {5235 {
5234 var lane_map: [16]u8 align(4) = undefined;5236 var lane_map: [16]u8 align(4) = undefined;
5235 const lanes_per_elem = elem_ty.bitSize(zcu) / 8;5237 const lanes_per_elem: usize = @intCast(elem_ty.bitSize(zcu) / 8);
5236 for (mask, 0..) |mask_elem, out_idx| {5238 for (mask, 0..) |mask_elem, out_idx| {
5237 const out_first_lane = out_idx * lanes_per_elem;5239 const out_first_lane = out_idx * lanes_per_elem;
5238 const in_first_lane = switch (mask_elem.unwrap()) {5240 const in_first_lane = switch (mask_elem.unwrap()) {
...@@ -5260,6 +5262,9 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5260,6 +5262,9 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
52605262
5261 // TODO: this is incorrect if either operand or the result is *not* by-ref, which is possible.5263 // TODO: this is incorrect if either operand or the result is *not* by-ref, which is possible.
5262 // I tried to fix it, but I couldn't make much sense of how this backend handles memory.5264 // I tried to fix it, but I couldn't make much sense of how this backend handles memory.
5265 if (!isByRef(result_ty, zcu, cg.target) or
5266 !isByRef(a_ty, zcu, cg.target) or
5267 !isByRef(b_ty, zcu, cg.target)) return cg.fail("TODO: handle mixed by-ref shuffle", .{});
52635268
5264 const dest_alloc = try cg.allocStack(result_ty);5269 const dest_alloc = try cg.allocStack(result_ty);
5265 for (mask, 0..) |mask_elem, out_idx| {5270 for (mask, 0..) |mask_elem, out_idx| {
src/arch/x86_64/CodeGen.zig+27-10
...@@ -53,11 +53,14 @@ pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features...@@ -53,11 +53,14 @@ pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features
53 .scalarize_div_exact_optimized = use_old,53 .scalarize_div_exact_optimized = use_old,
54 .scalarize_max = use_old,54 .scalarize_max = use_old,
55 .scalarize_min = use_old,55 .scalarize_min = use_old,
56 .scalarize_bit_and = use_old,
57 .scalarize_bit_or = use_old,
56 .scalarize_shr = true,58 .scalarize_shr = true,
57 .scalarize_shr_exact = true,59 .scalarize_shr_exact = true,
58 .scalarize_shl = true,60 .scalarize_shl = true,
59 .scalarize_shl_exact = true,61 .scalarize_shl_exact = true,
60 .scalarize_shl_sat = true,62 .scalarize_shl_sat = true,
63 .scalarize_xor = use_old,
61 .scalarize_not = use_old,64 .scalarize_not = use_old,
62 .scalarize_clz = use_old,65 .scalarize_clz = use_old,
63 .scalarize_ctz = true,66 .scalarize_ctz = true,
...@@ -84,6 +87,8 @@ pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features...@@ -84,6 +87,8 @@ pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features
84 .scalarize_int_from_float = use_old,87 .scalarize_int_from_float = use_old,
85 .scalarize_int_from_float_optimized = use_old,88 .scalarize_int_from_float_optimized = use_old,
86 .scalarize_float_from_int = use_old,89 .scalarize_float_from_int = use_old,
90 .scalarize_shuffle_one = true,
91 .scalarize_shuffle_two = true,
87 .scalarize_select = true,92 .scalarize_select = true,
88 .scalarize_mul_add = use_old,93 .scalarize_mul_add = use_old,
8994
...@@ -2299,11 +2304,17 @@ fn gen(self: *CodeGen) InnerError!void {...@@ -2299,11 +2304,17 @@ fn gen(self: *CodeGen) InnerError!void {
2299 try self.genBody(self.air.getMainBody());2304 try self.genBody(self.air.getMainBody());
23002305
2301 const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {2306 const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: {
2302 const epilogue_relocs_last_index = self.epilogue_relocs.items.len - 1;2307 var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
2303 for (if (self.epilogue_relocs.items[epilogue_relocs_last_index] == self.mir_instructions.len - 1) epilogue_relocs: {2308 while (self.epilogue_relocs.getLastOrNull() == last_inst) {
2304 _ = self.mir_instructions.pop();2309 self.epilogue_relocs.items.len -= 1;
2305 break :epilogue_relocs self.epilogue_relocs.items[0..epilogue_relocs_last_index];2310 self.mir_instructions.set(last_inst, .{
2306 } else self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc);2311 .tag = .pseudo,
2312 .ops = .pseudo_dead_none,
2313 .data = undefined,
2314 });
2315 last_inst -= 1;
2316 }
2317 for (self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc);
23072318
2308 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);2319 if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
2309 const backpatch_stack_dealloc = try self.asmPlaceholder();2320 const backpatch_stack_dealloc = try self.asmPlaceholder();
...@@ -174143,17 +174154,23 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index...@@ -174143,17 +174154,23 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index
174143 var block_data = self.blocks.fetchRemove(inst).?;174154 var block_data = self.blocks.fetchRemove(inst).?;
174144 defer block_data.value.deinit(self.gpa);174155 defer block_data.value.deinit(self.gpa);
174145 if (block_data.value.relocs.items.len > 0) {174156 if (block_data.value.relocs.items.len > 0) {
174157 var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1);
174158 while (block_data.value.relocs.getLastOrNull() == last_inst) {
174159 block_data.value.relocs.items.len -= 1;
174160 self.mir_instructions.set(last_inst, .{
174161 .tag = .pseudo,
174162 .ops = .pseudo_dead_none,
174163 .data = undefined,
174164 });
174165 last_inst -= 1;
174166 }
174167 for (block_data.value.relocs.items) |block_reloc| self.performReloc(block_reloc);
174146 try self.restoreState(block_data.value.state, liveness.deaths, .{174168 try self.restoreState(block_data.value.state, liveness.deaths, .{
174147 .emit_instructions = false,174169 .emit_instructions = false,
174148 .update_tracking = true,174170 .update_tracking = true,
174149 .resurrect = true,174171 .resurrect = true,
174150 .close_scope = true,174172 .close_scope = true,
174151 });174173 });
174152 const block_relocs_last_index = block_data.value.relocs.items.len - 1;
174153 for (if (block_data.value.relocs.items[block_relocs_last_index] == self.mir_instructions.len - 1) block_relocs: {
174154 _ = self.mir_instructions.pop();
174155 break :block_relocs block_data.value.relocs.items[0..block_relocs_last_index];
174156 } else block_data.value.relocs.items) |block_reloc| self.performReloc(block_reloc);
174157 }174174 }
174158174175
174159 if (std.debug.runtime_safety) assert(self.inst_tracking.getIndex(inst).? == inst_tracking_i);174176 if (std.debug.runtime_safety) assert(self.inst_tracking.getIndex(inst).? == inst_tracking_i);
test/behavior/shuffle.zig-5
...@@ -10,8 +10,6 @@ test "@shuffle int" {...@@ -10,8 +10,6 @@ test "@shuffle int" {
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_x86_64 and
14 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) return error.SkipZigTest;
1513
16 const S = struct {14 const S = struct {
17 fn doTheTest() !void {15 fn doTheTest() !void {
...@@ -53,7 +51,6 @@ test "@shuffle int" {...@@ -53,7 +51,6 @@ test "@shuffle int" {
5351
54test "@shuffle int strange sizes" {52test "@shuffle int strange sizes" {
55 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO53 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -136,7 +133,6 @@ fn testShuffle(...@@ -136,7 +133,6 @@ fn testShuffle(
136133
137test "@shuffle bool 1" {134test "@shuffle bool 1" {
138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -160,7 +156,6 @@ test "@shuffle bool 1" {...@@ -160,7 +156,6 @@ test "@shuffle bool 1" {
160156
161test "@shuffle bool 2" {157test "@shuffle bool 2" {
162 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO158 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
164 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
165 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/vector.zig-3
...@@ -906,8 +906,6 @@ test "mask parameter of @shuffle is comptime scope" {...@@ -906,8 +906,6 @@ test "mask parameter of @shuffle is comptime scope" {
906 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO906 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
907 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO907 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
908 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;908 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
909 if (builtin.zig_backend == .stage2_x86_64 and
910 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) return error.SkipZigTest;
911909
912 const __v4hi = @Vector(4, i16);910 const __v4hi = @Vector(4, i16);
913 var v4_a = __v4hi{ 1, 2, 3, 4 };911 var v4_a = __v4hi{ 1, 2, 3, 4 };
...@@ -1357,7 +1355,6 @@ test "array operands to shuffle are coerced to vectors" {...@@ -1357,7 +1355,6 @@ test "array operands to shuffle are coerced to vectors" {
1357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1359 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1360 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1361 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1358 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13621359
1363 const mask = [5]i32{ -1, 0, 1, 2, 3 };1360 const mask = [5]i32{ -1, 0, 1, 2, 3 };