| ... | ... | @@ -2160,9 +2160,9 @@ const DeclGen = struct { |
| 2160 | 2160 | const air_tags = self.air.instructions.items(.tag); |
| 2161 | 2161 | const maybe_result_id: ?IdRef = switch (air_tags[@intFromEnum(inst)]) { |
| 2162 | 2162 | // zig fmt: off |
| 2163 | | .add, .add_wrap => try self.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd), |
| 2164 | | .sub, .sub_wrap => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub), |
| 2165 | | .mul, .mul_wrap => try self.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul), |
| 2163 | .add, .add_wrap, .add_optimized => try self.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd), |
| 2164 | .sub, .sub_wrap, .sub_optimized => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub), |
| 2165 | .mul, .mul_wrap, .mul_optimized => try self.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul), |
| 2166 | 2166 | |
| 2167 | 2167 | .div_float, |
| 2168 | 2168 | .div_float_optimized, |
| ... | ... | @@ -2179,6 +2179,8 @@ const DeclGen = struct { |
| 2179 | 2179 | .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan), |
| 2180 | 2180 | .shl_with_overflow => try self.airShlOverflow(inst), |
| 2181 | 2181 | |
| 2182 | .mul_add => try self.airMulAdd(inst), |
| 2183 | |
| 2182 | 2184 | .reduce, .reduce_optimized => try self.airReduce(inst), |
| 2183 | 2185 | .shuffle => try self.airShuffle(inst), |
| 2184 | 2186 | |
| ... | ... | @@ -2439,40 +2441,38 @@ const DeclGen = struct { |
| 2439 | 2441 | switch (info.class) { |
| 2440 | 2442 | .integer, .bool, .float => return value_id, |
| 2441 | 2443 | .composite_integer => unreachable, // TODO |
| 2442 | | .strange_integer => { |
| 2443 | | switch (info.signedness) { |
| 2444 | | .unsigned => { |
| 2445 | | const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; |
| 2446 | | const result_id = self.spv.allocId(); |
| 2447 | | const mask_id = try self.constInt(ty_ref, mask_value); |
| 2448 | | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ |
| 2449 | | .id_result_type = self.typeId(ty_ref), |
| 2450 | | .id_result = result_id, |
| 2451 | | .operand_1 = value_id, |
| 2452 | | .operand_2 = mask_id, |
| 2453 | | }); |
| 2454 | | return result_id; |
| 2455 | | }, |
| 2456 | | .signed => { |
| 2457 | | // Shift left and right so that we can copy the sight bit that way. |
| 2458 | | const shift_amt_id = try self.constInt(ty_ref, info.backing_bits - info.bits); |
| 2459 | | const left_id = self.spv.allocId(); |
| 2460 | | try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{ |
| 2461 | | .id_result_type = self.typeId(ty_ref), |
| 2462 | | .id_result = left_id, |
| 2463 | | .base = value_id, |
| 2464 | | .shift = shift_amt_id, |
| 2465 | | }); |
| 2466 | | const right_id = self.spv.allocId(); |
| 2467 | | try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{ |
| 2468 | | .id_result_type = self.typeId(ty_ref), |
| 2469 | | .id_result = right_id, |
| 2470 | | .base = left_id, |
| 2471 | | .shift = shift_amt_id, |
| 2472 | | }); |
| 2473 | | return right_id; |
| 2474 | | }, |
| 2475 | | } |
| 2444 | .strange_integer => switch (info.signedness) { |
| 2445 | .unsigned => { |
| 2446 | const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; |
| 2447 | const result_id = self.spv.allocId(); |
| 2448 | const mask_id = try self.constInt(ty_ref, mask_value); |
| 2449 | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ |
| 2450 | .id_result_type = self.typeId(ty_ref), |
| 2451 | .id_result = result_id, |
| 2452 | .operand_1 = value_id, |
| 2453 | .operand_2 = mask_id, |
| 2454 | }); |
| 2455 | return result_id; |
| 2456 | }, |
| 2457 | .signed => { |
| 2458 | // Shift left and right so that we can copy the sight bit that way. |
| 2459 | const shift_amt_id = try self.constInt(ty_ref, info.backing_bits - info.bits); |
| 2460 | const left_id = self.spv.allocId(); |
| 2461 | try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{ |
| 2462 | .id_result_type = self.typeId(ty_ref), |
| 2463 | .id_result = left_id, |
| 2464 | .base = value_id, |
| 2465 | .shift = shift_amt_id, |
| 2466 | }); |
| 2467 | const right_id = self.spv.allocId(); |
| 2468 | try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{ |
| 2469 | .id_result_type = self.typeId(ty_ref), |
| 2470 | .id_result = right_id, |
| 2471 | .base = left_id, |
| 2472 | .shift = shift_amt_id, |
| 2473 | }); |
| 2474 | return right_id; |
| 2475 | }, |
| 2476 | 2476 | }, |
| 2477 | 2477 | } |
| 2478 | 2478 | } |
| ... | ... | @@ -2761,6 +2761,42 @@ const DeclGen = struct { |
| 2761 | 2761 | ); |
| 2762 | 2762 | } |
| 2763 | 2763 | |
| 2764 | fn airMulAdd(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2765 | if (self.liveness.isUnused(inst)) return null; |
| 2766 | |
| 2767 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 2768 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; |
| 2769 | |
| 2770 | const mulend1 = try self.resolve(extra.lhs); |
| 2771 | const mulend2 = try self.resolve(extra.rhs); |
| 2772 | const addend = try self.resolve(pl_op.operand); |
| 2773 | |
| 2774 | const ty = self.typeOfIndex(inst); |
| 2775 | |
| 2776 | const info = self.arithmeticTypeInfo(ty); |
| 2777 | assert(info.class == .float); // .mul_add is only emitted for floats |
| 2778 | |
| 2779 | var wip = try self.elementWise(ty); |
| 2780 | defer wip.deinit(); |
| 2781 | for (0..wip.results.len) |i| { |
| 2782 | const mul_result = self.spv.allocId(); |
| 2783 | try self.func.body.emit(self.spv.gpa, .OpFMul, .{ |
| 2784 | .id_result_type = wip.scalar_ty_id, |
| 2785 | .id_result = mul_result, |
| 2786 | .operand_1 = try wip.elementAt(ty, mulend1, i), |
| 2787 | .operand_2 = try wip.elementAt(ty, mulend2, i), |
| 2788 | }); |
| 2789 | |
| 2790 | try self.func.body.emit(self.spv.gpa, .OpFAdd, .{ |
| 2791 | .id_result_type = wip.scalar_ty_id, |
| 2792 | .id_result = wip.allocId(i), |
| 2793 | .operand_1 = mul_result, |
| 2794 | .operand_2 = try wip.elementAt(ty, addend, i), |
| 2795 | }); |
| 2796 | } |
| 2797 | return try wip.finalize(); |
| 2798 | } |
| 2799 | |
| 2764 | 2800 | fn airReduce(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 2765 | 2801 | if (self.liveness.isUnused(inst)) return null; |
| 2766 | 2802 | const mod = self.module; |