authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2023-10-14 04:05:04+03:30
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-10-15 14:00:33+02:00
log45a1945dc4a77fb757725d977a6e385a21793a98
treef4e26b49c42862ece168f98dd63f0af6e5a483f1
parent9c20449cc5be5da0458556e143980b40d51e8776
signaturebadge-check Signed by SSH key SHA256:CQ99aPxq+RueiL9u7z0FEki5Fm7V6T8q4PrEGmINrA4

spirv: simple binary and comparison vector operations


2 files changed, 72 insertions(+), 31 deletions(-)

src/codegen/spirv.zig+72-12
......@@ -2027,12 +2027,13 @@ const DeclGen = struct {
20272027 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
20282028 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
20292029
2030 .cmp_eq => try self.airCmp(inst, .eq),
2031 .cmp_neq => try self.airCmp(inst, .neq),
2032 .cmp_gt => try self.airCmp(inst, .gt),
2033 .cmp_gte => try self.airCmp(inst, .gte),
2034 .cmp_lt => try self.airCmp(inst, .lt),
2035 .cmp_lte => try self.airCmp(inst, .lte),
2030 .cmp_eq => try self.airCmp(inst, .eq),
2031 .cmp_neq => try self.airCmp(inst, .neq),
2032 .cmp_gt => try self.airCmp(inst, .gt),
2033 .cmp_gte => try self.airCmp(inst, .gte),
2034 .cmp_lt => try self.airCmp(inst, .lt),
2035 .cmp_lte => try self.airCmp(inst, .lte),
2036 .cmp_vector => try self.airVectorCmp(inst),
20362037
20372038 .arg => self.airArg(),
20382039 .alloc => try self.airAlloc(inst),
......@@ -2088,13 +2089,30 @@ const DeclGen = struct {
20882089 try self.inst_results.putNoClobber(self.gpa, inst, result_id);
20892090 }
20902091
2091 fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef {
2092 if (self.liveness.isUnused(inst)) return null;
2093 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2094 const lhs_id = try self.resolve(bin_op.lhs);
2095 const rhs_id = try self.resolve(bin_op.rhs);
2092 fn binOpSimple(self: *DeclGen, ty: Type, lhs_id: IdRef, rhs_id: IdRef, comptime opcode: Opcode) !IdRef {
2093 const mod = self.module;
2094
2095 if (ty.isVector(mod)) {
2096 const child_ty = ty.childType(mod);
2097 const vector_len = ty.vectorLen(mod);
2098
2099 var constituents = try self.gpa.alloc(IdRef, vector_len);
2100 defer self.gpa.free(constituents);
2101
2102 for (constituents, 0..) |*constituent, i| {
2103 const lhs_index_id = try self.extractField(child_ty, lhs_id, @intCast(i));
2104 const rhs_index_id = try self.extractField(child_ty, rhs_id, @intCast(i));
2105 const result_id = try self.binOpSimple(child_ty, lhs_index_id, rhs_index_id, opcode);
2106 constituent.* = try self.convertToIndirect(child_ty, result_id);
2107 }
2108
2109 const result_ty = try self.resolveType(child_ty, .indirect);
2110 const result_ty_ref = try self.spv.arrayType(vector_len, result_ty);
2111 return try self.constructArray(result_ty_ref, constituents);
2112 }
2113
20962114 const result_id = self.spv.allocId();
2097 const result_type_id = try self.resolveTypeId(self.typeOfIndex(inst));
2115 const result_type_id = try self.resolveTypeId(ty);
20982116 try self.func.body.emit(self.spv.gpa, opcode, .{
20992117 .id_result_type = result_type_id,
21002118 .id_result = result_id,
......@@ -2104,6 +2122,17 @@ const DeclGen = struct {
21042122 return result_id;
21052123 }
21062124
2125 fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef {
2126 if (self.liveness.isUnused(inst)) return null;
2127
2128 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2129 const lhs_id = try self.resolve(bin_op.lhs);
2130 const rhs_id = try self.resolve(bin_op.rhs);
2131 const ty = self.typeOf(bin_op.lhs);
2132
2133 return try self.binOpSimple(ty, lhs_id, rhs_id, opcode);
2134 }
2135
21072136 fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef {
21082137 if (self.liveness.isUnused(inst)) return null;
21092138 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -2676,6 +2705,24 @@ const DeclGen = struct {
26762705 }
26772706 return result_id;
26782707 },
2708 .Vector => {
2709 const child_ty = ty.childType(mod);
2710 const vector_len = ty.vectorLen(mod);
2711 const bool_ty_ref_indirect = try self.resolveType(Type.bool, .indirect);
2712
2713 var constituents = try self.gpa.alloc(IdRef, vector_len);
2714 defer self.gpa.free(constituents);
2715
2716 for (constituents, 0..) |*constituent, i| {
2717 const lhs_index_id = try self.extractField(child_ty, cmp_lhs_id, @intCast(i));
2718 const rhs_index_id = try self.extractField(child_ty, cmp_rhs_id, @intCast(i));
2719 const result_id = try self.cmp(op, child_ty, lhs_index_id, rhs_index_id);
2720 constituent.* = try self.convertToIndirect(Type.bool, result_id);
2721 }
2722
2723 const result_ty_ref = try self.spv.arrayType(vector_len, bool_ty_ref_indirect);
2724 return try self.constructArray(result_ty_ref, constituents);
2725 },
26792726 else => unreachable,
26802727 };
26812728
......@@ -2751,6 +2798,19 @@ const DeclGen = struct {
27512798 return try self.cmp(op, ty, lhs_id, rhs_id);
27522799 }
27532800
2801 fn airVectorCmp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2802 if (self.liveness.isUnused(inst)) return null;
2803
2804 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2805 const vec_cmp = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
2806 const lhs_id = try self.resolve(vec_cmp.lhs);
2807 const rhs_id = try self.resolve(vec_cmp.rhs);
2808 const op = vec_cmp.compareOperator();
2809 const ty = self.typeOf(vec_cmp.lhs);
2810
2811 return try self.cmp(op, ty, lhs_id, rhs_id);
2812 }
2813
27542814 fn bitCast(
27552815 self: *DeclGen,
27562816 dst_ty: Type,
test/behavior/vector.zig-19
......@@ -53,7 +53,6 @@ test "vector bin compares with mem.eql" {
5353 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5454 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5555 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5756
5857 const S = struct {
5958 fn doTheTest() !void {
......@@ -123,7 +122,6 @@ test "vector bit operators" {
123122 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
124123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
125124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
127125
128126 const S = struct {
129127 fn doTheTest() !void {
......@@ -142,7 +140,6 @@ test "implicit cast vector to array" {
142140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
143141 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
144142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
146143
147144 const S = struct {
148145 fn doTheTest() !void {
......@@ -160,7 +157,6 @@ test "array to vector" {
160157 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
161158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
162159 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
164160
165161 const S = struct {
166162 fn doTheTest() !void {
......@@ -285,7 +281,6 @@ test "vector casts of sizes not divisible by 8" {
285281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
286282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
287283 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
288 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
289284
290285 const S = struct {
291286 fn doTheTest() !void {
......@@ -366,7 +361,6 @@ test "load vector elements via comptime index" {
366361 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
367362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
368363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
370364
371365 const S = struct {
372366 fn doTheTest() !void {
......@@ -388,7 +382,6 @@ test "store vector elements via comptime index" {
388382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
389383 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
390384 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
391 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
392385
393386 const S = struct {
394387 fn doTheTest() !void {
......@@ -416,7 +409,6 @@ test "load vector elements via runtime index" {
416409 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
417410 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
418411 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
419 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
420412
421413 const S = struct {
422414 fn doTheTest() !void {
......@@ -438,7 +430,6 @@ test "store vector elements via runtime index" {
438430 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
439431 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
440432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
441 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
442433
443434 const S = struct {
444435 fn doTheTest() !void {
......@@ -461,7 +452,6 @@ test "initialize vector which is a struct field" {
461452 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
462453 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
463454 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
464 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
465455
466456 const Vec4Obj = struct {
467457 data: @Vector(4, f32),
......@@ -485,7 +475,6 @@ test "vector comparison operators" {
485475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
486476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
487477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
488 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
489478
490479 const S = struct {
491480 fn doTheTest() !void {
......@@ -1167,7 +1156,6 @@ test "loading the second vector from a slice of vectors" {
11671156 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11681157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11691158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1170 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11711159
11721160 @setRuntimeSafety(false);
11731161 var small_bases = [2]@Vector(2, u8){
......@@ -1184,7 +1172,6 @@ test "array of vectors is copied" {
11841172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11851173 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11861174 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1187 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11881175
11891176 const Vec3 = @Vector(3, i32);
11901177 var points = [_]Vec3{
......@@ -1255,7 +1242,6 @@ test "zero multiplicand" {
12551242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12561243 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12571244 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1258 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
12591245
12601246 const zeros = @Vector(2, u32){ 0.0, 0.0 };
12611247 var ones = @Vector(2, u32){ 1.0, 1.0 };
......@@ -1316,7 +1302,6 @@ test "load packed vector element" {
13161302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13171303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13181304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1319 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13201305 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
13211306 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13221307
......@@ -1347,7 +1332,6 @@ test "store to vector in slice" {
13471332 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
13481333 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13491334 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1350 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13511335
13521336 var v = [_]@Vector(3, f32){
13531337 .{ 1, 1, 1 },
......@@ -1411,7 +1395,6 @@ test "store vector with memset" {
14111395test "addition of vectors represented as strings" {
14121396 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14131397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1414 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14151398
14161399 const V = @Vector(3, u8);
14171400 const foo: V = "foo".*;
......@@ -1437,7 +1420,6 @@ test "vector pointer is indexable" {
14371420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14381421 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14391422 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1440 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
14411423
14421424 const V = @Vector(2, u32);
14431425
......@@ -1478,7 +1460,6 @@ test "bitcast to vector with different child type" {
14781460 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14791461 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14801462 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1481 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
14821463
14831464 const S = struct {
14841465 fn doTheTest() !void {