| ... | ... | @@ -2195,6 +2195,7 @@ const DeclGen = struct { |
| 2195 | 2195 | |
| 2196 | 2196 | .mul_add => try self.airMulAdd(inst), |
| 2197 | 2197 | |
| 2198 | .splat => try self.airSplat(inst), |
| 2198 | 2199 | .reduce, .reduce_optimized => try self.airReduce(inst), |
| 2199 | 2200 | .shuffle => try self.airShuffle(inst), |
| 2200 | 2201 | |
| ... | ... | @@ -2603,6 +2604,7 @@ const DeclGen = struct { |
| 2603 | 2604 | // Idk why spir-v doesn't have a dedicated abs() instruction in the base |
| 2604 | 2605 | // instruction set. For now we're just going to negate and check to avoid |
| 2605 | 2606 | // importing the extinst. |
| 2607 | // TODO: Make this a call to compiler rt / ext inst |
| 2606 | 2608 | const neg_id = self.spv.allocId(); |
| 2607 | 2609 | const args = .{ |
| 2608 | 2610 | .id_result_type = self.typeId(operand_scalar_ty_ref), |
| ... | ... | @@ -2877,6 +2879,19 @@ const DeclGen = struct { |
| 2877 | 2879 | return try wip.finalize(); |
| 2878 | 2880 | } |
| 2879 | 2881 | |
| 2882 | fn airSplat(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2883 | if (self.liveness.isUnused(inst)) return null; |
| 2884 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 2885 | const operand_id = try self.resolve(ty_op.operand); |
| 2886 | const result_ty = self.typeOfIndex(inst); |
| 2887 | var wip = try self.elementWise(result_ty); |
| 2888 | defer wip.deinit(); |
| 2889 | for (wip.results) |*result_id| { |
| 2890 | result_id.* = operand_id; |
| 2891 | } |
| 2892 | return try wip.finalize(); |
| 2893 | } |
| 2894 | |
| 2880 | 2895 | fn airReduce(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2881 | 2896 | if (self.liveness.isUnused(inst)) return null; |
| 2882 | 2897 | const mod = self.module; |