authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2024-02-09 09:13:11+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2024-02-09 16:40:34+03:30
log5ee96688a7456b9581fa605520fe90f6723bb95b
tree7d49c0006adc1bbc1221795f012e64c12c76cb14
parentddcea2cad486684607039aab45634e0e30e7312a

spirv: emit vectorized operations


1 files changed, 154 insertions(+), 114 deletions(-)

src/codegen/spirv.zig+154-114
...@@ -629,6 +629,16 @@ const DeclGen = struct {...@@ -629,6 +629,16 @@ const DeclGen = struct {
629 return self.backingIntBits(ty) == null;629 return self.backingIntBits(ty) == null;
630 }630 }
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
632 fn arithmeticTypeInfo(self: *DeclGen, ty: Type) ArithmeticTypeInfo {642 fn arithmeticTypeInfo(self: *DeclGen, ty: Type) ArithmeticTypeInfo {
633 const mod = self.module;643 const mod = self.module;
634 const target = self.getTarget();644 const target = self.getTarget();
...@@ -694,6 +704,24 @@ const DeclGen = struct {...@@ -694,6 +704,24 @@ const DeclGen = struct {
694 /// This function, unlike SpvModule.constInt, takes care to bitcast704 /// This function, unlike SpvModule.constInt, takes care to bitcast
695 /// the value to an unsigned int first for Kernels.705 /// the value to an unsigned int first for Kernels.
696 fn constInt(self: *DeclGen, ty_ref: CacheRef, value: anytype) !IdRef {706 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
697 if (value < 0) {725 if (value < 0) {
698 const ty = self.spv.cache.lookup(ty_ref).int_type;726 const ty = self.spv.cache.lookup(ty_ref).int_type;
699 // Manually truncate the value so that the resulting value727 // Manually truncate the value so that the resulting value
...@@ -711,6 +739,24 @@ const DeclGen = struct {...@@ -711,6 +739,24 @@ const DeclGen = struct {
711739
712 /// Emits a float constant740 /// Emits a float constant
713 fn constFloat(self: *DeclGen, ty_ref: CacheRef, value: f128) !IdRef {741 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
714 const ty = self.spv.cache.lookup(ty_ref).float_type;760 const ty = self.spv.cache.lookup(ty_ref).float_type;
715 return switch (ty.bits) {761 return switch (ty.bits) {
716 16 => try self.spv.resolveId(.{ .float = .{ .ty = ty_ref, .value = .{ .float16 = @floatCast(value) } } }),762 16 => try self.spv.resolveId(.{ .float = .{ .ty = ty_ref, .value = .{ .float16 = @floatCast(value) } } }),
...@@ -726,9 +772,9 @@ const DeclGen = struct {...@@ -726,9 +772,9 @@ const DeclGen = struct {
726 /// if the parameters are in indirect representation, then the result is too.772 /// if the parameters are in indirect representation, then the result is too.
727 fn constructComposite(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {773 fn constructComposite(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
728 const constituents_id = self.spv.allocId();774 const constituents_id = self.spv.allocId();
729 const type_id = try self.resolveTypeId(ty);775 const type_id = try self.resolveType(ty, .direct);
730 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{776 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
731 .id_result_type = type_id,777 .id_result_type = self.typeId(type_id),
732 .id_result = constituents_id,778 .id_result = constituents_id,
733 .constituents = constituents,779 .constituents = constituents,
734 });780 });
...@@ -901,19 +947,19 @@ const DeclGen = struct {...@@ -901,19 +947,19 @@ const DeclGen = struct {
901 .bytes => |bytes| {947 .bytes => |bytes| {
902 // TODO: This is really space inefficient, perhaps there is a better948 // TODO: This is really space inefficient, perhaps there is a better
903 // way to do it?949 // way to do it?
904 for (bytes, 0..) |byte, i| {950 for (constituents, bytes) |*constituent, byte| {
905 constituents[i] = try self.constInt(elem_ty_ref, byte);951 constituent.* = try self.constInt(elem_ty_ref, byte);
906 }952 }
907 },953 },
908 .elems => |elems| {954 .elems => |elems| {
909 for (0..@as(usize, @intCast(array_type.len))) |i| {955 for (constituents, elems) |*constituent, elem| {
910 constituents[i] = try self.constant(elem_ty, Value.fromInterned(elems[i]), .indirect);956 constituent.* = try self.constant(elem_ty, Value.fromInterned(elem), .indirect);
911 }957 }
912 },958 },
913 .repeated_elem => |elem| {959 .repeated_elem => |elem| {
914 const val_id = try self.constant(elem_ty, Value.fromInterned(elem), .indirect);960 const val_id = try self.constant(elem_ty, Value.fromInterned(elem), .indirect);
915 for (0..@as(usize, @intCast(array_type.len))) |i| {961 for (constituents) |*constituent| {
916 constituents[i] = val_id;962 constituent.* = val_id;
917 }963 }
918 },964 },
919 }965 }
...@@ -1448,12 +1494,11 @@ const DeclGen = struct {...@@ -1448,12 +1494,11 @@ const DeclGen = struct {
1448 const elem_ty = ty.childType(mod);1494 const elem_ty = ty.childType(mod);
1449 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);1495 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
1450 const len = ty.vectorLen(mod);1496 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)1498 const ty_ref = if (self.isVector(ty))
1454 try self.spv.vectorType(ty.vectorLen(mod), elem_ty_ref)1499 try self.spv.vectorType(len, elem_ty_ref)
1455 else1500 else
1456 try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref);1501 try self.spv.arrayType(len, elem_ty_ref);
14571502
1458 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });1503 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1459 return ty_ref;1504 return ty_ref;
...@@ -1752,18 +1797,16 @@ const DeclGen = struct {...@@ -1752,18 +1797,16 @@ const DeclGen = struct {
1752 }1797 }
17531798
1754 /// This structure is used as helper for element-wise operations. It is intended1799 /// 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.
1756 const WipElementWise = struct {1801 const WipElementWise = struct {
1757 dg: *DeclGen,1802 dg: *DeclGen,
1758 result_ty: Type,1803 result_ty: Type,
1804 ty: Type,
1759 /// Always in direct representation.1805 /// Always in direct representation.
1760 result_ty_ref: CacheRef,1806 ty_ref: CacheRef,
1761 scalar_ty: Type,1807 ty_id: IdRef,
1762 /// Always in direct representation.1808 /// True if the input is an array type.
1763 scalar_ty_ref: CacheRef,1809 is_array: bool,
1764 scalar_ty_id: IdRef,
1765 /// True if the input is actually a vector type.
1766 is_vector: bool,
1767 /// The element-wise operation should fill these results before calling finalize().1810 /// The element-wise operation should fill these results before calling finalize().
1768 /// These should all be in **direct** representation! `finalize()` will convert1811 /// These should all be in **direct** representation! `finalize()` will convert
1769 /// them to indirect if required.1812 /// them to indirect if required.
...@@ -1774,29 +1817,28 @@ const DeclGen = struct {...@@ -1774,29 +1817,28 @@ const DeclGen = struct {
1774 }1817 }
17751818
1776 /// Utility function to extract the element at a particular index in an1819 /// 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`, and1820 /// input array. This type is expected to be a fake vector (array) if `wip.is_array`, and
1778 /// a scalar otherwise.1821 /// a vector or scalar otherwise.
1779 fn elementAt(wip: WipElementWise, ty: Type, value: IdRef, index: usize) !IdRef {1822 fn elementAt(wip: WipElementWise, ty: Type, value: IdRef, index: usize) !IdRef {
1780 const mod = wip.dg.module;1823 const mod = wip.dg.module;
1781 if (wip.is_vector) {1824 if (wip.is_array) {
1782 assert(ty.isVector(mod));1825 assert(ty.isVector(mod));
1783 return try wip.dg.extractField(ty.childType(mod), value, @intCast(index));1826 return try wip.dg.extractField(ty.childType(mod), value, @intCast(index));
1784 } else {1827 } else {
1785 assert(!ty.isVector(mod));
1786 assert(index == 0);1828 assert(index == 0);
1787 return value;1829 return value;
1788 }1830 }
1789 }1831 }
17901832
1791 /// Turns the results of this WipElementWise into a result. This can either1833 /// Turns the results of this WipElementWise into a result. This can be
1792 /// be a vector or single element, depending on `result_ty`.1834 /// vectors, fake vectors (arrays) and single elements, depending on `result_ty`.
1793 /// After calling this function, this WIP is no longer usable.1835 /// After calling this function, this WIP is no longer usable.
1794 /// Results is in `direct` representation.1836 /// Results is in `direct` representation.
1795 fn finalize(wip: *WipElementWise) !IdRef {1837 fn finalize(wip: *WipElementWise) !IdRef {
1796 if (wip.is_vector) {1838 if (wip.is_array) {
1797 // Convert all the constituents to indirect, as required for the array.1839 // Convert all the constituents to indirect, as required for the array.
1798 for (wip.results) |*result| {1840 for (wip.results) |*result| {
1799 result.* = try wip.dg.convertToIndirect(wip.scalar_ty, result.*);1841 result.* = try wip.dg.convertToIndirect(wip.ty, result.*);
1800 }1842 }
1801 return try wip.dg.constructComposite(wip.result_ty, wip.results);1843 return try wip.dg.constructComposite(wip.result_ty, wip.results);
1802 } else {1844 } else {
...@@ -1806,33 +1848,30 @@ const DeclGen = struct {...@@ -1806,33 +1848,30 @@ const DeclGen = struct {
18061848
1807 /// Allocate a result id at a particular index, and return it.1849 /// Allocate a result id at a particular index, and return it.
1808 fn allocId(wip: *WipElementWise, index: usize) IdRef {1850 fn allocId(wip: *WipElementWise, index: usize) IdRef {
1809 assert(wip.is_vector or index == 0);1851 assert(wip.is_array or index == 0);
1810 wip.results[index] = wip.dg.spv.allocId();1852 wip.results[index] = wip.dg.spv.allocId();
1811 return wip.results[index];1853 return wip.results[index];
1812 }1854 }
1813 };1855 };
18141856
1815 /// Create a new element-wise operation.1857 /// 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 {
1817 const mod = self.module;1859 const mod = self.module;
1818 // For now, this operation also reasons in terms of `.direct` representation.1860 const is_array = result_ty.isVector(mod) and (!self.isVector(result_ty) or force_element_wise);
1819 const result_ty_ref = try self.resolveType(result_ty, .direct);1861 const num_results = if (is_array) result_ty.vectorLen(mod) else 1;
1820 const is_vector = result_ty.isVector(mod);
1821 const num_results = if (is_vector) result_ty.vectorLen(mod) else 1;
1822 const results = try self.gpa.alloc(IdRef, num_results);1862 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);1865 const ty = if (is_array) result_ty.scalarType(mod) else result_ty;
1826 const scalar_ty_ref = try self.resolveType(scalar_ty, .direct);1866 const ty_ref = try self.resolveType(ty, .direct);
18271867
1828 return .{1868 return .{
1829 .dg = self,1869 .dg = self,
1830 .result_ty = result_ty,1870 .result_ty = result_ty,
1831 .result_ty_ref = result_ty_ref,1871 .ty = ty,
1832 .scalar_ty = scalar_ty,1872 .ty_ref = ty_ref,
1833 .scalar_ty_ref = scalar_ty_ref,1873 .ty_id = self.typeId(ty_ref),
1834 .scalar_ty_id = self.typeId(scalar_ty_ref),1874 .is_array = is_array,
1835 .is_vector = is_vector,
1836 .results = results,1875 .results = results,
1837 };1876 };
1838 }1877 }
...@@ -2312,11 +2351,11 @@ const DeclGen = struct {...@@ -2312,11 +2351,11 @@ const DeclGen = struct {
2312 }2351 }
23132352
2314 fn binOpSimple(self: *DeclGen, ty: Type, lhs_id: IdRef, rhs_id: IdRef, comptime opcode: Opcode) !IdRef {2353 fn binOpSimple(self: *DeclGen, ty: Type, lhs_id: IdRef, rhs_id: IdRef, comptime opcode: Opcode) !IdRef {
2315 var wip = try self.elementWise(ty);2354 var wip = try self.elementWise(ty, false);
2316 defer wip.deinit();2355 defer wip.deinit();
2317 for (0..wip.results.len) |i| {2356 for (0..wip.results.len) |i| {
2318 try self.func.body.emit(self.spv.gpa, opcode, .{2357 try self.func.body.emit(self.spv.gpa, opcode, .{
2319 .id_result_type = wip.scalar_ty_id,2358 .id_result_type = wip.ty_id,
2320 .id_result = wip.allocId(i),2359 .id_result = wip.allocId(i),
2321 .operand_1 = try wip.elementAt(ty, lhs_id, i),2360 .operand_1 = try wip.elementAt(ty, lhs_id, i),
2322 .operand_2 = try wip.elementAt(ty, rhs_id, i),2361 .operand_2 = try wip.elementAt(ty, rhs_id, i),
...@@ -2345,7 +2384,7 @@ const DeclGen = struct {...@@ -2345,7 +2384,7 @@ const DeclGen = struct {
23452384
2346 const result_ty = self.typeOfIndex(inst);2385 const result_ty = self.typeOfIndex(inst);
2347 const shift_ty = self.typeOf(bin_op.rhs);2386 const shift_ty = self.typeOf(bin_op.rhs);
2348 const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct);2387 const shift_ty_ref = try self.resolveType(shift_ty, .direct);
23492388
2350 const info = self.arithmeticTypeInfo(result_ty);2389 const info = self.arithmeticTypeInfo(result_ty);
2351 switch (info.class) {2390 switch (info.class) {
...@@ -2354,7 +2393,7 @@ const DeclGen = struct {...@@ -2354,7 +2393,7 @@ const DeclGen = struct {
2354 .float, .bool => unreachable,2393 .float, .bool => unreachable,
2355 }2394 }
23562395
2357 var wip = try self.elementWise(result_ty);2396 var wip = try self.elementWise(result_ty, false);
2358 defer wip.deinit();2397 defer wip.deinit();
2359 for (wip.results, 0..) |*result_id, i| {2398 for (wip.results, 0..) |*result_id, i| {
2360 const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i);2399 const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i);
...@@ -2362,10 +2401,10 @@ const DeclGen = struct {...@@ -2362,10 +2401,10 @@ const DeclGen = struct {
23622401
2363 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,2402 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,
2364 // so just manually upcast it if required.2403 // so just manually upcast it if required.
2365 const shift_id = if (scalar_shift_ty_ref != wip.scalar_ty_ref) blk: {2404 const shift_id = if (shift_ty_ref != wip.ty_ref) blk: {
2366 const shift_id = self.spv.allocId();2405 const shift_id = self.spv.allocId();
2367 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{2406 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
2368 .id_result_type = wip.scalar_ty_id,2407 .id_result_type = wip.ty_id,
2369 .id_result = shift_id,2408 .id_result = shift_id,
2370 .unsigned_value = rhs_elem_id,2409 .unsigned_value = rhs_elem_id,
2371 });2410 });
...@@ -2374,7 +2413,7 @@ const DeclGen = struct {...@@ -2374,7 +2413,7 @@ const DeclGen = struct {
23742413
2375 const value_id = self.spv.allocId();2414 const value_id = self.spv.allocId();
2376 const args = .{2415 const args = .{
2377 .id_result_type = wip.scalar_ty_id,2416 .id_result_type = wip.ty_id,
2378 .id_result = value_id,2417 .id_result = value_id,
2379 .base = lhs_elem_id,2418 .base = lhs_elem_id,
2380 .shift = shift_id,2419 .shift = shift_id,
...@@ -2386,7 +2425,7 @@ const DeclGen = struct {...@@ -2386,7 +2425,7 @@ const DeclGen = struct {
2386 try self.func.body.emit(self.spv.gpa, unsigned, args);2425 try self.func.body.emit(self.spv.gpa, unsigned, args);
2387 }2426 }
23882427
2389 result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, info);2428 result_id.* = try self.normalize(wip.ty_ref, value_id, info);
2390 }2429 }
2391 return try wip.finalize();2430 return try wip.finalize();
2392 }2431 }
...@@ -2405,14 +2444,14 @@ const DeclGen = struct {...@@ -2405,14 +2444,14 @@ const DeclGen = struct {
2405 fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef {2444 fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef {
2406 const info = self.arithmeticTypeInfo(result_ty);2445 const info = self.arithmeticTypeInfo(result_ty);
24072446
2408 var wip = try self.elementWise(result_ty);2447 var wip = try self.elementWise(result_ty, true);
2409 defer wip.deinit();2448 defer wip.deinit();
2410 for (wip.results, 0..) |*result_id, i| {2449 for (wip.results, 0..) |*result_id, i| {
2411 const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i);2450 const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i);
2412 const rhs_elem_id = try wip.elementAt(result_ty, rhs_id, i);2451 const rhs_elem_id = try wip.elementAt(result_ty, rhs_id, i);
24132452
2414 // TODO: Use fmin for OpenCL2453 // TODO: Use fmin for OpenCL
2415 const cmp_id = try self.cmp(op, Type.bool, wip.scalar_ty, lhs_elem_id, rhs_elem_id);2454 const cmp_id = try self.cmp(op, Type.bool, wip.ty, lhs_elem_id, rhs_elem_id);
2416 const selection_id = switch (info.class) {2455 const selection_id = switch (info.class) {
2417 .float => blk: {2456 .float => blk: {
2418 // cmp uses OpFOrd. When we have 0 [<>] nan this returns false,2457 // cmp uses OpFOrd. When we have 0 [<>] nan this returns false,
...@@ -2440,7 +2479,7 @@ const DeclGen = struct {...@@ -2440,7 +2479,7 @@ const DeclGen = struct {
24402479
2441 result_id.* = self.spv.allocId();2480 result_id.* = self.spv.allocId();
2442 try self.func.body.emit(self.spv.gpa, .OpSelect, .{2481 try self.func.body.emit(self.spv.gpa, .OpSelect, .{
2443 .id_result_type = wip.scalar_ty_id,2482 .id_result_type = wip.ty_id,
2444 .id_result = result_id.*,2483 .id_result = result_id.*,
2445 .condition = selection_id,2484 .condition = selection_id,
2446 .object_1 = lhs_elem_id,2485 .object_1 = lhs_elem_id,
...@@ -2545,7 +2584,7 @@ const DeclGen = struct {...@@ -2545,7 +2584,7 @@ const DeclGen = struct {
2545 .bool => unreachable,2584 .bool => unreachable,
2546 };2585 };
25472586
2548 var wip = try self.elementWise(ty);2587 var wip = try self.elementWise(ty, false);
2549 defer wip.deinit();2588 defer wip.deinit();
2550 for (wip.results, 0..) |*result_id, i| {2589 for (wip.results, 0..) |*result_id, i| {
2551 const lhs_elem_id = try wip.elementAt(ty, lhs_id, i);2590 const lhs_elem_id = try wip.elementAt(ty, lhs_id, i);
...@@ -2553,7 +2592,7 @@ const DeclGen = struct {...@@ -2553,7 +2592,7 @@ const DeclGen = struct {
25532592
2554 const value_id = self.spv.allocId();2593 const value_id = self.spv.allocId();
2555 const operands = .{2594 const operands = .{
2556 .id_result_type = wip.scalar_ty_id,2595 .id_result_type = wip.ty_id,
2557 .id_result = value_id,2596 .id_result = value_id,
2558 .operand_1 = lhs_elem_id,2597 .operand_1 = lhs_elem_id,
2559 .operand_2 = rhs_elem_id,2598 .operand_2 = rhs_elem_id,
...@@ -2568,7 +2607,7 @@ const DeclGen = struct {...@@ -2568,7 +2607,7 @@ const DeclGen = struct {
25682607
2569 // TODO: Trap on overflow? Probably going to be annoying.2608 // TODO: Trap on overflow? Probably going to be annoying.
2570 // TODO: Look into SPV_KHR_no_integer_wrap_decoration which provides NoSignedWrap/NoUnsignedWrap.2609 // 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);2610 result_id.* = try self.normalize(wip.ty_ref, value_id, info);
2572 }2611 }
25732612
2574 return try wip.finalize();2613 return try wip.finalize();
...@@ -2582,12 +2621,12 @@ const DeclGen = struct {...@@ -2582,12 +2621,12 @@ const DeclGen = struct {
2582 const operand_id = try self.resolve(ty_op.operand);2621 const operand_id = try self.resolve(ty_op.operand);
2583 // Note: operand_ty may be signed, while ty is always unsigned!2622 // Note: operand_ty may be signed, while ty is always unsigned!
2584 const operand_ty = self.typeOf(ty_op.operand);2623 const operand_ty = self.typeOf(ty_op.operand);
2585 const ty = self.typeOfIndex(inst);2624 const result_ty = self.typeOfIndex(inst);
2586 const info = self.arithmeticTypeInfo(ty);2625 const info = self.arithmeticTypeInfo(result_ty);
2587 const operand_scalar_ty = operand_ty.scalarType(mod);2626 const operand_scalar_ty = operand_ty.scalarType(mod);
2588 const operand_scalar_ty_ref = try self.resolveType(operand_scalar_ty, .direct);2627 const operand_scalar_ty_ref = try self.resolveType(operand_scalar_ty, .direct);
25892628
2590 var wip = try self.elementWise(ty);2629 var wip = try self.elementWise(result_ty, true);
2591 defer wip.deinit();2630 defer wip.deinit();
25922631
2593 const zero_id = switch (info.class) {2632 const zero_id = switch (info.class) {
...@@ -2615,7 +2654,7 @@ const DeclGen = struct {...@@ -2615,7 +2654,7 @@ const DeclGen = struct {
2615 .composite_integer => unreachable, // TODO2654 .composite_integer => unreachable, // TODO
2616 .bool => unreachable,2655 .bool => unreachable,
2617 }2656 }
2618 const neg_norm_id = try self.normalize(wip.scalar_ty_ref, neg_id, info);2657 const neg_norm_id = try self.normalize(wip.ty_ref, neg_id, info);
26192658
2620 const gt_zero_id = try self.cmp(.gt, Type.bool, operand_scalar_ty, elem_id, zero_id);2659 const gt_zero_id = try self.cmp(.gt, Type.bool, operand_scalar_ty, elem_id, zero_id);
2621 const abs_id = self.spv.allocId();2660 const abs_id = self.spv.allocId();
...@@ -2627,7 +2666,7 @@ const DeclGen = struct {...@@ -2627,7 +2666,7 @@ const DeclGen = struct {
2627 .object_2 = neg_norm_id,2666 .object_2 = neg_norm_id,
2628 });2667 });
2629 // For Shader, we may need to cast from signed to unsigned here.2668 // 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);2669 result_id.* = try self.bitCast(wip.ty, operand_scalar_ty, abs_id);
2631 }2670 }
2632 return try wip.finalize();2671 return try wip.finalize();
2633 }2672 }
...@@ -2641,6 +2680,7 @@ const DeclGen = struct {...@@ -2641,6 +2680,7 @@ const DeclGen = struct {
2641 ) !?IdRef {2680 ) !?IdRef {
2642 if (self.liveness.isUnused(inst)) return null;2681 if (self.liveness.isUnused(inst)) return null;
26432682
2683 const mod = self.module;
2644 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2684 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2645 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2685 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2646 const lhs = try self.resolve(extra.lhs);2686 const lhs = try self.resolve(extra.lhs);
...@@ -2651,6 +2691,10 @@ const DeclGen = struct {...@@ -2651,6 +2691,10 @@ const DeclGen = struct {
2651 const ov_ty = result_ty.structFieldType(1, self.module);2691 const ov_ty = result_ty.structFieldType(1, self.module);
26522692
2653 const bool_ty_ref = try self.resolveType(Type.bool, .direct);2693 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
2694 const cmp_ty_ref = if (self.isVector(operand_ty))
2695 try self.spv.vectorType(operand_ty.vectorLen(mod), bool_ty_ref)
2696 else
2697 bool_ty_ref;
26542698
2655 const info = self.arithmeticTypeInfo(operand_ty);2699 const info = self.arithmeticTypeInfo(operand_ty);
2656 switch (info.class) {2700 switch (info.class) {
...@@ -2659,9 +2703,9 @@ const DeclGen = struct {...@@ -2659,9 +2703,9 @@ const DeclGen = struct {
2659 .float, .bool => unreachable,2703 .float, .bool => unreachable,
2660 }2704 }
26612705
2662 var wip_result = try self.elementWise(operand_ty);2706 var wip_result = try self.elementWise(operand_ty, false);
2663 defer wip_result.deinit();2707 defer wip_result.deinit();
2664 var wip_ov = try self.elementWise(ov_ty);2708 var wip_ov = try self.elementWise(ov_ty, false);
2665 defer wip_ov.deinit();2709 defer wip_ov.deinit();
2666 for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| {2710 for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| {
2667 const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i);2711 const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i);
...@@ -2671,14 +2715,14 @@ const DeclGen = struct {...@@ -2671,14 +2715,14 @@ const DeclGen = struct {
2671 const value_id = self.spv.allocId();2715 const value_id = self.spv.allocId();
26722716
2673 try self.func.body.emit(self.spv.gpa, add, .{2717 try self.func.body.emit(self.spv.gpa, add, .{
2674 .id_result_type = wip_result.scalar_ty_id,2718 .id_result_type = wip_result.ty_id,
2675 .id_result = value_id,2719 .id_result = value_id,
2676 .operand_1 = lhs_elem_id,2720 .operand_1 = lhs_elem_id,
2677 .operand_2 = rhs_elem_id,2721 .operand_2 = rhs_elem_id,
2678 });2722 });
26792723
2680 // Normalize the result so that the comparisons go well2724 // Normalize the result so that the comparisons go well
2681 result_id.* = try self.normalize(wip_result.scalar_ty_ref, value_id, info);2725 result_id.* = try self.normalize(wip_result.ty_ref, value_id, info);
26822726
2683 const overflowed_id = switch (info.signedness) {2727 const overflowed_id = switch (info.signedness) {
2684 .unsigned => blk: {2728 .unsigned => blk: {
...@@ -2686,7 +2730,7 @@ const DeclGen = struct {...@@ -2686,7 +2730,7 @@ const DeclGen = struct {
2686 // For subtraction the conditions need to be swapped.2730 // For subtraction the conditions need to be swapped.
2687 const overflowed_id = self.spv.allocId();2731 const overflowed_id = self.spv.allocId();
2688 try self.func.body.emit(self.spv.gpa, ucmp, .{2732 try self.func.body.emit(self.spv.gpa, ucmp, .{
2689 .id_result_type = self.typeId(bool_ty_ref),2733 .id_result_type = self.typeId(cmp_ty_ref),
2690 .id_result = overflowed_id,2734 .id_result = overflowed_id,
2691 .operand_1 = result_id.*,2735 .operand_1 = result_id.*,
2692 .operand_2 = lhs_elem_id,2736 .operand_2 = lhs_elem_id,
...@@ -2712,9 +2756,9 @@ const DeclGen = struct {...@@ -2712,9 +2756,9 @@ const DeclGen = struct {
2712 // = (rhs < 0) == (lhs > value)2756 // = (rhs < 0) == (lhs > value)
27132757
2714 const rhs_lt_zero_id = self.spv.allocId();2758 const rhs_lt_zero_id = self.spv.allocId();
2715 const zero_id = try self.constInt(wip_result.scalar_ty_ref, 0);2759 const zero_id = try self.constInt(wip_result.ty_ref, 0);
2716 try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{2760 try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{
2717 .id_result_type = self.typeId(bool_ty_ref),2761 .id_result_type = self.typeId(cmp_ty_ref),
2718 .id_result = rhs_lt_zero_id,2762 .id_result = rhs_lt_zero_id,
2719 .operand_1 = rhs_elem_id,2763 .operand_1 = rhs_elem_id,
2720 .operand_2 = zero_id,2764 .operand_2 = zero_id,
...@@ -2722,7 +2766,7 @@ const DeclGen = struct {...@@ -2722,7 +2766,7 @@ const DeclGen = struct {
27222766
2723 const value_gt_lhs_id = self.spv.allocId();2767 const value_gt_lhs_id = self.spv.allocId();
2724 try self.func.body.emit(self.spv.gpa, scmp, .{2768 try self.func.body.emit(self.spv.gpa, scmp, .{
2725 .id_result_type = self.typeId(bool_ty_ref),2769 .id_result_type = self.typeId(cmp_ty_ref),
2726 .id_result = value_gt_lhs_id,2770 .id_result = value_gt_lhs_id,
2727 .operand_1 = lhs_elem_id,2771 .operand_1 = lhs_elem_id,
2728 .operand_2 = result_id.*,2772 .operand_2 = result_id.*,
...@@ -2730,7 +2774,7 @@ const DeclGen = struct {...@@ -2730,7 +2774,7 @@ const DeclGen = struct {
27302774
2731 const overflowed_id = self.spv.allocId();2775 const overflowed_id = self.spv.allocId();
2732 try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{2776 try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{
2733 .id_result_type = self.typeId(bool_ty_ref),2777 .id_result_type = self.typeId(cmp_ty_ref),
2734 .id_result = overflowed_id,2778 .id_result = overflowed_id,
2735 .operand_1 = rhs_lt_zero_id,2779 .operand_1 = rhs_lt_zero_id,
2736 .operand_2 = value_gt_lhs_id,2780 .operand_2 = value_gt_lhs_id,
...@@ -2739,7 +2783,7 @@ const DeclGen = struct {...@@ -2739,7 +2783,7 @@ const DeclGen = struct {
2739 },2783 },
2740 };2784 };
27412785
2742 ov_id.* = try self.intFromBool(wip_ov.scalar_ty_ref, overflowed_id);2786 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
2743 }2787 }
27442788
2745 return try self.constructComposite(2789 return try self.constructComposite(
...@@ -2759,11 +2803,15 @@ const DeclGen = struct {...@@ -2759,11 +2803,15 @@ const DeclGen = struct {
2759 const result_ty = self.typeOfIndex(inst);2803 const result_ty = self.typeOfIndex(inst);
2760 const operand_ty = self.typeOf(extra.lhs);2804 const operand_ty = self.typeOf(extra.lhs);
2761 const shift_ty = self.typeOf(extra.rhs);2805 const shift_ty = self.typeOf(extra.rhs);
2762 const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct);2806 const shift_ty_ref = try self.resolveType(shift_ty, .direct);
27632807
2764 const ov_ty = result_ty.structFieldType(1, self.module);2808 const ov_ty = result_ty.structFieldType(1, self.module);
27652809
2766 const bool_ty_ref = try self.resolveType(Type.bool, .direct);2810 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
2811 const cmp_ty_ref = if (self.isVector(operand_ty))
2812 try self.spv.vectorType(operand_ty.vectorLen(mod), bool_ty_ref)
2813 else
2814 bool_ty_ref;
27672815
2768 const info = self.arithmeticTypeInfo(operand_ty);2816 const info = self.arithmeticTypeInfo(operand_ty);
2769 switch (info.class) {2817 switch (info.class) {
...@@ -2772,9 +2820,9 @@ const DeclGen = struct {...@@ -2772,9 +2820,9 @@ const DeclGen = struct {
2772 .float, .bool => unreachable,2820 .float, .bool => unreachable,
2773 }2821 }
27742822
2775 var wip_result = try self.elementWise(operand_ty);2823 var wip_result = try self.elementWise(operand_ty, false);
2776 defer wip_result.deinit();2824 defer wip_result.deinit();
2777 var wip_ov = try self.elementWise(ov_ty);2825 var wip_ov = try self.elementWise(ov_ty, false);
2778 defer wip_ov.deinit();2826 defer wip_ov.deinit();
2779 for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| {2827 for (wip_result.results, wip_ov.results, 0..) |*result_id, *ov_id, i| {
2780 const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i);2828 const lhs_elem_id = try wip_result.elementAt(operand_ty, lhs, i);
...@@ -2782,10 +2830,10 @@ const DeclGen = struct {...@@ -2782,10 +2830,10 @@ const DeclGen = struct {
27822830
2783 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,2831 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,
2784 // so just manually upcast it if required.2832 // so just manually upcast it if required.
2785 const shift_id = if (scalar_shift_ty_ref != wip_result.scalar_ty_ref) blk: {2833 const shift_id = if (shift_ty_ref != wip_result.ty_ref) blk: {
2786 const shift_id = self.spv.allocId();2834 const shift_id = self.spv.allocId();
2787 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{2835 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
2788 .id_result_type = wip_result.scalar_ty_id,2836 .id_result_type = wip_result.ty_id,
2789 .id_result = shift_id,2837 .id_result = shift_id,
2790 .unsigned_value = rhs_elem_id,2838 .unsigned_value = rhs_elem_id,
2791 });2839 });
...@@ -2794,18 +2842,18 @@ const DeclGen = struct {...@@ -2794,18 +2842,18 @@ const DeclGen = struct {
27942842
2795 const value_id = self.spv.allocId();2843 const value_id = self.spv.allocId();
2796 try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{2844 try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{
2797 .id_result_type = wip_result.scalar_ty_id,2845 .id_result_type = wip_result.ty_id,
2798 .id_result = value_id,2846 .id_result = value_id,
2799 .base = lhs_elem_id,2847 .base = lhs_elem_id,
2800 .shift = shift_id,2848 .shift = shift_id,
2801 });2849 });
2802 result_id.* = try self.normalize(wip_result.scalar_ty_ref, value_id, info);2850 result_id.* = try self.normalize(wip_result.ty_ref, value_id, info);
28032851
2804 const right_shift_id = self.spv.allocId();2852 const right_shift_id = self.spv.allocId();
2805 switch (info.signedness) {2853 switch (info.signedness) {
2806 .signed => {2854 .signed => {
2807 try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{2855 try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{
2808 .id_result_type = wip_result.scalar_ty_id,2856 .id_result_type = wip_result.ty_id,
2809 .id_result = right_shift_id,2857 .id_result = right_shift_id,
2810 .base = result_id.*,2858 .base = result_id.*,
2811 .shift = shift_id,2859 .shift = shift_id,
...@@ -2813,7 +2861,7 @@ const DeclGen = struct {...@@ -2813,7 +2861,7 @@ const DeclGen = struct {
2813 },2861 },
2814 .unsigned => {2862 .unsigned => {
2815 try self.func.body.emit(self.spv.gpa, .OpShiftRightLogical, .{2863 try self.func.body.emit(self.spv.gpa, .OpShiftRightLogical, .{
2816 .id_result_type = wip_result.scalar_ty_id,2864 .id_result_type = wip_result.ty_id,
2817 .id_result = right_shift_id,2865 .id_result = right_shift_id,
2818 .base = result_id.*,2866 .base = result_id.*,
2819 .shift = shift_id,2867 .shift = shift_id,
...@@ -2823,13 +2871,13 @@ const DeclGen = struct {...@@ -2823,13 +2871,13 @@ const DeclGen = struct {
28232871
2824 const overflowed_id = self.spv.allocId();2872 const overflowed_id = self.spv.allocId();
2825 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{2873 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
2826 .id_result_type = self.typeId(bool_ty_ref),2874 .id_result_type = self.typeId(cmp_ty_ref),
2827 .id_result = overflowed_id,2875 .id_result = overflowed_id,
2828 .operand_1 = lhs_elem_id,2876 .operand_1 = lhs_elem_id,
2829 .operand_2 = right_shift_id,2877 .operand_2 = right_shift_id,
2830 });2878 });
28312879
2832 ov_id.* = try self.intFromBool(wip_ov.scalar_ty_ref, overflowed_id);2880 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
2833 }2881 }
28342882
2835 return try self.constructComposite(2883 return try self.constructComposite(
...@@ -2853,19 +2901,19 @@ const DeclGen = struct {...@@ -2853,19 +2901,19 @@ const DeclGen = struct {
2853 const info = self.arithmeticTypeInfo(ty);2901 const info = self.arithmeticTypeInfo(ty);
2854 assert(info.class == .float); // .mul_add is only emitted for floats2902 assert(info.class == .float); // .mul_add is only emitted for floats
28552903
2856 var wip = try self.elementWise(ty);2904 var wip = try self.elementWise(ty, false);
2857 defer wip.deinit();2905 defer wip.deinit();
2858 for (0..wip.results.len) |i| {2906 for (0..wip.results.len) |i| {
2859 const mul_result = self.spv.allocId();2907 const mul_result = self.spv.allocId();
2860 try self.func.body.emit(self.spv.gpa, .OpFMul, .{2908 try self.func.body.emit(self.spv.gpa, .OpFMul, .{
2861 .id_result_type = wip.scalar_ty_id,2909 .id_result_type = wip.ty_id,
2862 .id_result = mul_result,2910 .id_result = mul_result,
2863 .operand_1 = try wip.elementAt(ty, mulend1, i),2911 .operand_1 = try wip.elementAt(ty, mulend1, i),
2864 .operand_2 = try wip.elementAt(ty, mulend2, i),2912 .operand_2 = try wip.elementAt(ty, mulend2, i),
2865 });2913 });
28662914
2867 try self.func.body.emit(self.spv.gpa, .OpFAdd, .{2915 try self.func.body.emit(self.spv.gpa, .OpFAdd, .{
2868 .id_result_type = wip.scalar_ty_id,2916 .id_result_type = wip.ty_id,
2869 .id_result = wip.allocId(i),2917 .id_result = wip.allocId(i),
2870 .operand_1 = mul_result,2918 .operand_1 = mul_result,
2871 .operand_2 = try wip.elementAt(ty, addend, i),2919 .operand_2 = try wip.elementAt(ty, addend, i),
...@@ -2879,11 +2927,9 @@ const DeclGen = struct {...@@ -2879,11 +2927,9 @@ const DeclGen = struct {
2879 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2927 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2880 const operand_id = try self.resolve(ty_op.operand);2928 const operand_id = try self.resolve(ty_op.operand);
2881 const result_ty = self.typeOfIndex(inst);2929 const result_ty = self.typeOfIndex(inst);
2882 var wip = try self.elementWise(result_ty);2930 var wip = try self.elementWise(result_ty, true);
2883 defer wip.deinit();2931 defer wip.deinit();
2884 for (wip.results) |*result_id| {2932 @memset(wip.results, operand_id);
2885 result_id.* = operand_id;
2886 }
2887 return try wip.finalize();2933 return try wip.finalize();
2888 }2934 }
28892935
...@@ -2965,20 +3011,20 @@ const DeclGen = struct {...@@ -2965,20 +3011,20 @@ const DeclGen = struct {
29653011
2966 const ty = self.typeOfIndex(inst);3012 const ty = self.typeOfIndex(inst);
29673013
2968 var wip = try self.elementWise(ty);3014 var wip = try self.elementWise(ty, true);
2969 defer wip.deinit();3015 defer wip.deinit();
2970 for (wip.results, 0..) |*result_id, i| {3016 for (wip.results, 0..) |*result_id, i| {
2971 const elem = try mask.elemValue(mod, i);3017 const elem = try mask.elemValue(mod, i);
2972 if (elem.isUndef(mod)) {3018 if (elem.isUndef(mod)) {
2973 result_id.* = try self.spv.constUndef(wip.scalar_ty_ref);3019 result_id.* = try self.spv.constUndef(wip.ty_ref);
2974 continue;3020 continue;
2975 }3021 }
29763022
2977 const index = elem.toSignedInt(mod);3023 const index = elem.toSignedInt(mod);
2978 if (index >= 0) {3024 if (index >= 0) {
2979 result_id.* = try self.extractField(wip.scalar_ty, a, @intCast(index));3025 result_id.* = try self.extractField(wip.ty, a, @intCast(index));
2980 } else {3026 } else {
2981 result_id.* = try self.extractField(wip.scalar_ty, b, @intCast(~index));3027 result_id.* = try self.extractField(wip.ty, b, @intCast(~index));
2982 }3028 }
2983 }3029 }
2984 return try wip.finalize();3030 return try wip.finalize();
...@@ -3188,7 +3234,7 @@ const DeclGen = struct {...@@ -3188,7 +3234,7 @@ const DeclGen = struct {
3188 return result_id;3234 return result_id;
3189 },3235 },
3190 .Vector => {3236 .Vector => {
3191 var wip = try self.elementWise(result_ty);3237 var wip = try self.elementWise(result_ty, true);
3192 defer wip.deinit();3238 defer wip.deinit();
3193 const scalar_ty = ty.scalarType(mod);3239 const scalar_ty = ty.scalarType(mod);
3194 for (wip.results, 0..) |*result_id, i| {3240 for (wip.results, 0..) |*result_id, i| {
...@@ -3374,19 +3420,19 @@ const DeclGen = struct {...@@ -3374,19 +3420,19 @@ const DeclGen = struct {
3374 return operand_id;3420 return operand_id;
3375 }3421 }
33763422
3377 var wip = try self.elementWise(dst_ty);3423 var wip = try self.elementWise(dst_ty, false);
3378 defer wip.deinit();3424 defer wip.deinit();
3379 for (wip.results, 0..) |*result_id, i| {3425 for (wip.results, 0..) |*result_id, i| {
3380 const elem_id = try wip.elementAt(src_ty, operand_id, i);3426 const elem_id = try wip.elementAt(src_ty, operand_id, i);
3381 const value_id = self.spv.allocId();3427 const value_id = self.spv.allocId();
3382 switch (dst_info.signedness) {3428 switch (dst_info.signedness) {
3383 .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{3429 .signed => try self.func.body.emit(self.spv.gpa, .OpSConvert, .{
3384 .id_result_type = wip.scalar_ty_id,3430 .id_result_type = wip.ty_id,
3385 .id_result = value_id,3431 .id_result = value_id,
3386 .signed_value = elem_id,3432 .signed_value = elem_id,
3387 }),3433 }),
3388 .unsigned => try self.func.body.emit(self.spv.gpa, .OpUConvert, .{3434 .unsigned => try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
3389 .id_result_type = wip.scalar_ty_id,3435 .id_result_type = wip.ty_id,
3390 .id_result = value_id,3436 .id_result = value_id,
3391 .unsigned_value = elem_id,3437 .unsigned_value = elem_id,
3392 }),3438 }),
...@@ -3397,7 +3443,7 @@ const DeclGen = struct {...@@ -3397,7 +3443,7 @@ const DeclGen = struct {
3397 // type, we don't need to normalize when growing the type. The3443 // type, we don't need to normalize when growing the type. The
3398 // representation is already the same.3444 // representation is already the same.
3399 if (dst_info.bits < src_info.bits) {3445 if (dst_info.bits < src_info.bits) {
3400 result_id.* = try self.normalize(wip.scalar_ty_ref, value_id, dst_info);3446 result_id.* = try self.normalize(wip.ty_ref, value_id, dst_info);
3401 } else {3447 } else {
3402 result_id.* = value_id;3448 result_id.* = value_id;
3403 }3449 }
...@@ -3482,11 +3528,11 @@ const DeclGen = struct {...@@ -3482,11 +3528,11 @@ const DeclGen = struct {
3482 const operand_id = try self.resolve(un_op);3528 const operand_id = try self.resolve(un_op);
3483 const result_ty = self.typeOfIndex(inst);3529 const result_ty = self.typeOfIndex(inst);
34843530
3485 var wip = try self.elementWise(result_ty);3531 var wip = try self.elementWise(result_ty, false);
3486 defer wip.deinit();3532 defer wip.deinit();
3487 for (wip.results, 0..) |*result_id, i| {3533 for (wip.results, 0..) |*result_id, i| {
3488 const elem_id = try wip.elementAt(Type.bool, operand_id, i);3534 const elem_id = try wip.elementAt(Type.bool, operand_id, i);
3489 result_id.* = try self.intFromBool(wip.scalar_ty_ref, elem_id);3535 result_id.* = try self.intFromBool(wip.ty_ref, elem_id);
3490 }3536 }
3491 return try wip.finalize();3537 return try wip.finalize();
3492 }3538 }
...@@ -3515,12 +3561,12 @@ const DeclGen = struct {...@@ -3515,12 +3561,12 @@ const DeclGen = struct {
3515 const result_ty = self.typeOfIndex(inst);3561 const result_ty = self.typeOfIndex(inst);
3516 const info = self.arithmeticTypeInfo(result_ty);3562 const info = self.arithmeticTypeInfo(result_ty);
35173563
3518 var wip = try self.elementWise(result_ty);3564 var wip = try self.elementWise(result_ty, false);
3519 defer wip.deinit();3565 defer wip.deinit();
35203566
3521 for (0..wip.results.len) |i| {3567 for (0..wip.results.len) |i| {
3522 const args = .{3568 const args = .{
3523 .id_result_type = wip.scalar_ty_id,3569 .id_result_type = wip.ty_id,
3524 .id_result = wip.allocId(i),3570 .id_result = wip.allocId(i),
3525 .operand = try wip.elementAt(result_ty, operand_id, i),3571 .operand = try wip.elementAt(result_ty, operand_id, i),
3526 };3572 };
...@@ -3563,10 +3609,7 @@ const DeclGen = struct {...@@ -3563,10 +3609,7 @@ const DeclGen = struct {
3563 // Convert the pointer-to-array to a pointer to the first element.3609 // Convert the pointer-to-array to a pointer to the first element.
3564 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});3610 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});
35653611
3566 return try self.constructComposite(3612 return try self.constructComposite(slice_ty, &.{ elem_ptr_id, len_id });
3567 slice_ty,
3568 &.{ elem_ptr_id, len_id },
3569 );
3570 }3613 }
35713614
3572 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3615 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3580,10 +3623,7 @@ const DeclGen = struct {...@@ -3580,10 +3623,7 @@ const DeclGen = struct {
35803623
3581 // Note: Types should not need to be converted to direct, these types3624 // Note: Types should not need to be converted to direct, these types
3582 // dont need to be converted.3625 // dont need to be converted.
3583 return try self.constructComposite(3626 return try self.constructComposite(slice_ty, &.{ ptr_id, len_id });
3584 slice_ty,
3585 &.{ ptr_id, len_id },
3586 );
3587 }3627 }
35883628
3589 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3629 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3641,9 +3681,9 @@ const DeclGen = struct {...@@ -3641,9 +3681,9 @@ const DeclGen = struct {
3641 const elem_ids = try self.gpa.alloc(IdRef, n_elems);3681 const elem_ids = try self.gpa.alloc(IdRef, n_elems);
3642 defer self.gpa.free(elem_ids);3682 defer self.gpa.free(elem_ids);
36433683
3644 for (elements, 0..) |element, i| {3684 for (elements, elem_ids) |element, *elem_id| {
3645 const id = try self.resolve(element);3685 const id = try self.resolve(element);
3646 elem_ids[i] = try self.convertToIndirect(result_ty.childType(mod), id);3686 elem_id.* = try self.convertToIndirect(result_ty.childType(mod), id);
3647 }3687 }
36483688
3649 return try self.constructComposite(result_ty, elem_ids);3689 return try self.constructComposite(result_ty, elem_ids);
...@@ -3654,9 +3694,9 @@ const DeclGen = struct {...@@ -3654,9 +3694,9 @@ const DeclGen = struct {
3654 const elem_ids = try self.gpa.alloc(IdRef, n_elems);3694 const elem_ids = try self.gpa.alloc(IdRef, n_elems);
3655 defer self.gpa.free(elem_ids);3695 defer self.gpa.free(elem_ids);
36563696
3657 for (elements, 0..) |element, i| {3697 for (elements, elem_ids) |element, *elem_id| {
3658 const id = try self.resolve(element);3698 const id = try self.resolve(element);
3659 elem_ids[i] = try self.convertToIndirect(array_info.elem_type, id);3699 elem_id.* = try self.convertToIndirect(array_info.elem_type, id);
3660 }3700 }
36613701
3662 if (array_info.sentinel) |sentinel_val| {3702 if (array_info.sentinel) |sentinel_val| {