authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-01-15 21:58:13+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-02-04 19:08:59+01:00
log747f4ae3f5efc89df0b1b76787eb90eab90fc362
tree567e3c45295fbcc424dffd713a0bd04a252fe000
parent3ef5b80d2c359c94ec2fa14bde492a6c9774d536
signaturebadge-check Signed by SSH key SHA256:ZS52FNyUv2WUXvO4njmVaFVO46RHojFuOrxRc4LuKzg

spirv: sh[rl](_exact)?


2 files changed, 29 insertions(+), 19 deletions(-)

src/codegen/spirv.zig+29-14
...@@ -2111,7 +2111,8 @@ const DeclGen = struct {...@@ -2111,7 +2111,8 @@ const DeclGen = struct {
2111 .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd),2111 .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd),
2112 .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr),2112 .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr),
21132113
2114 .shl => try self.airShift(inst, .OpShiftLeftLogical),2114 .shl, .shl_exact => try self.airShift(inst, .OpShiftLeftLogical, .OpShiftLeftLogical),
2115 .shr, .shr_exact => try self.airShift(inst, .OpShiftRightLogical, .OpShiftRightArithmetic),
21152116
2116 .min => try self.airMinMax(inst, .lt),2117 .min => try self.airMinMax(inst, .lt),
2117 .max => try self.airMinMax(inst, .gt),2118 .max => try self.airMinMax(inst, .gt),
...@@ -2254,28 +2255,42 @@ const DeclGen = struct {...@@ -2254,28 +2255,42 @@ const DeclGen = struct {
2254 return try self.binOpSimple(ty, lhs_id, rhs_id, opcode);2255 return try self.binOpSimple(ty, lhs_id, rhs_id, opcode);
2255 }2256 }
22562257
2257 fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef {2258 fn airShift(self: *DeclGen, inst: Air.Inst.Index, comptime unsigned: Opcode, comptime signed: Opcode) !?IdRef {
2258 if (self.liveness.isUnused(inst)) return null;2259 if (self.liveness.isUnused(inst)) return null;
2260 const mod = self.module;
2259 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2261 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2260 const lhs_id = try self.resolve(bin_op.lhs);2262 const lhs_id = try self.resolve(bin_op.lhs);
2261 const rhs_id = try self.resolve(bin_op.rhs);2263 const rhs_id = try self.resolve(bin_op.rhs);
2262 const result_type_id = try self.resolveTypeId(self.typeOfIndex(inst));2264 const result_ty = self.typeOfIndex(inst);
22632265 const result_ty_ref = try self.resolveType(result_ty, .direct);
2264 // the shift and the base must be the same type in SPIR-V, but in Zig the shift is a smaller int.
2265 const shift_id = self.spv.allocId();
2266 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
2267 .id_result_type = result_type_id,
2268 .id_result = shift_id,
2269 .unsigned_value = rhs_id,
2270 });
22712266
2272 const result_id = self.spv.allocId();2267 const result_id = self.spv.allocId();
2273 try self.func.body.emit(self.spv.gpa, opcode, .{2268
2274 .id_result_type = result_type_id,2269 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,
2270 // so just manually upcast it if required.
2271 const shift_ty_ref = try self.resolveType(self.typeOf(bin_op.rhs), .direct);
2272 const shift_id = if (shift_ty_ref != result_ty_ref) blk: {
2273 const shift_id = self.spv.allocId();
2274 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
2275 .id_result_type = self.typeId(result_ty_ref),
2276 .id_result = shift_id,
2277 .unsigned_value = rhs_id,
2278 });
2279 break :blk shift_id;
2280 } else rhs_id;
2281
2282 const args = .{
2283 .id_result_type = self.typeId(result_ty_ref),
2275 .id_result = result_id,2284 .id_result = result_id,
2276 .base = lhs_id,2285 .base = lhs_id,
2277 .shift = shift_id,2286 .shift = shift_id,
2278 });2287 };
2288
2289 if (result_ty.isSignedInt(mod)) {
2290 try self.func.body.emit(self.spv.gpa, signed, args);
2291 } else {
2292 try self.func.body.emit(self.spv.gpa, unsigned, args);
2293 }
2279 return result_id;2294 return result_id;
2280 }2295 }
22812296
test/behavior/math.zig-5
...@@ -12,7 +12,6 @@ const math = std.math;...@@ -12,7 +12,6 @@ const math = std.math;
12test "assignment operators" {12test "assignment operators" {
13 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO13 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1615
17 var i: u32 = 0;16 var i: u32 = 0;
18 i += 5;17 i += 5;
...@@ -649,8 +648,6 @@ test "bit shift a u1" {...@@ -649,8 +648,6 @@ test "bit shift a u1" {
649}648}
650649
651test "truncating shift right" {650test "truncating shift right" {
652 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
653
654 try testShrTrunc(maxInt(u16));651 try testShrTrunc(maxInt(u16));
655 try comptime testShrTrunc(maxInt(u16));652 try comptime testShrTrunc(maxInt(u16));
656}653}
...@@ -1343,8 +1340,6 @@ fn testShlExact(x: u8) !void {...@@ -1343,8 +1340,6 @@ fn testShlExact(x: u8) !void {
1343}1340}
13441341
1345test "exact shift right" {1342test "exact shift right" {
1346 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1347
1348 try testShrExact(0b10110100);1343 try testShrExact(0b10110100);
1349 try comptime testShrExact(0b10110100);1344 try comptime testShrExact(0b10110100);
1350}1345}