| ... | ... | @@ -17910,12 +17910,15 @@ fn cmpSelf( |
| 17910 | 17910 | const pt = sema.pt; |
| 17911 | 17911 | const zcu = pt.zcu; |
| 17912 | 17912 | const resolved_type = sema.typeOf(casted_lhs); |
| 17913 | | const runtime_src: LazySrcLoc = src: { |
| 17914 | | if (try sema.resolveValue(casted_lhs)) |lhs_val| { |
| 17915 | | if (lhs_val.isUndef(zcu)) return pt.undefRef(Type.bool); |
| 17916 | | if (try sema.resolveValue(casted_rhs)) |rhs_val| { |
| 17917 | | if (rhs_val.isUndef(zcu)) return pt.undefRef(Type.bool); |
| 17918 | 17913 | |
| 17914 | const maybe_lhs_val = try sema.resolveValue(casted_lhs); |
| 17915 | const maybe_rhs_val = try sema.resolveValue(casted_rhs); |
| 17916 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); |
| 17917 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); |
| 17918 | |
| 17919 | const runtime_src: LazySrcLoc = src: { |
| 17920 | if (maybe_lhs_val) |lhs_val| { |
| 17921 | if (maybe_rhs_val) |rhs_val| { |
| 17919 | 17922 | if (resolved_type.zigTypeTag(zcu) == .vector) { |
| 17920 | 17923 | const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_type); |
| 17921 | 17924 | return Air.internedToRef(cmp_val.toIntern()); |
| ... | ... | @@ -17936,8 +17939,7 @@ fn cmpSelf( |
| 17936 | 17939 | // For bools, we still check the other operand, because we can lower |
| 17937 | 17940 | // bool eq/neq more efficiently. |
| 17938 | 17941 | if (resolved_type.zigTypeTag(zcu) == .bool) { |
| 17939 | | if (try sema.resolveValue(casted_rhs)) |rhs_val| { |
| 17940 | | if (rhs_val.isUndef(zcu)) return pt.undefRef(Type.bool); |
| 17942 | if (maybe_rhs_val) |rhs_val| { |
| 17941 | 17943 | return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src); |
| 17942 | 17944 | } |
| 17943 | 17945 | } |
| ... | ... | @@ -33809,51 +33811,47 @@ fn cmpNumeric( |
| 33809 | 33811 | else |
| 33810 | 33812 | uncasted_rhs; |
| 33811 | 33813 | |
| 33812 | | const runtime_src: LazySrcLoc = src: { |
| 33813 | | if (try sema.resolveValue(lhs)) |lhs_val| { |
| 33814 | | if (try sema.resolveValue(rhs)) |rhs_val| { |
| 33815 | | // Compare ints: const vs. undefined (or vice versa) |
| 33816 | | if (!lhs_val.isUndef(zcu) and (lhs_ty.isInt(zcu) or lhs_ty_tag == .comptime_int) and rhs_ty.isInt(zcu) and rhs_val.isUndef(zcu)) { |
| 33817 | | if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(lhs_val), op, rhs_ty)) |res| { |
| 33818 | | return if (res) .bool_true else .bool_false; |
| 33819 | | } |
| 33820 | | } else if (!rhs_val.isUndef(zcu) and (rhs_ty.isInt(zcu) or rhs_ty_tag == .comptime_int) and lhs_ty.isInt(zcu) and lhs_val.isUndef(zcu)) { |
| 33821 | | if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(rhs_val), op.reverse(), lhs_ty)) |res| { |
| 33822 | | return if (res) .bool_true else .bool_false; |
| 33823 | | } |
| 33824 | | } |
| 33814 | const maybe_lhs_val = try sema.resolveValue(lhs); |
| 33815 | const maybe_rhs_val = try sema.resolveValue(rhs); |
| 33825 | 33816 | |
| 33826 | | if (lhs_val.isUndef(zcu) or rhs_val.isUndef(zcu)) { |
| 33827 | | return pt.undefRef(Type.bool); |
| 33828 | | } |
| 33829 | | if (lhs_val.isNan(zcu) or rhs_val.isNan(zcu)) { |
| 33830 | | return if (op == std.math.CompareOperator.neq) .bool_true else .bool_false; |
| 33831 | | } |
| 33832 | | return if (try Value.compareHeteroSema(lhs_val, op, rhs_val, pt)) |
| 33833 | | .bool_true |
| 33834 | | else |
| 33835 | | .bool_false; |
| 33836 | | } else { |
| 33837 | | if (!lhs_val.isUndef(zcu) and (lhs_ty.isInt(zcu) or lhs_ty_tag == .comptime_int) and rhs_ty.isInt(zcu)) { |
| 33838 | | // Compare ints: const vs. var |
| 33839 | | if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(lhs_val), op, rhs_ty)) |res| { |
| 33840 | | return if (res) .bool_true else .bool_false; |
| 33841 | | } |
| 33842 | | } |
| 33843 | | break :src rhs_src; |
| 33817 | // If the LHS is const, check if there is a guaranteed result which does not depend on ths RHS. |
| 33818 | if (maybe_lhs_val) |lhs_val| { |
| 33819 | // Result based on comparison exceeding type bounds |
| 33820 | if (!lhs_val.isUndef(zcu) and (lhs_ty.isInt(zcu) or lhs_ty_tag == .comptime_int) and rhs_ty.isInt(zcu)) { |
| 33821 | if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(lhs_val), op, rhs_ty)) |res| { |
| 33822 | return if (res) .bool_true else .bool_false; |
| 33844 | 33823 | } |
| 33845 | | } else { |
| 33846 | | if (try sema.resolveValueResolveLazy(rhs)) |rhs_val| { |
| 33847 | | if (!rhs_val.isUndef(zcu) and (rhs_ty.isInt(zcu) or rhs_ty_tag == .comptime_int) and lhs_ty.isInt(zcu)) { |
| 33848 | | // Compare ints: var vs. const |
| 33849 | | if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(rhs_val), op.reverse(), lhs_ty)) |res| { |
| 33850 | | return if (res) .bool_true else .bool_false; |
| 33851 | | } |
| 33852 | | } |
| 33824 | } |
| 33825 | // Result based on NaN comparison |
| 33826 | if (lhs_val.isNan(zcu)) { |
| 33827 | return if (op == .neq) .bool_true else .bool_false; |
| 33828 | } |
| 33829 | } |
| 33830 | |
| 33831 | // If the RHS is const, check if there is a guaranteed result which does not depend on ths LHS. |
| 33832 | if (maybe_rhs_val) |rhs_val| { |
| 33833 | // Result based on comparison exceeding type bounds |
| 33834 | if (!rhs_val.isUndef(zcu) and (rhs_ty.isInt(zcu) or rhs_ty_tag == .comptime_int) and lhs_ty.isInt(zcu)) { |
| 33835 | if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(rhs_val), op.reverse(), lhs_ty)) |res| { |
| 33836 | return if (res) .bool_true else .bool_false; |
| 33853 | 33837 | } |
| 33854 | | break :src lhs_src; |
| 33855 | 33838 | } |
| 33856 | | }; |
| 33839 | // Result based on NaN comparison |
| 33840 | if (rhs_val.isNan(zcu)) { |
| 33841 | return if (op == .neq) .bool_true else .bool_false; |
| 33842 | } |
| 33843 | } |
| 33844 | |
| 33845 | // Any other comparison depends on both values, so the result is undef if either is undef. |
| 33846 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); |
| 33847 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); |
| 33848 | |
| 33849 | const runtime_src: LazySrcLoc = if (maybe_lhs_val) |lhs_val| rs: { |
| 33850 | if (maybe_rhs_val) |rhs_val| { |
| 33851 | const res = try Value.compareHeteroSema(lhs_val, op, rhs_val, pt); |
| 33852 | return if (res) .bool_true else .bool_false; |
| 33853 | } else break :rs rhs_src; |
| 33854 | } else lhs_src; |
| 33857 | 33855 | |
| 33858 | 33856 | // TODO handle comparisons against lazy zero values |
| 33859 | 33857 | // Some values can be compared against zero without being runtime-known or without forcing |
| ... | ... | @@ -34161,21 +34159,17 @@ fn cmpVector( |
| 34161 | 34159 | .child = .bool_type, |
| 34162 | 34160 | }); |
| 34163 | 34161 | |
| 34164 | | const runtime_src: LazySrcLoc = src: { |
| 34165 | | if (try sema.resolveValue(casted_lhs)) |lhs_val| { |
| 34166 | | if (try sema.resolveValue(casted_rhs)) |rhs_val| { |
| 34167 | | if (lhs_val.isUndef(zcu) or rhs_val.isUndef(zcu)) { |
| 34168 | | return pt.undefRef(result_ty); |
| 34169 | | } |
| 34170 | | const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_ty); |
| 34171 | | return Air.internedToRef(cmp_val.toIntern()); |
| 34172 | | } else { |
| 34173 | | break :src rhs_src; |
| 34174 | | } |
| 34175 | | } else { |
| 34176 | | break :src lhs_src; |
| 34177 | | } |
| 34178 | | }; |
| 34162 | const maybe_lhs_val = try sema.resolveValue(casted_lhs); |
| 34163 | const maybe_rhs_val = try sema.resolveValue(casted_rhs); |
| 34164 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(result_ty); |
| 34165 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(result_ty); |
| 34166 | |
| 34167 | const runtime_src: LazySrcLoc = if (maybe_lhs_val) |lhs_val| src: { |
| 34168 | if (maybe_rhs_val) |rhs_val| { |
| 34169 | const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_ty); |
| 34170 | return Air.internedToRef(cmp_val.toIntern()); |
| 34171 | } else break :src rhs_src; |
| 34172 | } else lhs_src; |
| 34179 | 34173 | |
| 34180 | 34174 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 34181 | 34175 | return block.addCmpVector(casted_lhs, casted_rhs, op); |
| ... | ... | @@ -38662,8 +38656,12 @@ fn compareVector( |
| 38662 | 38656 | for (result_data, 0..) |*scalar, i| { |
| 38663 | 38657 | const lhs_elem = try lhs.elemValue(pt, i); |
| 38664 | 38658 | const rhs_elem = try rhs.elemValue(pt, i); |
| 38665 | | const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(zcu)); |
| 38666 | | scalar.* = Value.makeBool(res_bool).toIntern(); |
| 38659 | if (lhs_elem.isUndef(zcu) or rhs_elem.isUndef(zcu)) { |
| 38660 | scalar.* = try pt.intern(.{ .undef = .bool_type }); |
| 38661 | } else { |
| 38662 | const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(zcu)); |
| 38663 | scalar.* = Value.makeBool(res_bool).toIntern(); |
| 38664 | } |
| 38667 | 38665 | } |
| 38668 | 38666 | return Value.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 38669 | 38667 | .ty = (try pt.vectorType(.{ .len = ty.vectorLen(zcu), .child = .bool_type })).toIntern(), |