authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-10-05 05:34:52-07:00
committergravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-11-10 12:24:02-07:00
log7b978bf1e05727f15fc83ae7d2455c08833cc439
tree61648de296eb45d762d0bc8440d144a32dea896d
parentb1357091ae0876645d75a608bd1e26f21cec7c13

stage2: Rename `Value.compare` to `compareAll`, etc.

These functions have a very error-prone API. They are essentially `all(cmp(op, ...))` but that's not reflected in the name. This renames these functions to `compareAllAgainstZero...` etc. for clarity and fixes >20 locations where the predicate was incorrect. In the future, the scalar `compare` should probably be split off from the vector comparison. Rank-polymorphic programming is great, but a proper implementation in Zig would decouple comparison and reduction, which then needs a way to fuse ops at comptime.

4 files changed, 101 insertions(+), 96 deletions(-)

src/RangeSet.zig+3-3
......@@ -35,8 +35,8 @@ pub fn add(
3535 src: SwitchProngSrc,
3636) !?SwitchProngSrc {
3737 for (self.ranges.items) |range| {
38 if (last.compare(.gte, range.first, ty, self.module) and
39 first.compare(.lte, range.last, ty, self.module))
38 if (last.compareAll(.gte, range.first, ty, self.module) and
39 first.compareAll(.lte, range.last, ty, self.module))
4040 {
4141 return range.src; // They overlap.
4242 }
......@@ -53,7 +53,7 @@ const LessThanContext = struct { ty: Type, module: *Module };
5353
5454/// Assumes a and b do not overlap
5555fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {
56 return a.first.compare(.lt, b.first, ctx.ty, ctx.module);
56 return a.first.compareAll(.lt, b.first, ctx.ty, ctx.module);
5757}
5858
5959pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
src/Sema.zig+83-80
......@@ -10333,8 +10333,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1033310333 // Validation above ensured these will succeed.
1033410334 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;
1033510335 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable;
10336 if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and
10337 (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty)))
10336 if ((try sema.compareAll(block, src, operand_val, .gte, first_tv.val, operand_ty)) and
10337 (try sema.compareAll(block, src, operand_val, .lte, last_tv.val, operand_ty)))
1033810338 {
1033910339 if (is_inline) child_block.inline_case_capture = operand;
1034010340 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
......@@ -10482,7 +10482,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1048210482 const item_last_ref = try sema.resolveInst(last_ref);
1048310483 const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable;
1048410484
10485 while (item.compare(.lte, item_last, operand_ty, sema.mod)) : ({
10485 while (item.compareAll(.lte, item_last, operand_ty, sema.mod)) : ({
1048610486 // Previous validation has resolved any possible lazy values.
1048710487 item = try sema.intAddScalar(block, .unneeded, item, Value.one);
1048810488 }) {
......@@ -10937,7 +10937,7 @@ const RangeSetUnhandledIterator = struct {
1093710937 it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty);
1093810938 }
1093910939 it.first = false;
10940 if (it.cur.compare(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) {
10940 if (it.cur.compareAll(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) {
1094110941 return it.cur;
1094210942 }
1094310943 it.cur = it.ranges[it.range_i].last;
......@@ -10946,7 +10946,7 @@ const RangeSetUnhandledIterator = struct {
1094610946 it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty);
1094710947 }
1094810948 it.first = false;
10949 if (it.cur.compare(.lte, it.max, it.ty, it.sema.mod)) {
10949 if (it.cur.compareAll(.lte, it.max, it.ty, it.sema.mod)) {
1095010950 return it.cur;
1095110951 }
1095210952 return null;
......@@ -10992,7 +10992,7 @@ fn validateSwitchRange(
1099210992) CompileError!void {
1099310993 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
1099410994 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;
10995 if (first_val.compare(.gt, last_val, operand_ty, sema.mod)) {
10995 if (first_val.compareAll(.gt, last_val, operand_ty, sema.mod)) {
1099610996 const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first);
1099710997 return sema.fail(block, src, "range start value is greater than the end value", .{});
1099810998 }
......@@ -11456,7 +11456,7 @@ fn zirShl(
1145611456 return sema.addConstUndef(sema.typeOf(lhs));
1145711457 }
1145811458 // If rhs is 0, return lhs without doing any calculations.
11459 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11459 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1146011460 return lhs;
1146111461 }
1146211462 if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) {
......@@ -11500,7 +11500,7 @@ fn zirShl(
1150011500 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
1150111501 break :val shifted.wrapped_result;
1150211502 }
11503 if (shifted.overflowed.compareWithZero(.eq)) {
11503 if (shifted.overflowed.compareAllWithZero(.eq)) {
1150411504 break :val shifted.wrapped_result;
1150511505 }
1150611506 return sema.fail(block, src, "operation caused overflow", .{});
......@@ -11625,7 +11625,7 @@ fn zirShr(
1162511625 return sema.addConstUndef(lhs_ty);
1162611626 }
1162711627 // If rhs is 0, return lhs without doing any calculations.
11628 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
11628 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1162911629 return lhs;
1163011630 }
1163111631 if (scalar_ty.zigTypeTag() != .ComptimeInt) {
......@@ -11659,7 +11659,7 @@ fn zirShr(
1165911659 if (air_tag == .shr_exact) {
1166011660 // Detect if any ones would be shifted out.
1166111661 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target);
11662 if (!(try truncated.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
11662 if (!(try truncated.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1166311663 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});
1166411664 }
1166511665 }
......@@ -12414,7 +12414,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1241412414 const lhs_val = maybe_lhs_val orelse unreachable;
1241512415 const rhs_val = maybe_rhs_val orelse unreachable;
1241612416 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target) catch unreachable;
12417 if (rem.compareWithZero(.neq)) {
12417 if (!rem.compareAllWithZero(.eq)) {
1241812418 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{
1241912419 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),
1242012420 });
......@@ -12452,7 +12452,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1245212452 .Int, .ComptimeInt, .ComptimeFloat => {
1245312453 if (maybe_lhs_val) |lhs_val| {
1245412454 if (!lhs_val.isUndef()) {
12455 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12455 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1245612456 const zero_val = if (is_vector) b: {
1245712457 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1245812458 } else Value.zero;
......@@ -12464,7 +12464,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1246412464 if (rhs_val.isUndef()) {
1246512465 return sema.failWithUseOfUndef(block, rhs_src);
1246612466 }
12467 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12467 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1246812468 return sema.failWithDivideByZero(block, rhs_src);
1246912469 }
1247012470 // TODO: if the RHS is one, return the LHS directly
......@@ -12478,7 +12478,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1247812478 if (lhs_val.isUndef()) {
1247912479 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
1248012480 if (maybe_rhs_val) |rhs_val| {
12481 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
12481 if (try sema.compareAll(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
1248212482 return sema.addConstUndef(resolved_type);
1248312483 }
1248412484 }
......@@ -12587,7 +12587,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1258712587 if (lhs_val.isUndef()) {
1258812588 return sema.failWithUseOfUndef(block, rhs_src);
1258912589 } else {
12590 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12590 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1259112591 const zero_val = if (is_vector) b: {
1259212592 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1259312593 } else Value.zero;
......@@ -12599,7 +12599,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1259912599 if (rhs_val.isUndef()) {
1260012600 return sema.failWithUseOfUndef(block, rhs_src);
1260112601 }
12602 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12602 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1260312603 return sema.failWithDivideByZero(block, rhs_src);
1260412604 }
1260512605 // TODO: if the RHS is one, return the LHS directly
......@@ -12608,7 +12608,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1260812608 if (maybe_rhs_val) |rhs_val| {
1260912609 if (is_int) {
1261012610 const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, target);
12611 if (modulus_val.compareWithZero(.neq)) {
12611 if (!(modulus_val.compareAllWithZero(.eq))) {
1261212612 return sema.fail(block, src, "exact division produced remainder", .{});
1261312613 }
1261412614 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target);
......@@ -12619,7 +12619,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1261912619 return sema.addConstant(resolved_type, res);
1262012620 } else {
1262112621 const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target);
12622 if (modulus_val.compareWithZero(.neq)) {
12622 if (!(modulus_val.compareAllWithZero(.eq))) {
1262312623 return sema.fail(block, src, "exact division produced remainder", .{});
1262412624 }
1262512625 return sema.addConstant(
......@@ -12753,7 +12753,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1275312753 // If the lhs is undefined, result is undefined.
1275412754 if (maybe_lhs_val) |lhs_val| {
1275512755 if (!lhs_val.isUndef()) {
12756 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12756 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1275712757 const zero_val = if (is_vector) b: {
1275812758 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1275912759 } else Value.zero;
......@@ -12765,7 +12765,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1276512765 if (rhs_val.isUndef()) {
1276612766 return sema.failWithUseOfUndef(block, rhs_src);
1276712767 }
12768 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12768 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1276912769 return sema.failWithDivideByZero(block, rhs_src);
1277012770 }
1277112771 // TODO: if the RHS is one, return the LHS directly
......@@ -12774,7 +12774,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1277412774 if (lhs_val.isUndef()) {
1277512775 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
1277612776 if (maybe_rhs_val) |rhs_val| {
12777 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
12777 if (try sema.compareAll(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
1277812778 return sema.addConstUndef(resolved_type);
1277912779 }
1278012780 }
......@@ -12870,7 +12870,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1287012870 // If the lhs is undefined, result is undefined.
1287112871 if (maybe_lhs_val) |lhs_val| {
1287212872 if (!lhs_val.isUndef()) {
12873 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12873 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1287412874 const zero_val = if (is_vector) b: {
1287512875 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1287612876 } else Value.zero;
......@@ -12882,7 +12882,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1288212882 if (rhs_val.isUndef()) {
1288312883 return sema.failWithUseOfUndef(block, rhs_src);
1288412884 }
12885 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
12885 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1288612886 return sema.failWithDivideByZero(block, rhs_src);
1288712887 }
1288812888 }
......@@ -12890,7 +12890,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1289012890 if (lhs_val.isUndef()) {
1289112891 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
1289212892 if (maybe_rhs_val) |rhs_val| {
12893 if (try sema.compare(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
12893 if (try sema.compareAll(block, src, rhs_val, .neq, Value.negative_one, resolved_type)) {
1289412894 return sema.addConstUndef(resolved_type);
1289512895 }
1289612896 }
......@@ -12961,12 +12961,12 @@ fn addDivIntOverflowSafety(
1296112961 // If the LHS is comptime-known to be not equal to the min int,
1296212962 // no overflow is possible.
1296312963 if (maybe_lhs_val) |lhs_val| {
12964 if (!lhs_val.compare(.eq, min_int, resolved_type, mod)) return;
12964 if (lhs_val.compareAll(.neq, min_int, resolved_type, mod)) return;
1296512965 }
1296612966
1296712967 // If the RHS is comptime-known to not be equal to -1, no overflow is possible.
1296812968 if (maybe_rhs_val) |rhs_val| {
12969 if (!rhs_val.compare(.eq, neg_one, resolved_type, mod)) return;
12969 if (rhs_val.compareAll(.neq, neg_one, resolved_type, mod)) return;
1297012970 }
1297112971
1297212972 var ok: Air.Inst.Ref = .none;
......@@ -13111,7 +13111,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1311113111 if (lhs_val.isUndef()) {
1311213112 return sema.failWithUseOfUndef(block, lhs_src);
1311313113 }
13114 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13114 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1311513115 const zero_val = if (is_vector) b: {
1311613116 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1311713117 } else Value.zero;
......@@ -13124,17 +13124,18 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1312413124 if (rhs_val.isUndef()) {
1312513125 return sema.failWithUseOfUndef(block, rhs_src);
1312613126 }
13127 switch (try rhs_val.orderAgainstZeroAdvanced(sema.kit(block, src))) {
13128 .lt => return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty),
13129 .eq => return sema.failWithDivideByZero(block, rhs_src),
13130 .gt => {},
13127 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
13128 return sema.failWithDivideByZero(block, rhs_src);
13129 }
13130 if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) {
13131 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
1313113132 }
1313213133 if (maybe_lhs_val) |lhs_val| {
1313313134 const rem_result = try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src);
1313413135 // If this answer could possibly be different by doing `intMod`,
1313513136 // we must emit a compile error. Otherwise, it's OK.
13136 if ((try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) and
13137 !(try rem_result.compareWithZeroAdvanced(.eq, sema.kit(block, src))))
13137 if (!(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src))) and
13138 !(try rem_result.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))))
1313813139 {
1313913140 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
1314013141 }
......@@ -13152,14 +13153,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1315213153 if (rhs_val.isUndef()) {
1315313154 return sema.failWithUseOfUndef(block, rhs_src);
1315413155 }
13155 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13156 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1315613157 return sema.failWithDivideByZero(block, rhs_src);
1315713158 }
13158 if (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) {
13159 if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) {
1315913160 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
1316013161 }
1316113162 if (maybe_lhs_val) |lhs_val| {
13162 if (lhs_val.isUndef() or (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src)))) {
13163 if (lhs_val.isUndef() or !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) {
1316313164 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
1316413165 }
1316513166 return sema.addConstant(
......@@ -13295,7 +13296,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1329513296 if (rhs_val.isUndef()) {
1329613297 return sema.failWithUseOfUndef(block, rhs_src);
1329713298 }
13298 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13299 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1329913300 return sema.failWithDivideByZero(block, rhs_src);
1330013301 }
1330113302 if (maybe_lhs_val) |lhs_val| {
......@@ -13314,7 +13315,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1331413315 if (rhs_val.isUndef()) {
1331513316 return sema.failWithUseOfUndef(block, rhs_src);
1331613317 }
13317 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13318 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1331813319 return sema.failWithDivideByZero(block, rhs_src);
1331913320 }
1332013321 }
......@@ -13398,7 +13399,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1339813399 if (rhs_val.isUndef()) {
1339913400 return sema.failWithUseOfUndef(block, rhs_src);
1340013401 }
13401 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13402 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1340213403 return sema.failWithDivideByZero(block, rhs_src);
1340313404 }
1340413405 if (maybe_lhs_val) |lhs_val| {
......@@ -13417,7 +13418,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1341713418 if (rhs_val.isUndef()) {
1341813419 return sema.failWithUseOfUndef(block, rhs_src);
1341913420 }
13420 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13421 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
1342113422 return sema.failWithDivideByZero(block, rhs_src);
1342213423 }
1342313424 }
......@@ -13496,12 +13497,12 @@ fn zirOverflowArithmetic(
1349613497 // to the result, even if it is undefined..
1349713498 // Otherwise, if either of the argument is undefined, undefined is returned.
1349813499 if (maybe_lhs_val) |lhs_val| {
13499 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
13500 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1350013501 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
1350113502 }
1350213503 }
1350313504 if (maybe_rhs_val) |rhs_val| {
13504 if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
13505 if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1350513506 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
1350613507 }
1350713508 }
......@@ -13524,7 +13525,7 @@ fn zirOverflowArithmetic(
1352413525 if (maybe_rhs_val) |rhs_val| {
1352513526 if (rhs_val.isUndef()) {
1352613527 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
13527 } else if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13528 } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1352813529 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
1352913530 } else if (maybe_lhs_val) |lhs_val| {
1353013531 if (lhs_val.isUndef()) {
......@@ -13544,9 +13545,9 @@ fn zirOverflowArithmetic(
1354413545 // Otherwise, if either of the arguments is undefined, both results are undefined.
1354513546 if (maybe_lhs_val) |lhs_val| {
1354613547 if (!lhs_val.isUndef()) {
13547 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13548 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1354813549 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
13549 } else if (try sema.compare(block, src, lhs_val, .eq, Value.one, dest_ty)) {
13550 } else if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, dest_ty)) {
1355013551 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
1355113552 }
1355213553 }
......@@ -13554,9 +13555,9 @@ fn zirOverflowArithmetic(
1355413555
1355513556 if (maybe_rhs_val) |rhs_val| {
1355613557 if (!rhs_val.isUndef()) {
13557 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13558 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1355813559 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
13559 } else if (try sema.compare(block, src, rhs_val, .eq, Value.one, dest_ty)) {
13560 } else if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, dest_ty)) {
1356013561 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
1356113562 }
1356213563 }
......@@ -13580,12 +13581,12 @@ fn zirOverflowArithmetic(
1358013581 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
1358113582 // Oterhwise if either of the arguments is undefined, both results are undefined.
1358213583 if (maybe_lhs_val) |lhs_val| {
13583 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
13584 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1358413585 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
1358513586 }
1358613587 }
1358713588 if (maybe_rhs_val) |rhs_val| {
13588 if (!rhs_val.isUndef() and (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
13589 if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1358913590 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
1359013591 }
1359113592 }
......@@ -13728,7 +13729,7 @@ fn analyzeArithmetic(
1372813729 // overflow (max_int), causing illegal behavior.
1372913730 // For floats: either operand being undef makes the result undef.
1373013731 if (maybe_lhs_val) |lhs_val| {
13731 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
13732 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1373213733 return casted_rhs;
1373313734 }
1373413735 }
......@@ -13740,7 +13741,7 @@ fn analyzeArithmetic(
1374013741 return sema.addConstUndef(resolved_type);
1374113742 }
1374213743 }
13743 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13744 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1374413745 return casted_lhs;
1374513746 }
1374613747 }
......@@ -13775,7 +13776,7 @@ fn analyzeArithmetic(
1377513776 // If either of the operands are zero, the other operand is returned.
1377613777 // If either of the operands are undefined, the result is undefined.
1377713778 if (maybe_lhs_val) |lhs_val| {
13778 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
13779 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1377913780 return casted_rhs;
1378013781 }
1378113782 }
......@@ -13784,7 +13785,7 @@ fn analyzeArithmetic(
1378413785 if (rhs_val.isUndef()) {
1378513786 return sema.addConstUndef(resolved_type);
1378613787 }
13787 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13788 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1378813789 return casted_lhs;
1378913790 }
1379013791 if (maybe_lhs_val) |lhs_val| {
......@@ -13800,7 +13801,7 @@ fn analyzeArithmetic(
1380013801 // If either of the operands are zero, then the other operand is returned.
1380113802 // If either of the operands are undefined, the result is undefined.
1380213803 if (maybe_lhs_val) |lhs_val| {
13803 if (!lhs_val.isUndef() and (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src)))) {
13804 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src)))) {
1380413805 return casted_rhs;
1380513806 }
1380613807 }
......@@ -13808,7 +13809,7 @@ fn analyzeArithmetic(
1380813809 if (rhs_val.isUndef()) {
1380913810 return sema.addConstUndef(resolved_type);
1381013811 }
13811 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13812 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1381213813 return casted_lhs;
1381313814 }
1381413815 if (maybe_lhs_val) |lhs_val| {
......@@ -13837,7 +13838,7 @@ fn analyzeArithmetic(
1383713838 return sema.addConstUndef(resolved_type);
1383813839 }
1383913840 }
13840 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13841 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1384113842 return casted_lhs;
1384213843 }
1384313844 }
......@@ -13875,7 +13876,7 @@ fn analyzeArithmetic(
1387513876 if (rhs_val.isUndef()) {
1387613877 return sema.addConstUndef(resolved_type);
1387713878 }
13878 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13879 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1387913880 return casted_lhs;
1388013881 }
1388113882 }
......@@ -13900,7 +13901,7 @@ fn analyzeArithmetic(
1390013901 if (rhs_val.isUndef()) {
1390113902 return sema.addConstUndef(resolved_type);
1390213903 }
13903 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13904 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1390413905 return casted_lhs;
1390513906 }
1390613907 }
......@@ -13929,13 +13930,13 @@ fn analyzeArithmetic(
1392913930 // For floats: either operand being undef makes the result undef.
1393013931 if (maybe_lhs_val) |lhs_val| {
1393113932 if (!lhs_val.isUndef()) {
13932 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13933 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1393313934 const zero_val = if (is_vector) b: {
1393413935 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1393513936 } else Value.zero;
1393613937 return sema.addConstant(resolved_type, zero_val);
1393713938 }
13938 if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) {
13939 if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, resolved_type)) {
1393913940 return casted_rhs;
1394013941 }
1394113942 }
......@@ -13949,13 +13950,13 @@ fn analyzeArithmetic(
1394913950 return sema.addConstUndef(resolved_type);
1395013951 }
1395113952 }
13952 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13953 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1395313954 const zero_val = if (is_vector) b: {
1395413955 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1395513956 } else Value.zero;
1395613957 return sema.addConstant(resolved_type, zero_val);
1395713958 }
13958 if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) {
13959 if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, resolved_type)) {
1395913960 return casted_lhs;
1396013961 }
1396113962 if (maybe_lhs_val) |lhs_val| {
......@@ -13989,13 +13990,13 @@ fn analyzeArithmetic(
1398913990 // If either of the operands are undefined, result is undefined.
1399013991 if (maybe_lhs_val) |lhs_val| {
1399113992 if (!lhs_val.isUndef()) {
13992 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
13993 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1399313994 const zero_val = if (is_vector) b: {
1399413995 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1399513996 } else Value.zero;
1399613997 return sema.addConstant(resolved_type, zero_val);
1399713998 }
13998 if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) {
13999 if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, resolved_type)) {
1399914000 return casted_rhs;
1400014001 }
1400114002 }
......@@ -14005,13 +14006,13 @@ fn analyzeArithmetic(
1400514006 if (rhs_val.isUndef()) {
1400614007 return sema.addConstUndef(resolved_type);
1400714008 }
14008 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
14009 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1400914010 const zero_val = if (is_vector) b: {
1401014011 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1401114012 } else Value.zero;
1401214013 return sema.addConstant(resolved_type, zero_val);
1401314014 }
14014 if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) {
14015 if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, resolved_type)) {
1401514016 return casted_lhs;
1401614017 }
1401714018 if (maybe_lhs_val) |lhs_val| {
......@@ -14032,13 +14033,13 @@ fn analyzeArithmetic(
1403214033 // If either of the operands are undefined, result is undefined.
1403314034 if (maybe_lhs_val) |lhs_val| {
1403414035 if (!lhs_val.isUndef()) {
14035 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
14036 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1403614037 const zero_val = if (is_vector) b: {
1403714038 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1403814039 } else Value.zero;
1403914040 return sema.addConstant(resolved_type, zero_val);
1404014041 }
14041 if (try sema.compare(block, src, lhs_val, .eq, Value.one, resolved_type)) {
14042 if (try sema.compareAll(block, src, lhs_val, .eq, Value.one, resolved_type)) {
1404214043 return casted_rhs;
1404314044 }
1404414045 }
......@@ -14047,13 +14048,13 @@ fn analyzeArithmetic(
1404714048 if (rhs_val.isUndef()) {
1404814049 return sema.addConstUndef(resolved_type);
1404914050 }
14050 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {
14051 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
1405114052 const zero_val = if (is_vector) b: {
1405214053 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
1405314054 } else Value.zero;
1405414055 return sema.addConstant(resolved_type, zero_val);
1405514056 }
14056 if (try sema.compare(block, src, rhs_val, .eq, Value.one, resolved_type)) {
14057 if (try sema.compareAll(block, src, rhs_val, .eq, Value.one, resolved_type)) {
1405714058 return casted_lhs;
1405814059 }
1405914060 if (maybe_lhs_val) |lhs_val| {
......@@ -14605,7 +14606,7 @@ fn cmpSelf(
1460514606 return sema.addConstant(result_ty, cmp_val);
1460614607 }
1460714608
14608 if (try sema.compare(block, lhs_src, lhs_val, op, rhs_val, resolved_type)) {
14609 if (try sema.compareAll(block, lhs_src, lhs_val, op, rhs_val, resolved_type)) {
1460914610 return Air.Inst.Ref.bool_true;
1461014611 } else {
1461114612 return Air.Inst.Ref.bool_false;
......@@ -27811,7 +27812,7 @@ fn analyzeSlice(
2781127812 sema.arena,
2781227813 array_ty.arrayLenIncludingSentinel(),
2781327814 );
27814 if (try sema.compare(block, src, end_val, .gt, len_s_val, Type.usize)) {
27815 if (!(try sema.compareAll(block, src, end_val, .lte, len_s_val, Type.usize))) {
2781527816 const sentinel_label: []const u8 = if (array_ty.sentinel() != null)
2781627817 " +1 (sentinel)"
2781727818 else
......@@ -27854,7 +27855,7 @@ fn analyzeSlice(
2785427855 .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel),
2785527856 };
2785627857 const slice_len_val = Value.initPayload(&int_payload.base);
27857 if (try sema.compare(block, src, end_val, .gt, slice_len_val, Type.usize)) {
27858 if (!(try sema.compareAll(block, src, end_val, .lte, slice_len_val, Type.usize))) {
2785827859 const sentinel_label: []const u8 = if (has_sentinel)
2785927860 " +1 (sentinel)"
2786027861 else
......@@ -27913,7 +27914,7 @@ fn analyzeSlice(
2791327914 // requirement: start <= end
2791427915 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
2791527916 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {
27916 if (try sema.compare(block, src, start_val, .gt, end_val, Type.usize)) {
27917 if (!(try sema.compareAll(block, src, start_val, .lte, end_val, Type.usize))) {
2791727918 return sema.fail(
2791827919 block,
2791927920 start_src,
......@@ -28202,11 +28203,11 @@ fn cmpNumeric(
2820228203 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,
2820328204 // add/subtract 1.
2820428205 const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val|
28205 (try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src)))
28206 !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))
2820628207 else
2820728208 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt());
2820828209 const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val|
28209 (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src)))
28210 !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))
2821028211 else
2821128212 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt());
2821228213 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
......@@ -31933,13 +31934,13 @@ fn intInRange(
3193331934 int_val: Value,
3193431935 end: usize,
3193531936) !bool {
31936 if (try int_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) return false;
31937 if (!(try int_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) return false;
3193731938 var end_payload: Value.Payload.U64 = .{
3193831939 .base = .{ .tag = .int_u64 },
3193931940 .data = end,
3194031941 };
3194131942 const end_val = Value.initPayload(&end_payload.base);
31942 if (try sema.compare(block, src, int_val, .gte, end_val, tag_ty)) return false;
31943 if (!(try sema.compareAll(block, src, int_val, .lt, end_val, tag_ty))) return false;
3194331944 return true;
3194431945}
3194531946
......@@ -32057,8 +32058,10 @@ fn intAddWithOverflowScalar(
3205732058}
3205832059
3205932060/// Asserts the values are comparable. Both operands have type `ty`.
32060/// Vector results will be reduced with AND.
32061fn compare(
32061/// For vectors, returns true if the comparison is true for ALL elements.
32062///
32063/// Note that `!compareAll(.eq, ...) != compareAll(.neq, ...)`
32064fn compareAll(
3206232065 sema: *Sema,
3206332066 block: *Block,
3206432067 src: LazySrcLoc,
src/type.zig+4-4
......@@ -5463,13 +5463,13 @@ pub const Type = extern union {
54635463 }
54645464 const S = struct {
54655465 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {
5466 if (int_val.compareWithZero(.lt)) return null;
5466 if (int_val.compareAllWithZero(.lt)) return null;
54675467 var end_payload: Value.Payload.U64 = .{
54685468 .base = .{ .tag = .int_u64 },
54695469 .data = end,
54705470 };
54715471 const end_val = Value.initPayload(&end_payload.base);
5472 if (int_val.compare(.gte, end_val, int_ty, m)) return null;
5472 if (int_val.compareAll(.gte, end_val, int_ty, m)) return null;
54735473 return @intCast(usize, int_val.toUnsignedInt(m.getTarget()));
54745474 }
54755475 };
......@@ -6455,12 +6455,12 @@ pub const Type = extern union {
64556455 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
64566456 switch (d.size) {
64576457 .Slice => {
6458 if (sent.compareWithZero(.eq)) {
6458 if (sent.compareAllWithZero(.eq)) {
64596459 return Type.initTag(.const_slice_u8_sentinel_0);
64606460 }
64616461 },
64626462 .Many => {
6463 if (sent.compareWithZero(.eq)) {
6463 if (sent.compareAllWithZero(.eq)) {
64646464 return Type.initTag(.manyptr_const_u8_sentinel_0);
64656465 }
64666466 },
src/value.zig+11-9
......@@ -2005,8 +2005,8 @@ pub const Value = extern union {
20052005 }
20062006
20072007 /// Asserts the values are comparable. Both operands have type `ty`.
2008 /// Vector results will be reduced with AND.
2009 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool {
2008 /// For vectors, returns true if comparison is true for ALL elements.
2009 pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool {
20102010 if (ty.zigTypeTag() == .Vector) {
20112011 var i: usize = 0;
20122012 while (i < ty.vectorLen()) : (i += 1) {
......@@ -2035,21 +2035,23 @@ pub const Value = extern union {
20352035 }
20362036
20372037 /// Asserts the value is comparable.
2038 /// Vector results will be reduced with AND.
2039 pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {
2040 return compareWithZeroAdvanced(lhs, op, null) catch unreachable;
2038 /// For vectors, returns true if comparison is true for ALL elements.
2039 ///
2040 /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`
2041 pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator) bool {
2042 return compareAllWithZeroAdvanced(lhs, op, null) catch unreachable;
20412043 }
20422044
2043 pub fn compareWithZeroAdvanced(
2045 pub fn compareAllWithZeroAdvanced(
20442046 lhs: Value,
20452047 op: std.math.CompareOperator,
20462048 sema_kit: ?Module.WipAnalysis,
20472049 ) Module.CompileError!bool {
20482050 switch (lhs.tag()) {
2049 .repeated => return lhs.castTag(.repeated).?.data.compareWithZeroAdvanced(op, sema_kit),
2051 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvanced(op, sema_kit),
20502052 .aggregate => {
20512053 for (lhs.castTag(.aggregate).?.data) |elem_val| {
2052 if (!(try elem_val.compareWithZeroAdvanced(op, sema_kit))) return false;
2054 if (!(try elem_val.compareAllWithZeroAdvanced(op, sema_kit))) return false;
20532055 }
20542056 return true;
20552057 },
......@@ -2982,7 +2984,7 @@ pub const Value = extern union {
29822984 .int_i64,
29832985 .int_big_positive,
29842986 .int_big_negative,
2985 => compareWithZero(self, .eq),
2987 => compareAllWithZero(self, .eq),
29862988
29872989 .undef => unreachable,
29882990 .unreachable_value => unreachable,