@@ -699,9 +699,21 @@ pub const Inst = struct {
699
699
/// equal to the scalar value.
700
700
/// Uses the `ty_op` field.
701
701
splat ,
702
- /// Constructs a vector by selecting elements from `a` and `b` based on `mask`.
703
- /// Uses the `ty_pl` field with payload `Shuffle`.
704
- shuffle ,
702
+ /// Constructs a vector by selecting elements from a single vector based on a mask. Each
703
+ /// mask element is either an index into the vector, or a comptime-known value, or "undef".
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`
706
+ /// 2. operand: Ref // guaranteed not to be an interned value
707
+ /// See `unwrapShufleOne`.
708
+ shuffle_one ,
709
+ /// 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".
711
+ /// Uses the `ty_pl` field, where the payload index points to:
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 value
714
+ /// 3. operand_b: Ref // guaranteed not to be an interned value
715
+ /// See `unwrapShufleTwo`.
716
+ shuffle_two ,
705
717
/// Constructs a vector element-wise from `a` or `b` based on `pred`.
706
718
/// Uses the `pl_op` field with `pred` as operand, and payload `Bin`.
707
719
select ,
@@ -1299,13 +1311,6 @@ pub const FieldParentPtr = struct {
1299
1311
field_index : u32 ,
1300
1312
};
1301
1313
1302
- pub const Shuffle = struct {
1303
- a : Inst.Ref ,
1304
- b : Inst.Ref ,
1305
- mask : InternPool.Index ,
1306
- mask_len : u32 ,
1307
- };
1308
-
1309
1314
pub const VectorCmp = struct {
1310
1315
lhs : Inst.Ref ,
1311
1316
rhs : Inst.Ref ,
@@ -1320,6 +1325,64 @@ pub const VectorCmp = struct {
1320
1325
}
1321
1326
};
1322
1327
1328
+ /// Used by `Inst.Tag.shuffle_one`. Represents a mask element which either indexes into a
1329
+ /// runtime-known vector, or is a comptime-known value.
1330
+ pub const ShuffleOneMask = packed struct (u32 ) {
1331
+ index : u31 ,
1332
+ kind : enum (u1 ) { elem , value },
1333
+ pub fn elem (idx : u32 ) ShuffleOneMask {
1334
+ return .{ .index = @intCast (idx ), .kind = .elem };
1335
+ }
1336
+ pub fn value (val : Value ) ShuffleOneMask {
1337
+ return .{ .index = @intCast (@intFromEnum (val .toIntern ())), .kind = .value };
1338
+ }
1339
+ pub const Unwrapped = union (enum ) {
1340
+ /// The resulting element is this index into the runtime vector.
1341
+ elem : u32 ,
1342
+ /// The resulting element is this comptime-known value.
1343
+ /// It is correctly typed. It might be `undefined`.
1344
+ value : InternPool.Index ,
1345
+ };
1346
+ pub fn unwrap (raw : ShuffleOneMask ) Unwrapped {
1347
+ return switch (raw .kind ) {
1348
+ .elem = > .{ .elem = raw .index },
1349
+ .value = > .{ .value = @enumFromInt (raw .index ) },
1350
+ };
1351
+ }
1352
+ };
1353
+
1354
+ /// Used by `Inst.Tag.shuffle_two`. Represents a mask element which either indexes into one
1355
+ /// of two runtime-known vectors, or is undefined.
1356
+ pub const ShuffleTwoMask = enum (u32 ) {
1357
+ undef = std .math .maxInt (u32 ),
1358
+ _ ,
1359
+ pub fn aElem (idx : u32 ) ShuffleTwoMask {
1360
+ return @enumFromInt (idx << 1 );
1361
+ }
1362
+ pub fn bElem (idx : u32 ) ShuffleTwoMask {
1363
+ return @enumFromInt (idx << 1 | 1 );
1364
+ }
1365
+ pub const Unwrapped = union (enum ) {
1366
+ /// The resulting element is this index into the first runtime vector.
1367
+ a_elem : u32 ,
1368
+ /// The resulting element is this index into the second runtime vector.
1369
+ b_elem : u32 ,
1370
+ /// The resulting element is `undefined`.
1371
+ undef ,
1372
+ };
1373
+ pub fn unwrap (raw : ShuffleTwoMask ) Unwrapped {
1374
+ switch (raw ) {
1375
+ .undef = > return .undef ,
1376
+ _ = > {},
1377
+ }
1378
+ const x = @intFromEnum (raw );
1379
+ return switch (@as (u1 , @truncate (x ))) {
1380
+ 0 = > .{ .a_elem = x >> 1 },
1381
+ 1 = > .{ .b_elem = x >> 1 },
1382
+ };
1383
+ }
1384
+ };
1385
+
1323
1386
/// Trailing:
1324
1387
/// 0. `Inst.Ref` for every outputs_len
1325
1388
/// 1. `Inst.Ref` for every inputs_len
@@ -1503,7 +1566,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1503
1566
.cmpxchg_weak ,
1504
1567
.cmpxchg_strong ,
1505
1568
.slice ,
1506
- .shuffle ,
1507
1569
.aggregate_init ,
1508
1570
.union_init ,
1509
1571
.field_parent_ptr ,
@@ -1517,6 +1579,8 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1517
1579
.ptr_sub ,
1518
1580
.try_ptr ,
1519
1581
.try_ptr_cold ,
1582
+ .shuffle_one ,
1583
+ .shuffle_two ,
1520
1584
= > return datas [@intFromEnum (inst )].ty_pl .ty .toType (),
1521
1585
1522
1586
.not ,
@@ -1903,7 +1967,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1903
1967
.reduce ,
1904
1968
.reduce_optimized ,
1905
1969
.splat ,
1906
- .shuffle ,
1970
+ .shuffle_one ,
1971
+ .shuffle_two ,
1907
1972
.select ,
1908
1973
.is_named_enum_value ,
1909
1974
.tag_name ,
@@ -2030,6 +2095,48 @@ pub fn unwrapSwitch(air: *const Air, switch_inst: Inst.Index) UnwrappedSwitch {
2030
2095
};
2031
2096
}
2032
2097
2098
+ pub fn unwrapShuffleOne (air : * const Air , zcu : * const Zcu , inst_index : Inst.Index ) struct {
2099
+ result_ty : Type ,
2100
+ operand : Inst.Ref ,
2101
+ mask : []const ShuffleOneMask ,
2102
+ } {
2103
+ const inst = air .instructions .get (@intFromEnum (inst_index ));
2104
+ switch (inst .tag ) {
2105
+ .shuffle_one = > {},
2106
+ else = > unreachable , // assertion failure
2107
+ }
2108
+ const result_ty : Type = .fromInterned (inst .data .ty_pl .ty .toInterned ().? );
2109
+ const mask_len : u32 = result_ty .vectorLen (zcu );
2110
+ const extra_idx = inst .data .ty_pl .payload ;
2111
+ return .{
2112
+ .result_ty = result_ty ,
2113
+ .operand = @enumFromInt (air .extra .items [extra_idx + mask_len ]),
2114
+ .mask = @ptrCast (air .extra .items [extra_idx .. ][0.. mask_len ]),
2115
+ };
2116
+ }
2117
+
2118
+ pub fn unwrapShuffleTwo (air : * const Air , zcu : * const Zcu , inst_index : Inst.Index ) struct {
2119
+ result_ty : Type ,
2120
+ operand_a : Inst.Ref ,
2121
+ operand_b : Inst.Ref ,
2122
+ mask : []const ShuffleTwoMask ,
2123
+ } {
2124
+ const inst = air .instructions .get (@intFromEnum (inst_index ));
2125
+ switch (inst .tag ) {
2126
+ .shuffle_two = > {},
2127
+ else = > unreachable , // assertion failure
2128
+ }
2129
+ const result_ty : Type = .fromInterned (inst .data .ty_pl .ty .toInterned ().? );
2130
+ const mask_len : u32 = result_ty .vectorLen (zcu );
2131
+ const extra_idx = inst .data .ty_pl .payload ;
2132
+ return .{
2133
+ .result_ty = result_ty ,
2134
+ .operand_a = @enumFromInt (air .extra .items [extra_idx + mask_len + 0 ]),
2135
+ .operand_b = @enumFromInt (air .extra .items [extra_idx + mask_len + 1 ]),
2136
+ .mask = @ptrCast (air .extra .items [extra_idx .. ][0.. mask_len ]),
2137
+ };
2138
+ }
2139
+
2033
2140
pub const typesFullyResolved = types_resolved .typesFullyResolved ;
2034
2141
pub const typeFullyResolved = types_resolved .checkType ;
2035
2142
pub const valFullyResolved = types_resolved .checkVal ;
0 commit comments