@@ -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) and (rhs_ty.isInt(zcu) or rhs_ty_tag == .comptime_int)) {
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) and (lhs_ty.isInt(zcu) or lhs_ty_tag == .comptime_int)) {
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(),
0 commit comments