authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-10 22:36:50-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-10 22:36:50-08:00
loge56fe06d3083d29b253ee8f4586971ec362a1e95
treeca58f93f7d987a49a73ce21daf854b55c809b36e
parentd18f52197d3e796858b79a70bfc6b6911b4f92ff
parent72bd1cd378dcdb96217473baee899528c21bcbbc
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18878 from alichraghi/vector

spirv: emit vectorized operations

1 files changed, 145 insertions(+), 182 deletions(-)

src/codegen/spirv.zig+145-182
......@@ -629,6 +629,16 @@ const DeclGen = struct {
629629 return self.backingIntBits(ty) == null;
630630 }
631631
632 /// Checks whether the type can be directly translated to SPIR-V vectors
633 fn isVector(self: *DeclGen, ty: Type) bool {
634 const mod = self.module;
635 if (ty.zigTypeTag(mod) != .Vector) return false;
636 const elem_ty = ty.childType(mod);
637 const len = ty.vectorLen(mod);
638 const is_scalar = elem_ty.isNumeric(mod) or elem_ty.toIntern() == .bool_type;
639 return is_scalar and len > 1 and len <= 4;
640 }
641
632642 fn arithmeticTypeInfo(self: *DeclGen, ty: Type) ArithmeticTypeInfo {
633643 const mod = self.module;
634644 const target = self.getTarget();
......@@ -694,6 +704,24 @@ const DeclGen = struct {
694704 /// This function, unlike SpvModule.constInt, takes care to bitcast
695705 /// the value to an unsigned int first for Kernels.
696706 fn constInt(self: *DeclGen, ty_ref: CacheRef, value: anytype) !IdRef {
707 switch (self.spv.cache.lookup(ty_ref)) {
708 .vector_type => |vec_type| {
709 const elem_ids = try self.gpa.alloc(IdRef, vec_type.component_count);
710 defer self.gpa.free(elem_ids);
711 const int_value = try self.constInt(vec_type.component_type, value);
712 @memset(elem_ids, int_value);
713
714 const constituents_id = self.spv.allocId();
715 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
716 .id_result_type = self.typeId(ty_ref),
717 .id_result = constituents_id,
718 .constituents = elem_ids,
719 });
720 return constituents_id;
721 },
722 else => {},
723 }
724
697725 if (value < 0) {
698726 const ty = self.spv.cache.lookup(ty_ref).int_type;
699727 // Manually truncate the value so that the resulting value
......@@ -711,6 +739,24 @@ const DeclGen = struct {
711739
712740 /// Emits a float constant
713741 fn constFloat(self: *DeclGen, ty_ref: CacheRef, value: f128) !IdRef {
742 switch (self.spv.cache.lookup(ty_ref)) {
743 .vector_type => |vec_type| {
744 const elem_ids = try self.gpa.alloc(IdRef, vec_type.component_count);
745 defer self.gpa.free(elem_ids);
746 const int_value = try self.constFloat(vec_type.component_type, value);
747 @memset(elem_ids, int_value);
748
749 const constituents_id = self.spv.allocId();
750 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
751 .id_result_type = self.typeId(ty_ref),
752 .id_result = constituents_id,
753 .constituents = elem_ids,
754 });
755 return constituents_id;
756 },
757 else => {},
758 }
759
714760 const ty = self.spv.cache.lookup(ty_ref).float_type;
715761 return switch (ty.bits) {
716762 16 => try self.spv.resolveId(.{ .float = .{ .ty = ty_ref, .value = .{ .float16 = @floatCast(value) } } }),
......@@ -726,9 +772,9 @@ const DeclGen = struct {
726772 /// if the parameters are in indirect representation, then the result is too.
727773 fn constructComposite(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
728774 const constituents_id = self.spv.allocId();
729 const type_id = try self.resolveTypeId(ty);
775 const type_id = try self.resolveType(ty, .direct);
730776 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
731 .id_result_type = type_id,
777 .id_result_type = self.typeId(type_id),
732778 .id_result = constituents_id,
733779 .constituents = constituents,
734780 });
......@@ -1448,12 +1494,11 @@ const DeclGen = struct {
14481494 const elem_ty = ty.childType(mod);
14491495 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
14501496 const len = ty.vectorLen(mod);
1451 const is_scalar = elem_ty.isNumeric(mod) or elem_ty.toIntern() == .bool_type;
14521497
1453 const ty_ref = if (is_scalar and len > 1 and len <= 4)
1454 try self.spv.vectorType(ty.vectorLen(mod), elem_ty_ref)
1498 const ty_ref = if (self.isVector(ty))
1499 try self.spv.vectorType(len, elem_ty_ref)
14551500 else
1456 try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref);
1501 try self.spv.arrayType(len, elem_ty_ref);
14571502
14581503 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
14591504 return ty_ref;
......@@ -1752,18 +1797,16 @@ const DeclGen = struct {
17521797 }
17531798
17541799 /// This structure is used as helper for element-wise operations. It is intended
1755 /// to be used with both vectors and single elements.
1800 /// to be used with vectors, fake vectors (arrays) and single elements.
17561801 const WipElementWise = struct {
17571802 dg: *DeclGen,
17581803 result_ty: Type,
1804 ty: Type,
17591805 /// Always in direct representation.
1760 result_ty_ref: CacheRef,
1761 scalar_ty: Type,
1762 /// Always in direct representation.
1763 scalar_ty_ref: CacheRef,
1764 scalar_ty_id: IdRef,
1765 /// True if the input is actually a vector type.
1766 is_vector: bool,
1806 ty_ref: CacheRef,
1807 ty_id: IdRef,
1808 /// True if the input is an array type.
1809 is_array: bool,
17671810 /// The element-wise operation should fill these results before calling finalize().
17681811 /// These should all be in **direct** representation! `finalize()` will convert
17691812 /// them to indirect if required.
......@@ -1774,29 +1817,28 @@ const DeclGen = struct {
17741817 }
17751818
17761819 /// Utility function to extract the element at a particular index in an
1777 /// input vector. This type is expected to be a vector if `wip.is_vector`, and
1778 /// a scalar otherwise.
1820 /// input array. This type is expected to be a fake vector (array) if `wip.is_array`, and
1821 /// a vector or scalar otherwise.
17791822 fn elementAt(wip: WipElementWise, ty: Type, value: IdRef, index: usize) !IdRef {
17801823 const mod = wip.dg.module;
1781 if (wip.is_vector) {
1824 if (wip.is_array) {
17821825 assert(ty.isVector(mod));
17831826 return try wip.dg.extractField(ty.childType(mod), value, @intCast(index));
17841827 } else {
1785 assert(!ty.isVector(mod));
17861828 assert(index == 0);
17871829 return value;
17881830 }
17891831 }
17901832
1791 /// Turns the results of this WipElementWise into a result. This can either
1792 /// be a vector or single element, depending on `result_ty`.
1833 /// Turns the results of this WipElementWise into a result. This can be
1834 /// vectors, fake vectors (arrays) and single elements, depending on `result_ty`.
17931835 /// After calling this function, this WIP is no longer usable.
17941836 /// Results is in `direct` representation.
17951837 fn finalize(wip: *WipElementWise) !IdRef {
1796 if (wip.is_vector) {
1838 if (wip.is_array) {
17971839 // Convert all the constituents to indirect, as required for the array.
17981840 for (wip.results) |*result| {
1799 result.* = try wip.dg.convertToIndirect(wip.scalar_ty, result.*);
1841 result.* = try wip.dg.convertToIndirect(wip.ty, result.*);
18001842 }
18011843 return try wip.dg.constructComposite(wip.result_ty, wip.results);
18021844 } else {
......@@ -1806,33 +1848,30 @@ const DeclGen = struct {
18061848
18071849 /// Allocate a result id at a particular index, and return it.
18081850 fn allocId(wip: *WipElementWise, index: usize) IdRef {
1809 assert(wip.is_vector or index == 0);
1851 assert(wip.is_array or index == 0);
18101852 wip.results[index] = wip.dg.spv.allocId();
18111853 return wip.results[index];
18121854 }
18131855 };
18141856
18151857 /// Create a new element-wise operation.
1816 fn elementWise(self: *DeclGen, result_ty: Type) !WipElementWise {
1858 fn elementWise(self: *DeclGen, result_ty: Type, force_element_wise: bool) !WipElementWise {
18171859 const mod = self.module;
1818 // For now, this operation also reasons in terms of `.direct` representation.
1819 const result_ty_ref = try self.resolveType(result_ty, .direct);
1820 const is_vector = result_ty.isVector(mod);
1821 const num_results = if (is_vector) result_ty.vectorLen(mod) else 1;
1860 const is_array = result_ty.isVector(mod) and (!self.isVector(result_ty) or force_element_wise);
1861 const num_results = if (is_array) result_ty.vectorLen(mod) else 1;
18221862 const results = try self.gpa.alloc(IdRef, num_results);
1823 for (results) |*result| result.* = undefined;
1863 @memset(results, undefined);
18241864
1825 const scalar_ty = result_ty.scalarType(mod);
1826 const scalar_ty_ref = try self.resolveType(scalar_ty, .direct);
1865 const ty = if (is_array) result_ty.scalarType(mod) else result_ty;
1866 const ty_ref = try self.resolveType(ty, .direct);
18271867
18281868 return .{
18291869 .dg = self,
18301870 .result_ty = result_ty,
1831 .result_ty_ref = result_ty_ref,
1832 .scalar_ty = scalar_ty,
1833 .scalar_ty_ref = scalar_ty_ref,
1834 .scalar_ty_id = self.typeId(scalar_ty_ref),
1835 .is_vector = is_vector,
1871 .ty = ty,
1872 .ty_ref = ty_ref,
1873 .ty_id = self.typeId(ty_ref),
1874 .is_array = is_array,
18361875 .results = results,
18371876 };
18381877 }
......@@ -2160,7 +2199,6 @@ const DeclGen = struct {
21602199 fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void {
21612200 const mod = self.module;
21622201 const ip = &mod.intern_pool;
2163 // TODO: remove now-redundant isUnused calls from AIR handler functions
21642202 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
21652203 return;
21662204
......@@ -2312,11 +2350,11 @@ const DeclGen = struct {
23122350 }
23132351
23142352 fn binOpSimple(self: *DeclGen, ty: Type, lhs_id: IdRef, rhs_id: IdRef, comptime opcode: Opcode) !IdRef {
2315 var wip = try self.elementWise(ty);
2353 var wip = try self.elementWise(ty, false);
23162354 defer wip.deinit();
23172355 for (0..wip.results.len) |i| {
23182356 try self.func.body.emit(self.spv.gpa, opcode, .{
2319 .id_result_type = wip.scalar_ty_id,
2357 .id_result_type = wip.ty_id,
23202358 .id_result = wip.allocId(i),
23212359 .operand_1 = try wip.elementAt(ty, lhs_id, i),
23222360 .operand_2 = try wip.elementAt(ty, rhs_id, i),
......@@ -2326,8 +2364,6 @@ const DeclGen = struct {
23262364 }
23272365
23282366 fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef {
2329 if (self.liveness.isUnused(inst)) return null;
2330
23312367 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
23322368 const lhs_id = try self.resolve(bin_op.lhs);
23332369 const rhs_id = try self.resolve(bin_op.rhs);
......@@ -2337,7 +2373,6 @@ const DeclGen = struct {
23372373 }
23382374
23392375 fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime unsigned: Opcode, comptime signed: Opcode) !?IdRef {
2340 if (self.liveness.isUnused(inst)) return null;
23412376 const mod = self.module;
23422377 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
23432378 const lhs_id = try self.resolve(bin_op.lhs);
......@@ -2345,7 +2380,7 @@ const DeclGen = struct {
23452380
23462381 const result_ty = self.typeOfIndex(inst);
23472382 const shift_ty = self.typeOf(bin_op.rhs);
2348 const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct);
2383 const shift_ty_ref = try self.resolveType(shift_ty, .direct);
23492384
23502385 const info = self.arithmeticTypeInfo(result_ty);
23512386 switch (info.class) {
......@@ -2354,7 +2389,7 @@ const DeclGen = struct {
23542389 .float, .bool => unreachable,
23552390 }
23562391
2357 var wip = try self.elementWise(result_ty);
2392 var wip = try self.elementWise(result_ty, false);
23582393 defer wip.deinit();
23592394 for (wip.results, 0..) |*result_id, i| {
23602395 const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i);
......@@ -2362,10 +2397,10 @@ const DeclGen = struct {
23622397
23632398 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,
23642399 // so just manually upcast it if required.
2365 const shift_id = if (scalar_shift_ty_ref != wip.scalar_ty_ref) blk: {
2400 const shift_id = if (shift_ty_ref != wip.ty_ref) blk: {
23662401 const shift_id = self.spv.allocId();
23672402 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
2368 .id_result_type = wip.scalar_ty_id,
2403 .id_result_type = wip.ty_id,
23692404 .id_result = shift_id,
23702405 .unsigned_value = rhs_elem_id,
23712406 });
......@@ -2374,7 +2409,7 @@ const DeclGen = struct {
23742409
23752410 const value_id = self.spv.allocId();
23762411 const args = .{
2377 .id_result_type = wip.scalar_ty_id,
2412 .id_result_type = wip.ty_id,
23782413 .id_result = value_id,
23792414 .base = lhs_elem_id,
23802415 .shift = shift_id,
......@@ -2386,14 +2421,12 @@ const DeclGen = struct {
23862421 try self.func.body.emit(self.spv.gpa, unsigned, args);
23872422 }
23882423
2389 result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, info);
2424 result_id.* = try self.normalize(wip.ty_ref, value_id, info);
23902425 }
23912426 return try wip.finalize();
23922427 }
23932428
23942429 fn airMinMax(self: *DeclGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !?IdRef {
2395 if (self.liveness.isUnused(inst)) return null;
2396
23972430 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
23982431 const lhs_id = try self.resolve(bin_op.lhs);
23992432 const rhs_id = try self.resolve(bin_op.rhs);
......@@ -2405,14 +2438,14 @@ const DeclGen = struct {
24052438 fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef {
24062439 const info = self.arithmeticTypeInfo(result_ty);
24072440
2408 var wip = try self.elementWise(result_ty);
2441 var wip = try self.elementWise(result_ty, true);
24092442 defer wip.deinit();
24102443 for (wip.results, 0..) |*result_id, i| {
24112444 const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i);
24122445 const rhs_elem_id = try wip.elementAt(result_ty, rhs_id, i);
24132446
24142447 // TODO: Use fmin for OpenCL
2415 const cmp_id = try self.cmp(op, Type.bool, wip.scalar_ty, lhs_elem_id, rhs_elem_id);
2448 const cmp_id = try self.cmp(op, Type.bool, wip.ty, lhs_elem_id, rhs_elem_id);
24162449 const selection_id = switch (info.class) {
24172450 .float => blk: {
24182451 // cmp uses OpFOrd. When we have 0 [<>] nan this returns false,
......@@ -2440,7 +2473,7 @@ const DeclGen = struct {
24402473
24412474 result_id.* = self.spv.allocId();
24422475 try self.func.body.emit(self.spv.gpa, .OpSelect, .{
2443 .id_result_type = wip.scalar_ty_id,
2476 .id_result_type = wip.ty_id,
24442477 .id_result = result_id.*,
24452478 .condition = selection_id,
24462479 .object_1 = lhs_elem_id,
......@@ -2505,7 +2538,6 @@ const DeclGen = struct {
25052538 comptime sop: Opcode,
25062539 comptime uop: Opcode,
25072540 ) !?IdRef {
2508 if (self.liveness.isUnused(inst)) return null;
25092541
25102542 // LHS and RHS are guaranteed to have the same type, and AIR guarantees
25112543 // the result to be the same as the LHS and RHS, which matches SPIR-V.
......@@ -2545,7 +2577,7 @@ const DeclGen = struct {
25452577 .bool => unreachable,
25462578 };
25472579
2548 var wip = try self.elementWise(ty);
2580 var wip = try self.elementWise(ty, false);
25492581 defer wip.deinit();
25502582 for (wip.results, 0..) |*result_id, i| {
25512583 const lhs_elem_id = try wip.elementAt(ty, lhs_id, i);
......@@ -2553,7 +2585,7 @@ const DeclGen = struct {
25532585
25542586 const value_id = self.spv.allocId();
25552587 const operands = .{
2556 .id_result_type = wip.scalar_ty_id,
2588 .id_result_type = wip.ty_id,
25572589 .id_result = value_id,
25582590 .operand_1 = lhs_elem_id,
25592591 .operand_2 = rhs_elem_id,
......@@ -2568,26 +2600,24 @@ const DeclGen = struct {
25682600
25692601 // TODO: Trap on overflow? Probably going to be annoying.
25702602 // TODO: Look into SPV_KHR_no_integer_wrap_decoration which provides NoSignedWrap/NoUnsignedWrap.
2571 result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, info);
2603 result_id.* = try self.normalize(wip.ty_ref, value_id, info);
25722604 }
25732605
25742606 return try wip.finalize();
25752607 }
25762608
25772609 fn airAbs(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2578 if (self.liveness.isUnused(inst)) return null;
2579
25802610 const mod = self.module;
25812611 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
25822612 const operand_id = try self.resolve(ty_op.operand);
25832613 // Note: operand_ty may be signed, while ty is always unsigned!
25842614 const operand_ty = self.typeOf(ty_op.operand);
2585 const ty = self.typeOfIndex(inst);
2586 const info = self.arithmeticTypeInfo(ty);
2615 const result_ty = self.typeOfIndex(inst);
2616 const info = self.arithmeticTypeInfo(result_ty);
25872617 const operand_scalar_ty = operand_ty.scalarType(mod);
25882618 const operand_scalar_ty_ref = try self.resolveType(operand_scalar_ty, .direct);
25892619
2590 var wip = try self.elementWise(ty);
2620 var wip = try self.elementWise(result_ty, true);
25912621 defer wip.deinit();
25922622
25932623 const zero_id = switch (info.class) {
......@@ -2615,7 +2645,7 @@ const DeclGen = struct {
26152645 .composite_integer => unreachable, // TODO
26162646 .bool => unreachable,
26172647 }
2618 const neg_norm_id = try self.normalize(wip.scalar_ty_ref, neg_id, info);
2648 const neg_norm_id = try self.normalize(wip.ty_ref, neg_id, info);
26192649
26202650 const gt_zero_id = try self.cmp(.gt, Type.bool, operand_scalar_ty, elem_id, zero_id);
26212651 const abs_id = self.spv.allocId();
......@@ -2627,7 +2657,7 @@ const DeclGen = struct {
26272657 .object_2 = neg_norm_id,
26282658 });
26292659 // For Shader, we may need to cast from signed to unsigned here.
2630 result_id.* = try self.bitCast(wip.scalar_ty, operand_scalar_ty, abs_id);
2660 result_id.* = try self.bitCast(wip.ty, operand_scalar_ty, abs_id);
26312661 }
26322662 return try wip.finalize();
26332663 }
......@@ -2639,8 +2669,7 @@ const DeclGen = struct {
26392669 comptime ucmp: Opcode,
26402670 comptime scmp: Opcode,
26412671 ) !?IdRef {
2642 if (self.liveness.isUnused(inst)) return null;
2643
2672 const mod = self.module;
26442673 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
26452674 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
26462675 const lhs = try self.resolve(extra.lhs);
......@@ -2651,6 +2680,10 @@ const DeclGen = struct {
26512680 const ov_ty = result_ty.structFieldType(1, self.module);
26522681
26532682 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
2683 const cmp_ty_ref = if (self.isVector(operand_ty))
2684 try self.spv.vectorType(operand_ty.vectorLen(mod), bool_ty_ref)
2685 else
2686 bool_ty_ref;
26542687
26552688 const info = self.arithmeticTypeInfo(operand_ty);
26562689 switch (info.class) {
......@@ -2659,9 +2692,9 @@ const DeclGen = struct {
26592692 .float, .bool => unreachable,
26602693 }
26612694
2662 var wip_result = try self.elementWise(operand_ty);
2695 var wip_result = try self.elementWise(operand_ty, false);
26632696 defer wip_result.deinit();
2664 var wip_ov = try self.elementWise(ov_ty);
2697 var wip_ov = try self.elementWise(ov_ty, false);
26652698 defer wip_ov.deinit();
26662699 for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| {
26672700 const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i);
......@@ -2671,14 +2704,14 @@ const DeclGen = struct {
26712704 const value_id = self.spv.allocId();
26722705
26732706 try self.func.body.emit(self.spv.gpa, add, .{
2674 .id_result_type = wip_result.scalar_ty_id,
2707 .id_result_type = wip_result.ty_id,
26752708 .id_result = value_id,
26762709 .operand_1 = lhs_elem_id,
26772710 .operand_2 = rhs_elem_id,
26782711 });
26792712
26802713 // Normalize the result so that the comparisons go well
2681 result_id.* = try self.normalize(wip_result.scalar_ty_ref, value_id, info);
2714 result_id.* = try self.normalize(wip_result.ty_ref, value_id, info);
26822715
26832716 const overflowed_id = switch (info.signedness) {
26842717 .unsigned => blk: {
......@@ -2686,7 +2719,7 @@ const DeclGen = struct {
26862719 // For subtraction the conditions need to be swapped.
26872720 const overflowed_id = self.spv.allocId();
26882721 try self.func.body.emit(self.spv.gpa, ucmp, .{
2689 .id_result_type = self.typeId(bool_ty_ref),
2722 .id_result_type = self.typeId(cmp_ty_ref),
26902723 .id_result = overflowed_id,
26912724 .operand_1 = result_id.*,
26922725 .operand_2 = lhs_elem_id,
......@@ -2712,9 +2745,9 @@ const DeclGen = struct {
27122745 // = (rhs < 0) == (lhs > value)
27132746
27142747 const rhs_lt_zero_id = self.spv.allocId();
2715 const zero_id = try self.constInt(wip_result.scalar_ty_ref, 0);
2748 const zero_id = try self.constInt(wip_result.ty_ref, 0);
27162749 try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{
2717 .id_result_type = self.typeId(bool_ty_ref),
2750 .id_result_type = self.typeId(cmp_ty_ref),
27182751 .id_result = rhs_lt_zero_id,
27192752 .operand_1 = rhs_elem_id,
27202753 .operand_2 = zero_id,
......@@ -2722,7 +2755,7 @@ const DeclGen = struct {
27222755
27232756 const value_gt_lhs_id = self.spv.allocId();
27242757 try self.func.body.emit(self.spv.gpa, scmp, .{
2725 .id_result_type = self.typeId(bool_ty_ref),
2758 .id_result_type = self.typeId(cmp_ty_ref),
27262759 .id_result = value_gt_lhs_id,
27272760 .operand_1 = lhs_elem_id,
27282761 .operand_2 = result_id.*,
......@@ -2730,7 +2763,7 @@ const DeclGen = struct {
27302763
27312764 const overflowed_id = self.spv.allocId();
27322765 try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{
2733 .id_result_type = self.typeId(bool_ty_ref),
2766 .id_result_type = self.typeId(cmp_ty_ref),
27342767 .id_result = overflowed_id,
27352768 .operand_1 = rhs_lt_zero_id,
27362769 .operand_2 = value_gt_lhs_id,
......@@ -2739,7 +2772,7 @@ const DeclGen = struct {
27392772 },
27402773 };
27412774
2742 ov_id.* = try self.intFromBool(wip_ov.scalar_ty_ref, overflowed_id);
2775 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
27432776 }
27442777
27452778 return try self.constructComposite(
......@@ -2749,7 +2782,6 @@ const DeclGen = struct {
27492782 }
27502783
27512784 fn airShlOverflow(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2752 if (self.liveness.isUnused(inst)) return null;
27532785 const mod = self.module;
27542786 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
27552787 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
......@@ -2759,11 +2791,15 @@ const DeclGen = struct {
27592791 const result_ty = self.typeOfIndex(inst);
27602792 const operand_ty = self.typeOf(extra.lhs);
27612793 const shift_ty = self.typeOf(extra.rhs);
2762 const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct);
2794 const shift_ty_ref = try self.resolveType(shift_ty, .direct);
27632795
27642796 const ov_ty = result_ty.structFieldType(1, self.module);
27652797
27662798 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
2799 const cmp_ty_ref = if (self.isVector(operand_ty))
2800 try self.spv.vectorType(operand_ty.vectorLen(mod), bool_ty_ref)
2801 else
2802 bool_ty_ref;
27672803
27682804 const info = self.arithmeticTypeInfo(operand_ty);
27692805 switch (info.class) {
......@@ -2772,9 +2808,9 @@ const DeclGen = struct {
27722808 .float, .bool => unreachable,
27732809 }
27742810
2775 var wip_result = try self.elementWise(operand_ty);
2811 var wip_result = try self.elementWise(operand_ty, false);
27762812 defer wip_result.deinit();
2777 var wip_ov = try self.elementWise(ov_ty);
2813 var wip_ov = try self.elementWise(ov_ty, false);
27782814 defer wip_ov.deinit();
27792815 for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| {
27802816 const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i);
......@@ -2782,10 +2818,10 @@ const DeclGen = struct {
27822818
27832819 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,
27842820 // so just manually upcast it if required.
2785 const shift_id = if (scalar_shift_ty_ref != wip_result.scalar_ty_ref) blk: {
2821 const shift_id = if (shift_ty_ref != wip_result.ty_ref) blk: {
27862822 const shift_id = self.spv.allocId();
27872823 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
2788 .id_result_type = wip_result.scalar_ty_id,
2824 .id_result_type = wip_result.ty_id,
27892825 .id_result = shift_id,
27902826 .unsigned_value = rhs_elem_id,
27912827 });
......@@ -2794,18 +2830,18 @@ const DeclGen = struct {
27942830
27952831 const value_id = self.spv.allocId();
27962832 try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{
2797 .id_result_type = wip_result.scalar_ty_id,
2833 .id_result_type = wip_result.ty_id,
27982834 .id_result = value_id,
27992835 .base = lhs_elem_id,
28002836 .shift = shift_id,
28012837 });
2802 result_id.* = try self.normalize(wip_result.scalar_ty_ref, value_id, info);
2838 result_id.* = try self.normalize(wip_result.ty_ref, value_id, info);
28032839
28042840 const right_shift_id = self.spv.allocId();
28052841 switch (info.signedness) {
28062842 .signed => {
28072843 try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{
2808 .id_result_type = wip_result.scalar_ty_id,
2844 .id_result_type = wip_result.ty_id,
28092845 .id_result = right_shift_id,
28102846 .base = result_id.*,
28112847 .shift = shift_id,
......@@ -2813,7 +2849,7 @@ const DeclGen = struct {
28132849 },
28142850 .unsigned => {
28152851 try self.func.body.emit(self.spv.gpa, .OpShiftRightLogical, .{
2816 .id_result_type = wip_result.scalar_ty_id,
2852 .id_result_type = wip_result.ty_id,
28172853 .id_result = right_shift_id,
28182854 .base = result_id.*,
28192855 .shift = shift_id,
......@@ -2823,13 +2859,13 @@ const DeclGen = struct {
28232859
28242860 const overflowed_id = self.spv.allocId();
28252861 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
2826 .id_result_type = self.typeId(bool_ty_ref),
2862 .id_result_type = self.typeId(cmp_ty_ref),
28272863 .id_result = overflowed_id,
28282864 .operand_1 = lhs_elem_id,
28292865 .operand_2 = right_shift_id,
28302866 });
28312867
2832 ov_id.* = try self.intFromBool(wip_ov.scalar_ty_ref, overflowed_id);
2868 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
28332869 }
28342870
28352871 return try self.constructComposite(
......@@ -2839,8 +2875,6 @@ const DeclGen = struct {
28392875 }
28402876
28412877 fn airMulAdd(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2842 if (self.liveness.isUnused(inst)) return null;
2843
28442878 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
28452879 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
28462880
......@@ -2853,19 +2887,19 @@ const DeclGen = struct {
28532887 const info = self.arithmeticTypeInfo(ty);
28542888 assert(info.class == .float); // .mul_add is only emitted for floats
28552889
2856 var wip = try self.elementWise(ty);
2890 var wip = try self.elementWise(ty, false);
28572891 defer wip.deinit();
28582892 for (0..wip.results.len) |i| {
28592893 const mul_result = self.spv.allocId();
28602894 try self.func.body.emit(self.spv.gpa, .OpFMul, .{
2861 .id_result_type = wip.scalar_ty_id,
2895 .id_result_type = wip.ty_id,
28622896 .id_result = mul_result,
28632897 .operand_1 = try wip.elementAt(ty, mulend1, i),
28642898 .operand_2 = try wip.elementAt(ty, mulend2, i),
28652899 });
28662900
28672901 try self.func.body.emit(self.spv.gpa, .OpFAdd, .{
2868 .id_result_type = wip.scalar_ty_id,
2902 .id_result_type = wip.ty_id,
28692903 .id_result = wip.allocId(i),
28702904 .operand_1 = mul_result,
28712905 .operand_2 = try wip.elementAt(ty, addend, i),
......@@ -2875,20 +2909,16 @@ const DeclGen = struct {
28752909 }
28762910
28772911 fn airSplat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2878 if (self.liveness.isUnused(inst)) return null;
28792912 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
28802913 const operand_id = try self.resolve(ty_op.operand);
28812914 const result_ty = self.typeOfIndex(inst);
2882 var wip = try self.elementWise(result_ty);
2915 var wip = try self.elementWise(result_ty, true);
28832916 defer wip.deinit();
2884 for (wip.results) |*result_id| {
2885 result_id.* = operand_id;
2886 }
2917 @memset(wip.results, operand_id);
28872918 return try wip.finalize();
28882919 }
28892920
28902921 fn airReduce(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2891 if (self.liveness.isUnused(inst)) return null;
28922922 const mod = self.module;
28932923 const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
28942924 const operand = try self.resolve(reduce.operand);
......@@ -2956,7 +2986,6 @@ const DeclGen = struct {
29562986
29572987 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
29582988 const mod = self.module;
2959 if (self.liveness.isUnused(inst)) return null;
29602989 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
29612990 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
29622991 const a = try self.resolve(extra.a);
......@@ -2965,20 +2994,20 @@ const DeclGen = struct {
29652994
29662995 const ty = self.typeOfIndex(inst);
29672996
2968 var wip = try self.elementWise(ty);
2997 var wip = try self.elementWise(ty, true);
29692998 defer wip.deinit();
29702999 for (wip.results, 0..) |*result_id, i| {
29713000 const elem = try mask.elemValue(mod, i);
29723001 if (elem.isUndef(mod)) {
2973 result_id.* = try self.spv.constUndef(wip.scalar_ty_ref);
3002 result_id.* = try self.spv.constUndef(wip.ty_ref);
29743003 continue;
29753004 }
29763005
29773006 const index = elem.toSignedInt(mod);
29783007 if (index >= 0) {
2979 result_id.* = try self.extractField(wip.scalar_ty, a, @intCast(index));
3008 result_id.* = try self.extractField(wip.ty, a, @intCast(index));
29803009 } else {
2981 result_id.* = try self.extractField(wip.scalar_ty, b, @intCast(~index));
3010 result_id.* = try self.extractField(wip.ty, b, @intCast(~index));
29823011 }
29833012 }
29843013 return try wip.finalize();
......@@ -3069,7 +3098,6 @@ const DeclGen = struct {
30693098 }
30703099
30713100 fn airPtrAdd(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3072 if (self.liveness.isUnused(inst)) return null;
30733101 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
30743102 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
30753103 const ptr_id = try self.resolve(bin_op.lhs);
......@@ -3081,7 +3109,6 @@ const DeclGen = struct {
30813109 }
30823110
30833111 fn airPtrSub(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3084 if (self.liveness.isUnused(inst)) return null;
30853112 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
30863113 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
30873114 const ptr_id = try self.resolve(bin_op.lhs);
......@@ -3188,7 +3215,7 @@ const DeclGen = struct {
31883215 return result_id;
31893216 },
31903217 .Vector => {
3191 var wip = try self.elementWise(result_ty);
3218 var wip = try self.elementWise(result_ty, true);
31923219 defer wip.deinit();
31933220 const scalar_ty = ty.scalarType(mod);
31943221 for (wip.results, 0..) |*result_id, i| {
......@@ -3257,7 +3284,6 @@ const DeclGen = struct {
32573284 inst: Air.Inst.Index,
32583285 comptime op: std.math.CompareOperator,
32593286 ) !?IdRef {
3260 if (self.liveness.isUnused(inst)) return null;
32613287 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
32623288 const lhs_id = try self.resolve(bin_op.lhs);
32633289 const rhs_id = try self.resolve(bin_op.rhs);
......@@ -3268,8 +3294,6 @@ const DeclGen = struct {
32683294 }
32693295
32703296 fn airVectorCmp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3271 if (self.liveness.isUnused(inst)) return null;
3272
32733297 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
32743298 const vec_cmp = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
32753299 const lhs_id = try self.resolve(vec_cmp.lhs);
......@@ -3351,7 +3375,6 @@ const DeclGen = struct {
33513375 }
33523376
33533377 fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3354 if (self.liveness.isUnused(inst)) return null;
33553378 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
33563379 const operand_id = try self.resolve(ty_op.operand);
33573380 const operand_ty = self.typeOf(ty_op.operand);
......@@ -3360,8 +3383,6 @@ const DeclGen = struct {
33603383 }
33613384
33623385 fn airIntCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3363 if (self.liveness.isUnused(inst)) return null;
3364
33653386 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
33663387 const operand_id = try self.resolve(ty_op.operand);
33673388 const src_ty = self.typeOf(ty_op.operand);
......@@ -3374,19 +3395,19 @@ const DeclGen = struct {
33743395 return operand_id;
33753396 }
33763397
3377 var wip = try self.elementWise(dst_ty);
3398 var wip = try self.elementWise(dst_ty, false);
33783399 defer wip.deinit();
33793400 for (wip.results, 0..) |*result_id, i| {
33803401 const elem_id = try wip.elementAt(src_ty, operand_id, i);
33813402 const value_id = self.spv.allocId();
33823403 switch (dst_info.signedness) {
33833404 .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{
3384 .id_result_type = wip.scalar_ty_id,
3405 .id_result_type = wip.ty_id,
33853406 .id_result = value_id,
33863407 .signed_value = elem_id,
33873408 }),
33883409 .unsigned => try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
3389 .id_result_type = wip.scalar_ty_id,
3410 .id_result_type = wip.ty_id,
33903411 .id_result = value_id,
33913412 .unsigned_value = elem_id,
33923413 }),
......@@ -3397,7 +3418,7 @@ const DeclGen = struct {
33973418 // type, we don't need to normalize when growing the type. The
33983419 // representation is already the same.
33993420 if (dst_info.bits < src_info.bits) {
3400 result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, dst_info);
3421 result_id.* = try self.normalize(wip.ty_ref, value_id, dst_info);
34013422 } else {
34023423 result_id.* = value_id;
34033424 }
......@@ -3417,16 +3438,12 @@ const DeclGen = struct {
34173438 }
34183439
34193440 fn airIntFromPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3420 if (self.liveness.isUnused(inst)) return null;
3421
34223441 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
34233442 const operand_id = try self.resolve(un_op);
34243443 return try self.intFromPtr(operand_id);
34253444 }
34263445
34273446 fn airFloatFromInt(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3428 if (self.liveness.isUnused(inst)) return null;
3429
34303447 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
34313448 const operand_ty = self.typeOf(ty_op.operand);
34323449 const operand_id = try self.resolve(ty_op.operand);
......@@ -3451,8 +3468,6 @@ const DeclGen = struct {
34513468 }
34523469
34533470 fn airIntFromFloat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3454 if (self.liveness.isUnused(inst)) return null;
3455
34563471 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
34573472 const operand_id = try self.resolve(ty_op.operand);
34583473 const dest_ty = self.typeOfIndex(inst);
......@@ -3476,24 +3491,20 @@ const DeclGen = struct {
34763491 }
34773492
34783493 fn airIntFromBool(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3479 if (self.liveness.isUnused(inst)) return null;
3480
34813494 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
34823495 const operand_id = try self.resolve(un_op);
34833496 const result_ty = self.typeOfIndex(inst);
34843497
3485 var wip = try self.elementWise(result_ty);
3498 var wip = try self.elementWise(result_ty, false);
34863499 defer wip.deinit();
34873500 for (wip.results, 0..) |*result_id, i| {
34883501 const elem_id = try wip.elementAt(Type.bool, operand_id, i);
3489 result_id.* = try self.intFromBool(wip.scalar_ty_ref, elem_id);
3502 result_id.* = try self.intFromBool(wip.ty_ref, elem_id);
34903503 }
34913504 return try wip.finalize();
34923505 }
34933506
34943507 fn airFloatCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3495 if (self.liveness.isUnused(inst)) return null;
3496
34973508 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
34983509 const operand_id = try self.resolve(ty_op.operand);
34993510 const dest_ty = self.typeOfIndex(inst);
......@@ -3509,18 +3520,17 @@ const DeclGen = struct {
35093520 }
35103521
35113522 fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3512 if (self.liveness.isUnused(inst)) return null;
35133523 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
35143524 const operand_id = try self.resolve(ty_op.operand);
35153525 const result_ty = self.typeOfIndex(inst);
35163526 const info = self.arithmeticTypeInfo(result_ty);
35173527
3518 var wip = try self.elementWise(result_ty);
3528 var wip = try self.elementWise(result_ty, false);
35193529 defer wip.deinit();
35203530
35213531 for (0..wip.results.len) |i| {
35223532 const args = .{
3523 .id_result_type = wip.scalar_ty_id,
3533 .id_result_type = wip.ty_id,
35243534 .id_result = wip.allocId(i),
35253535 .operand = try wip.elementAt(result_ty, operand_id, i),
35263536 };
......@@ -3541,8 +3551,6 @@ const DeclGen = struct {
35413551 }
35423552
35433553 fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3544 if (self.liveness.isUnused(inst)) return null;
3545
35463554 const mod = self.module;
35473555 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
35483556 const array_ptr_ty = self.typeOf(ty_op.operand);
......@@ -3563,15 +3571,10 @@ const DeclGen = struct {
35633571 // Convert the pointer-to-array to a pointer to the first element.
35643572 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});
35653573
3566 return try self.constructComposite(
3567 slice_ty,
3568 &.{ elem_ptr_id, len_id },
3569 );
3574 return try self.constructComposite(slice_ty, &.{ elem_ptr_id, len_id });
35703575 }
35713576
35723577 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3573 if (self.liveness.isUnused(inst)) return null;
3574
35753578 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
35763579 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
35773580 const ptr_id = try self.resolve(bin_op.lhs);
......@@ -3580,15 +3583,10 @@ const DeclGen = struct {
35803583
35813584 // Note: Types should not need to be converted to direct, these types
35823585 // dont need to be converted.
3583 return try self.constructComposite(
3584 slice_ty,
3585 &.{ ptr_id, len_id },
3586 );
3586 return try self.constructComposite(slice_ty, &.{ ptr_id, len_id });
35873587 }
35883588
35893589 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3590 if (self.liveness.isUnused(inst)) return null;
3591
35923590 const mod = self.module;
35933591 const ip = &mod.intern_pool;
35943592 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
......@@ -3710,7 +3708,6 @@ const DeclGen = struct {
37103708 }
37113709
37123710 fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {
3713 if (self.liveness.isUnused(inst)) return null;
37143711 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
37153712 const field_ty = self.typeOfIndex(inst);
37163713 const operand_id = try self.resolve(ty_op.operand);
......@@ -3767,8 +3764,6 @@ const DeclGen = struct {
37673764 }
37683765
37693766 fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3770 if (self.liveness.isUnused(inst)) return null;
3771
37723767 const mod = self.module;
37733768 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
37743769 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
......@@ -3786,8 +3781,6 @@ const DeclGen = struct {
37863781 }
37873782
37883783 fn airArrayElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3789 if (self.liveness.isUnused(inst)) return null;
3790
37913784 const mod = self.module;
37923785 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
37933786 const array_ty = self.typeOf(bin_op.lhs);
......@@ -3808,8 +3801,6 @@ const DeclGen = struct {
38083801 }
38093802
38103803 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3811 if (self.liveness.isUnused(inst)) return null;
3812
38133804 const mod = self.module;
38143805 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
38153806 const ptr_ty = self.typeOf(bin_op.lhs);
......@@ -3866,8 +3857,6 @@ const DeclGen = struct {
38663857 }
38673858
38683859 fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3869 if (self.liveness.isUnused(inst)) return null;
3870
38713860 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
38723861 const un_ty = self.typeOf(ty_op.operand);
38733862
......@@ -3951,8 +3940,6 @@ const DeclGen = struct {
39513940 }
39523941
39533942 fn airUnionInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3954 if (self.liveness.isUnused(inst)) return null;
3955
39563943 const mod = self.module;
39573944 const ip = &mod.intern_pool;
39583945 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
......@@ -3969,8 +3956,6 @@ const DeclGen = struct {
39693956 }
39703957
39713958 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3972 if (self.liveness.isUnused(inst)) return null;
3973
39743959 const mod = self.module;
39753960 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
39763961 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
......@@ -4091,7 +4076,6 @@ const DeclGen = struct {
40914076 }
40924077
40934078 fn airStructFieldPtrIndex(self: *DeclGen, inst: Air.Inst.Index, field_index: u32) !?IdRef {
4094 if (self.liveness.isUnused(inst)) return null;
40954079 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
40964080 const struct_ptr = try self.resolve(ty_op.operand);
40974081 const struct_ptr_ty = self.typeOf(ty_op.operand);
......@@ -4145,7 +4129,6 @@ const DeclGen = struct {
41454129 }
41464130
41474131 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4148 if (self.liveness.isUnused(inst)) return null;
41494132 const mod = self.module;
41504133 const ptr_ty = self.typeOfIndex(inst);
41514134 assert(ptr_ty.ptrAddressSpace(mod) == .generic);
......@@ -4729,9 +4712,7 @@ const DeclGen = struct {
47294712
47304713 try self.beginSpvBlock(ok_block);
47314714 }
4732 if (self.liveness.isUnused(inst)) {
4733 return null;
4734 }
4715
47354716 if (!eu_layout.payload_has_bits) {
47364717 return null;
47374718 }
......@@ -4741,8 +4722,6 @@ const DeclGen = struct {
47414722 }
47424723
47434724 fn airErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4744 if (self.liveness.isUnused(inst)) return null;
4745
47464725 const mod = self.module;
47474726 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
47484727 const operand_id = try self.resolve(ty_op.operand);
......@@ -4766,8 +4745,6 @@ const DeclGen = struct {
47664745 }
47674746
47684747 fn airErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4769 if (self.liveness.isUnused(inst)) return null;
4770
47714748 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
47724749 const operand_id = try self.resolve(ty_op.operand);
47734750 const payload_ty = self.typeOfIndex(inst);
......@@ -4781,8 +4758,6 @@ const DeclGen = struct {
47814758 }
47824759
47834760 fn airWrapErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4784 if (self.liveness.isUnused(inst)) return null;
4785
47864761 const mod = self.module;
47874762 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
47884763 const err_union_ty = self.typeOfIndex(inst);
......@@ -4804,8 +4779,6 @@ const DeclGen = struct {
48044779 }
48054780
48064781 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4807 if (self.liveness.isUnused(inst)) return null;
4808
48094782 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
48104783 const err_union_ty = self.typeOfIndex(inst);
48114784 const operand_id = try self.resolve(ty_op.operand);
......@@ -4825,8 +4798,6 @@ const DeclGen = struct {
48254798 }
48264799
48274800 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef {
4828 if (self.liveness.isUnused(inst)) return null;
4829
48304801 const mod = self.module;
48314802 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
48324803 const operand_id = try self.resolve(un_op);
......@@ -4899,8 +4870,6 @@ const DeclGen = struct {
48994870 }
49004871
49014872 fn airIsErr(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_err, is_non_err }) !?IdRef {
4902 if (self.liveness.isUnused(inst)) return null;
4903
49044873 const mod = self.module;
49054874 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
49064875 const operand_id = try self.resolve(un_op);
......@@ -4935,8 +4904,6 @@ const DeclGen = struct {
49354904 }
49364905
49374906 fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4938 if (self.liveness.isUnused(inst)) return null;
4939
49404907 const mod = self.module;
49414908 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
49424909 const operand_id = try self.resolve(ty_op.operand);
......@@ -4953,8 +4920,6 @@ const DeclGen = struct {
49534920 }
49544921
49554922 fn airUnwrapOptionalPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4956 if (self.liveness.isUnused(inst)) return null;
4957
49584923 const mod = self.module;
49594924 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
49604925 const operand_id = try self.resolve(ty_op.operand);
......@@ -4979,8 +4944,6 @@ const DeclGen = struct {
49794944 }
49804945
49814946 fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
4982 if (self.liveness.isUnused(inst)) return null;
4983
49844947 const mod = self.module;
49854948 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
49864949 const payload_ty = self.typeOf(ty_op.operand);