authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-03-17 18:18:35+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-03-18 19:13:50+01:00
log335ff5a5f422256765892dfb4ffebeeb2b9d581b
tree7dcc7156472aa7972a1635fd7a2c25fdd3b25382
parent8ed134243ac9b3d1286153f95495176875472669
signaturebadge-check Signed by SSH key SHA256:ZS52FNyUv2WUXvO4njmVaFVO46RHojFuOrxRc4LuKzg

spirv: fix optional comparison


1 files changed, 60 insertions(+), 19 deletions(-)

src/codegen/spirv.zig+60-19
...@@ -3307,35 +3307,76 @@ const DeclGen = struct {...@@ -3307,35 +3307,76 @@ const DeclGen = struct {
3307 else3307 else
3308 try self.convertToDirect(Type.bool, rhs_id);3308 try self.convertToDirect(Type.bool, rhs_id);
33093309
3310 const valid_cmp_id = try self.cmp(op, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
3311 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {3310 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3312 return valid_cmp_id;3311 return try self.cmp(op, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
3313 }3312 }
33143313
3315 // TODO: Should we short circuit here? It shouldn't affect correctness, but3314 // a = lhs_valid
3316 // perhaps it will generate more efficient code.3315 // b = rhs_valid
3316 // c = lhs_pl == rhs_pl
3317 //
3318 // For op == .eq we have:
3319 // a == b && a -> c
3320 // = a == b && (!a || c)
3321 //
3322 // For op == .neq we have
3323 // a == b && a -> c
3324 // = !(a == b && a -> c)
3325 // = a != b || !(a -> c
3326 // = a != b || !(!a || c)
3327 // = a != b || a && !c
33173328
3318 const lhs_pl_id = try self.extractField(payload_ty, lhs_id, 0);3329 const lhs_pl_id = try self.extractField(payload_ty, lhs_id, 0);
3319 const rhs_pl_id = try self.extractField(payload_ty, rhs_id, 0);3330 const rhs_pl_id = try self.extractField(payload_ty, rhs_id, 0);
33203331
3321 const pl_cmp_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
3322
3323 // op == .eq => lhs_valid == rhs_valid && lhs_pl == rhs_pl
3324 // op == .neq => lhs_valid != rhs_valid || lhs_pl != rhs_pl
3325
3326 const result_id = self.spv.allocId();
3327 const args = .{
3328 .id_result_type = self.typeId(bool_ty_ref),
3329 .id_result = result_id,
3330 .operand_1 = valid_cmp_id,
3331 .operand_2 = pl_cmp_id,
3332 };
3333 switch (op) {3332 switch (op) {
3334 .eq => try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, args),3333 .eq => {
3335 .neq => try self.func.body.emit(self.spv.gpa, .OpLogicalOr, args),3334 const valid_eq_id = try self.cmp(.eq, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
3335 const pl_eq_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
3336 const lhs_not_valid_id = self.spv.allocId();
3337 try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{
3338 .id_result_type = self.typeId(bool_ty_ref),
3339 .id_result = lhs_not_valid_id,
3340 .operand = lhs_valid_id,
3341 });
3342 const impl_id = self.spv.allocId();
3343 try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{
3344 .id_result_type = self.typeId(bool_ty_ref),
3345 .id_result = impl_id,
3346 .operand_1 = lhs_not_valid_id,
3347 .operand_2 = pl_eq_id,
3348 });
3349 const result_id = self.spv.allocId();
3350 try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{
3351 .id_result_type = self.typeId(bool_ty_ref),
3352 .id_result = result_id,
3353 .operand_1 = valid_eq_id,
3354 .operand_2 = impl_id,
3355 });
3356 return result_id;
3357 },
3358 .neq => {
3359 const valid_neq_id = try self.cmp(.neq, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
3360 const pl_neq_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
3361
3362 const impl_id = self.spv.allocId();
3363 try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{
3364 .id_result_type = self.typeId(bool_ty_ref),
3365 .id_result = impl_id,
3366 .operand_1 = lhs_valid_id,
3367 .operand_2 = pl_neq_id,
3368 });
3369 const result_id = self.spv.allocId();
3370 try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{
3371 .id_result_type = self.typeId(bool_ty_ref),
3372 .id_result = result_id,
3373 .operand_1 = valid_neq_id,
3374 .operand_2 = impl_id,
3375 });
3376 return result_id;
3377 },
3336 else => unreachable,3378 else => unreachable,
3337 }3379 }
3338 return result_id;
3339 },3380 },
3340 .Vector => {3381 .Vector => {
3341 var wip = try self.elementWise(result_ty, true);3382 var wip = try self.elementWise(result_ty, true);