authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-01-19 01:12:56+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-02-04 19:09:27+01:00
log761594e2260eb780ab1861568e38a7066a7513df
treec5b5edf66d371f19708c65ccfb12d2ae36824ef6
parent2f815853dcae49bbfd109675cde1f4097b75c8cc
signaturebadge-check Signed by SSH key SHA256:ZS52FNyUv2WUXvO4njmVaFVO46RHojFuOrxRc4LuKzg

spirv: reduce, reduce_optimized


2 files changed, 74 insertions(+), 3 deletions(-)

src/codegen/spirv.zig+74-1
...@@ -2187,6 +2187,7 @@ const DeclGen = struct {...@@ -2187,6 +2187,7 @@ const DeclGen = struct {
2187 .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan),2187 .sub_with_overflow => try self.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan),
2188 .shl_with_overflow => try self.airShlOverflow(inst),2188 .shl_with_overflow => try self.airShlOverflow(inst),
21892189
2190 .reduce, .reduce_optimized => try self.airReduce(inst),
2190 .shuffle => try self.airShuffle(inst),2191 .shuffle => try self.airShuffle(inst),
21912192
2192 .ptr_add => try self.airPtrAdd(inst),2193 .ptr_add => try self.airPtrAdd(inst),
...@@ -2388,9 +2389,14 @@ const DeclGen = struct {...@@ -2388,9 +2389,14 @@ const DeclGen = struct {
2388 const lhs_id = try self.resolve(bin_op.lhs);2389 const lhs_id = try self.resolve(bin_op.lhs);
2389 const rhs_id = try self.resolve(bin_op.rhs);2390 const rhs_id = try self.resolve(bin_op.rhs);
2390 const result_ty = self.typeOfIndex(inst);2391 const result_ty = self.typeOfIndex(inst);
2391 const result_ty_ref = try self.resolveType(result_ty, .direct);
23922392
2393 return try self.minMax(result_ty, op, lhs_id, rhs_id);
2394 }
2395
2396 fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef {
2397 const result_ty_ref = try self.resolveType(result_ty, .direct);
2393 const info = try self.arithmeticTypeInfo(result_ty);2398 const info = try self.arithmeticTypeInfo(result_ty);
2399
2394 // TODO: Use fmin for OpenCL2400 // TODO: Use fmin for OpenCL
2395 const cmp_id = try self.cmp(op, Type.bool, result_ty, lhs_id, rhs_id);2401 const cmp_id = try self.cmp(op, Type.bool, result_ty, lhs_id, rhs_id);
2396 const selection_id = switch (info.class) {2402 const selection_id = switch (info.class) {
...@@ -2758,6 +2764,73 @@ const DeclGen = struct {...@@ -2758,6 +2764,73 @@ const DeclGen = struct {
2758 );2764 );
2759 }2765 }
27602766
2767 fn airReduce(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2768 if (self.liveness.isUnused(inst)) return null;
2769 const mod = self.module;
2770 const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
2771 const operand = try self.resolve(reduce.operand);
2772 const operand_ty = self.typeOf(reduce.operand);
2773 const scalar_ty = operand_ty.scalarType(mod);
2774 const scalar_ty_ref = try self.resolveType(scalar_ty, .direct);
2775 const scalar_ty_id = self.typeId(scalar_ty_ref);
2776
2777 const info = try self.arithmeticTypeInfo(operand_ty);
2778
2779 var result_id = try self.extractField(scalar_ty, operand, 0);
2780 const len = operand_ty.vectorLen(mod);
2781
2782 switch (reduce.operation) {
2783 .Min, .Max => |op| {
2784 const cmp_op: std.math.CompareOperator = if (op == .Max) .gt else .lt;
2785 for (1..len) |i| {
2786 const lhs = result_id;
2787 const rhs = try self.extractField(scalar_ty, operand, @intCast(i));
2788 result_id = try self.minMax(scalar_ty, cmp_op, lhs, rhs);
2789 }
2790
2791 return result_id;
2792 },
2793 else => {},
2794 }
2795
2796 const opcode: Opcode = switch (info.class) {
2797 .bool => switch (reduce.operation) {
2798 .And => .OpLogicalAnd,
2799 .Or => .OpLogicalOr,
2800 .Xor => .OpLogicalNotEqual,
2801 else => unreachable,
2802 },
2803 .strange_integer, .integer => switch (reduce.operation) {
2804 .And => .OpBitwiseAnd,
2805 .Or => .OpBitwiseOr,
2806 .Xor => .OpBitwiseXor,
2807 .Add => .OpIAdd,
2808 .Mul => .OpIMul,
2809 else => unreachable,
2810 },
2811 .float => switch (reduce.operation) {
2812 .Add => .OpFAdd,
2813 .Mul => .OpFMul,
2814 else => unreachable,
2815 },
2816 .composite_integer => unreachable, // TODO
2817 };
2818
2819 for (1..len) |i| {
2820 const lhs = result_id;
2821 const rhs = try self.extractField(scalar_ty, operand, @intCast(i));
2822 result_id = self.spv.allocId();
2823
2824 try self.func.body.emitRaw(self.spv.gpa, opcode, 4);
2825 self.func.body.writeOperand(spec.IdResultType, scalar_ty_id);
2826 self.func.body.writeOperand(spec.IdResult, result_id);
2827 self.func.body.writeOperand(spec.IdResultType, lhs);
2828 self.func.body.writeOperand(spec.IdResultType, rhs);
2829 }
2830
2831 return result_id;
2832 }
2833
2761 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2834 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2762 const mod = self.module;2835 const mod = self.module;
2763 if (self.liveness.isUnused(inst)) return null;2836 if (self.liveness.isUnused(inst)) return null;
test/behavior/vector.zig-2
...@@ -1231,7 +1231,6 @@ test "byte vector initialized in inline function" {...@@ -1231,7 +1231,6 @@ test "byte vector initialized in inline function" {
1231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1234 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
12351234
1236 if (comptime builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and1235 if (comptime builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and
1237 builtin.cpu.features.isEnabled(@intFromEnum(std.Target.x86.Feature.avx512f)))1236 builtin.cpu.features.isEnabled(@intFromEnum(std.Target.x86.Feature.avx512f)))
...@@ -1301,7 +1300,6 @@ test "@intCast to u0" {...@@ -1301,7 +1300,6 @@ test "@intCast to u0" {
1301 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1304 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13051303
1306 var zeros = @Vector(2, u32){ 0, 0 };1304 var zeros = @Vector(2, u32){ 0, 0 };
1307 _ = &zeros;1305 _ = &zeros;