| author | |
| committer | |
| log | 9641d2ebdb74926a56ff3b916082534052dc637f |
| tree | a562880abf840da19497106ecbdfa9095042a187 |
| parent | 9f0227a326d84208e23e90c2a84ff95f734bd2ae |
| signature |
2 files changed, 50 insertions(+), 54 deletions(-)
src/codegen/spirv.zig+50-49| ... | @@ -2391,45 +2391,51 @@ const DeclGen = struct { | ... | @@ -2391,45 +2391,51 @@ const DeclGen = struct { |
| 2391 | } | 2391 | } |
| 2392 | 2392 | ||
| 2393 | fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef { | 2393 | fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef { |
| 2394 | const result_ty_ref = try self.resolveType(result_ty, .direct); | ||
| 2395 | const info = self.arithmeticTypeInfo(result_ty); | 2394 | const info = self.arithmeticTypeInfo(result_ty); |
| 2396 | 2395 | ||
| 2397 | // TODO: Use fmin for OpenCL | 2396 | var wip = try self.elementWise(result_ty); |
| 2398 | const cmp_id = try self.cmp(op, Type.bool, result_ty, lhs_id, rhs_id); | 2397 | defer wip.deinit(); |
| 2399 | const selection_id = switch (info.class) { | 2398 | for (wip.results, 0..) |*result_id, i| { |
| 2400 | .float => blk: { | 2399 | const lhs_elem_id = try wip.elementAt(result_ty, lhs_id, i); |
| 2401 | // cmp uses OpFOrd. When we have 0 [<>] nan this returns false, | 2400 | const rhs_elem_id = try wip.elementAt(result_ty, rhs_id, i); |
| 2402 | // but we want it to pick lhs. Therefore we also have to check if | 2401 | |
| 2403 | // rhs is nan. We don't need to care about the result when both | 2402 | // TODO: Use fmin for OpenCL |
| 2404 | // are nan. | 2403 | const cmp_id = try self.cmp(op, Type.bool, wip.scalar_ty, lhs_elem_id, rhs_elem_id); |
| 2405 | const rhs_is_nan_id = self.spv.allocId(); | 2404 | const selection_id = switch (info.class) { |
| 2406 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | 2405 | .float => blk: { |
| 2407 | try self.func.body.emit(self.spv.gpa, .OpIsNan, .{ | 2406 | // cmp uses OpFOrd. When we have 0 [<>] nan this returns false, |
| 2408 | .id_result_type = self.typeId(bool_ty_ref), | 2407 | // but we want it to pick lhs. Therefore we also have to check if |
| 2409 | .id_result = rhs_is_nan_id, | 2408 | // rhs is nan. We don't need to care about the result when both |
| 2410 | .x = rhs_id, | 2409 | // are nan. |
| 2411 | }); | 2410 | const rhs_is_nan_id = self.spv.allocId(); |
| 2412 | const float_cmp_id = self.spv.allocId(); | 2411 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 2413 | try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{ | 2412 | try self.func.body.emit(self.spv.gpa, .OpIsNan, .{ |
| 2414 | .id_result_type = self.typeId(bool_ty_ref), | 2413 | .id_result_type = self.typeId(bool_ty_ref), |
| 2415 | .id_result = float_cmp_id, | 2414 | .id_result = rhs_is_nan_id, |
| 2416 | .operand_1 = cmp_id, | 2415 | .x = rhs_elem_id, |
| 2417 | .operand_2 = rhs_is_nan_id, | 2416 | }); |
| 2418 | }); | 2417 | const float_cmp_id = self.spv.allocId(); |
| 2419 | break :blk float_cmp_id; | 2418 | try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{ |
| 2420 | }, | 2419 | .id_result_type = self.typeId(bool_ty_ref), |
| 2421 | else => cmp_id, | 2420 | .id_result = float_cmp_id, |
| 2422 | }; | 2421 | .operand_1 = cmp_id, |
| 2422 | .operand_2 = rhs_is_nan_id, | ||
| 2423 | }); | ||
| 2424 | break :blk float_cmp_id; | ||
| 2425 | }, | ||
| 2426 | else => cmp_id, | ||
| 2427 | }; | ||
| 2423 | 2428 | ||
| 2424 | const result_id = self.spv.allocId(); | 2429 | result_id.* = self.spv.allocId(); |
| 2425 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ | 2430 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ |
| 2426 | .id_result_type = self.typeId(result_ty_ref), | 2431 | .id_result_type = wip.scalar_ty_id, |
| 2427 | .id_result = result_id, | 2432 | .id_result = result_id.*, |
| 2428 | .condition = selection_id, | 2433 | .condition = selection_id, |
| 2429 | .object_1 = lhs_id, | 2434 | .object_1 = lhs_elem_id, |
| 2430 | .object_2 = rhs_id, | 2435 | .object_2 = rhs_elem_id, |
| 2431 | }); | 2436 | }); |
| 2432 | return result_id; | 2437 | } |
| 2438 | return wip.finalize(); | ||
| 2433 | } | 2439 | } |
| 2434 | 2440 | ||
| 2435 | /// This function normalizes values to a canonical representation | 2441 | /// This function normalizes values to a canonical representation |
| ... | @@ -3107,20 +3113,15 @@ const DeclGen = struct { | ... | @@ -3107,20 +3113,15 @@ const DeclGen = struct { |
| 3107 | return result_id; | 3113 | return result_id; |
| 3108 | }, | 3114 | }, |
| 3109 | .Vector => { | 3115 | .Vector => { |
| 3110 | const child_ty = ty.childType(mod); | 3116 | var wip = try self.elementWise(result_ty); |
| 3111 | const vector_len = ty.vectorLen(mod); | 3117 | defer wip.deinit(); |
| 3112 | 3118 | const scalar_ty = ty.scalarType(mod); | |
| 3113 | const constituents = try self.gpa.alloc(IdRef, vector_len); | 3119 | for (wip.results, 0..) |*result_id, i| { |
| 3114 | defer self.gpa.free(constituents); | 3120 | const lhs_elem_id = try wip.elementAt(ty, lhs_id, i); |
| 3115 | 3121 | const rhs_elem_id = try wip.elementAt(ty, rhs_id, i); | |
| 3116 | for (constituents, 0..) |*constituent, i| { | 3122 | result_id.* = try self.cmp(op, Type.bool, scalar_ty, lhs_elem_id, rhs_elem_id); |
| 3117 | const lhs_index_id = try self.extractField(child_ty, cmp_lhs_id, @intCast(i)); | ||
| 3118 | const rhs_index_id = try self.extractField(child_ty, cmp_rhs_id, @intCast(i)); | ||
| 3119 | const result_id = try self.cmp(op, Type.bool, child_ty, lhs_index_id, rhs_index_id); | ||
| 3120 | constituent.* = try self.convertToIndirect(Type.bool, result_id); | ||
| 3121 | } | 3123 | } |
| 3122 | 3124 | return wip.finalize(); | |
| 3123 | return try self.constructArray(result_ty, constituents); | ||
| 3124 | }, | 3125 | }, |
| 3125 | else => unreachable, | 3126 | else => unreachable, |
| 3126 | }; | 3127 | }; |
test/behavior/maximum_minimum.zig-5| ... | @@ -31,7 +31,6 @@ test "@max on vectors" { | ... | @@ -31,7 +31,6 @@ test "@max on vectors" { |
| 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 32 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 32 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 33 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 33 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 34 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 35 | if (builtin.zig_backend == .stage2_x86_64 and | 34 | if (builtin.zig_backend == .stage2_x86_64 and |
| 36 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | 35 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; |
| 37 | 36 | ||
| ... | @@ -86,7 +85,6 @@ test "@min for vectors" { | ... | @@ -86,7 +85,6 @@ test "@min for vectors" { |
| 86 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 85 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 87 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 86 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 88 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 87 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 89 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 90 | if (builtin.zig_backend == .stage2_x86_64 and | 88 | if (builtin.zig_backend == .stage2_x86_64 and |
| 91 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | 89 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; |
| 92 | 90 | ||
| ... | @@ -199,7 +197,6 @@ test "@min/@max notices vector bounds" { | ... | @@ -199,7 +197,6 @@ test "@min/@max notices vector bounds" { |
| 199 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 197 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 200 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 198 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 201 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 199 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 202 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 203 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 200 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 204 | 201 | ||
| 205 | var x: @Vector(2, u16) = .{ 140, 40 }; | 202 | var x: @Vector(2, u16) = .{ 140, 40 }; |
| ... | @@ -253,7 +250,6 @@ test "@min/@max notices bounds from vector types" { | ... | @@ -253,7 +250,6 @@ test "@min/@max notices bounds from vector types" { |
| 253 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 250 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 254 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 251 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 255 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 252 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 256 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 257 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 253 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 258 | 254 | ||
| 259 | var x: @Vector(2, u16) = .{ 30, 67 }; | 255 | var x: @Vector(2, u16) = .{ 30, 67 }; |
| ... | @@ -295,7 +291,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known | ... | @@ -295,7 +291,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known |
| 295 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 291 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 296 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 292 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 297 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 293 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 298 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 299 | if (builtin.zig_backend == .stage2_x86_64 and | 294 | if (builtin.zig_backend == .stage2_x86_64 and |
| 300 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest; | 295 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest; |
| 301 | 296 |