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