mirror of
https://github.com/ziglang/zig.git
synced 2026-02-02 12:43:40 +00:00
spirv: fix optional comparison
This commit is contained in:
parent
8ed134243a
commit
335ff5a5f4
@ -3307,35 +3307,76 @@ const DeclGen = struct {
|
||||
else
|
||||
try self.convertToDirect(Type.bool, rhs_id);
|
||||
|
||||
const valid_cmp_id = try self.cmp(op, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
return valid_cmp_id;
|
||||
return try self.cmp(op, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
|
||||
}
|
||||
|
||||
// TODO: Should we short circuit here? It shouldn't affect correctness, but
|
||||
// perhaps it will generate more efficient code.
|
||||
// a = lhs_valid
|
||||
// b = rhs_valid
|
||||
// c = lhs_pl == rhs_pl
|
||||
//
|
||||
// For op == .eq we have:
|
||||
// a == b && a -> c
|
||||
// = a == b && (!a || c)
|
||||
//
|
||||
// For op == .neq we have
|
||||
// a == b && a -> c
|
||||
// = !(a == b && a -> c)
|
||||
// = a != b || !(a -> c
|
||||
// = a != b || !(!a || c)
|
||||
// = a != b || a && !c
|
||||
|
||||
const lhs_pl_id = try self.extractField(payload_ty, lhs_id, 0);
|
||||
const rhs_pl_id = try self.extractField(payload_ty, rhs_id, 0);
|
||||
|
||||
const pl_cmp_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
|
||||
|
||||
// op == .eq => lhs_valid == rhs_valid && lhs_pl == rhs_pl
|
||||
// op == .neq => lhs_valid != rhs_valid || lhs_pl != rhs_pl
|
||||
|
||||
const result_id = self.spv.allocId();
|
||||
const args = .{
|
||||
.id_result_type = self.typeId(bool_ty_ref),
|
||||
.id_result = result_id,
|
||||
.operand_1 = valid_cmp_id,
|
||||
.operand_2 = pl_cmp_id,
|
||||
};
|
||||
switch (op) {
|
||||
.eq => try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, args),
|
||||
.neq => try self.func.body.emit(self.spv.gpa, .OpLogicalOr, args),
|
||||
.eq => {
|
||||
const valid_eq_id = try self.cmp(.eq, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
|
||||
const pl_eq_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
|
||||
const lhs_not_valid_id = self.spv.allocId();
|
||||
try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{
|
||||
.id_result_type = self.typeId(bool_ty_ref),
|
||||
.id_result = lhs_not_valid_id,
|
||||
.operand = lhs_valid_id,
|
||||
});
|
||||
const impl_id = self.spv.allocId();
|
||||
try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{
|
||||
.id_result_type = self.typeId(bool_ty_ref),
|
||||
.id_result = impl_id,
|
||||
.operand_1 = lhs_not_valid_id,
|
||||
.operand_2 = pl_eq_id,
|
||||
});
|
||||
const result_id = self.spv.allocId();
|
||||
try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{
|
||||
.id_result_type = self.typeId(bool_ty_ref),
|
||||
.id_result = result_id,
|
||||
.operand_1 = valid_eq_id,
|
||||
.operand_2 = impl_id,
|
||||
});
|
||||
return result_id;
|
||||
},
|
||||
.neq => {
|
||||
const valid_neq_id = try self.cmp(.neq, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
|
||||
const pl_neq_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
|
||||
|
||||
const impl_id = self.spv.allocId();
|
||||
try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{
|
||||
.id_result_type = self.typeId(bool_ty_ref),
|
||||
.id_result = impl_id,
|
||||
.operand_1 = lhs_valid_id,
|
||||
.operand_2 = pl_neq_id,
|
||||
});
|
||||
const result_id = self.spv.allocId();
|
||||
try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{
|
||||
.id_result_type = self.typeId(bool_ty_ref),
|
||||
.id_result = result_id,
|
||||
.operand_1 = valid_neq_id,
|
||||
.operand_2 = impl_id,
|
||||
});
|
||||
return result_id;
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
return result_id;
|
||||
},
|
||||
.Vector => {
|
||||
var wip = try self.elementWise(result_ty, true);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user