| ... | @@ -3307,35 +3307,76 @@ const DeclGen = struct { | ... | @@ -3307,35 +3307,76 @@ const DeclGen = struct { |
| 3307 | else | 3307 | else |
| 3308 | try self.convertToDirect(Type.bool, rhs_id); | 3308 | try self.convertToDirect(Type.bool, rhs_id); |
| 3309 | | 3309 | |
| 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 | } |
| 3314 | | 3313 | |
| 3315 | // TODO: Should we short circuit here? It shouldn't affect correctness, but | 3314 | // 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 |
| 3317 | | 3328 | |
| 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); |
| 3320 | | 3331 | |
| 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); |