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(...@@ -35,8 +35,8 @@ pub fn add(
35 src: SwitchProngSrc,35 src: SwitchProngSrc,
36) !?SwitchProngSrc {36) !?SwitchProngSrc {
37 for (self.ranges.items) |range| {37 for (self.ranges.items) |range| {
38 if (last.compare(.gte, range.first, ty, self.module) and38 if (last.compareAll(.gte, range.first, ty, self.module) and
39 first.compare(.lte, range.last, ty, self.module))39 first.compareAll(.lte, range.last, ty, self.module))
40 {40 {
41 return range.src; // They overlap.41 return range.src; // They overlap.
42 }42 }
...@@ -53,7 +53,7 @@ const LessThanContext = struct { ty: Type, module: *Module };...@@ -53,7 +53,7 @@ const LessThanContext = struct { ty: Type, module: *Module };
5353
54/// Assumes a and b do not overlap54/// Assumes a and b do not overlap
55fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {55fn 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);
57}57}
5858
59pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {59pub 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...@@ -10333,8 +10333,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10333 // Validation above ensured these will succeed.10333 // Validation above ensured these will succeed.
10334 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;10334 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;
10335 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable;10335 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)) and10336 if ((try sema.compareAll(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)))10337 (try sema.compareAll(block, src, operand_val, .lte, last_tv.val, operand_ty)))
10338 {10338 {
10339 if (is_inline) child_block.inline_case_capture = operand;10339 if (is_inline) child_block.inline_case_capture = operand;
10340 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);10340 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...@@ -10482,7 +10482,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10482 const item_last_ref = try sema.resolveInst(last_ref);10482 const item_last_ref = try sema.resolveInst(last_ref);
10483 const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable;10483 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)) : ({
10486 // Previous validation has resolved any possible lazy values.10486 // Previous validation has resolved any possible lazy values.
10487 item = try sema.intAddScalar(block, .unneeded, item, Value.one);10487 item = try sema.intAddScalar(block, .unneeded, item, Value.one);
10488 }) {10488 }) {
...@@ -10937,7 +10937,7 @@ const RangeSetUnhandledIterator = struct {...@@ -10937,7 +10937,7 @@ const RangeSetUnhandledIterator = struct {
10937 it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty);10937 it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty);
10938 }10938 }
10939 it.first = false;10939 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)) {
10941 return it.cur;10941 return it.cur;
10942 }10942 }
10943 it.cur = it.ranges[it.range_i].last;10943 it.cur = it.ranges[it.range_i].last;
...@@ -10946,7 +10946,7 @@ const RangeSetUnhandledIterator = struct {...@@ -10946,7 +10946,7 @@ const RangeSetUnhandledIterator = struct {
10946 it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty);10946 it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty);
10947 }10947 }
10948 it.first = false;10948 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)) {
10950 return it.cur;10950 return it.cur;
10951 }10951 }
10952 return null;10952 return null;
...@@ -10992,7 +10992,7 @@ fn validateSwitchRange(...@@ -10992,7 +10992,7 @@ fn validateSwitchRange(
10992) CompileError!void {10992) CompileError!void {
10993 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;10993 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
10994 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;10994 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)) {
10996 const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first);10996 const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first);
10997 return sema.fail(block, src, "range start value is greater than the end value", .{});10997 return sema.fail(block, src, "range start value is greater than the end value", .{});
10998 }10998 }
...@@ -11456,7 +11456,7 @@ fn zirShl(...@@ -11456,7 +11456,7 @@ fn zirShl(
11456 return sema.addConstUndef(sema.typeOf(lhs));11456 return sema.addConstUndef(sema.typeOf(lhs));
11457 }11457 }
11458 // If rhs is 0, return lhs without doing any calculations.11458 // 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))) {
11460 return lhs;11460 return lhs;
11461 }11461 }
11462 if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) {11462 if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) {
...@@ -11500,7 +11500,7 @@ fn zirShl(...@@ -11500,7 +11500,7 @@ fn zirShl(
11500 if (scalar_ty.zigTypeTag() == .ComptimeInt) {11500 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
11501 break :val shifted.wrapped_result;11501 break :val shifted.wrapped_result;
11502 }11502 }
11503 if (shifted.overflowed.compareWithZero(.eq)) {11503 if (shifted.overflowed.compareAllWithZero(.eq)) {
11504 break :val shifted.wrapped_result;11504 break :val shifted.wrapped_result;
11505 }11505 }
11506 return sema.fail(block, src, "operation caused overflow", .{});11506 return sema.fail(block, src, "operation caused overflow", .{});
...@@ -11625,7 +11625,7 @@ fn zirShr(...@@ -11625,7 +11625,7 @@ fn zirShr(
11625 return sema.addConstUndef(lhs_ty);11625 return sema.addConstUndef(lhs_ty);
11626 }11626 }
11627 // If rhs is 0, return lhs without doing any calculations.11627 // 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))) {
11629 return lhs;11629 return lhs;
11630 }11630 }
11631 if (scalar_ty.zigTypeTag() != .ComptimeInt) {11631 if (scalar_ty.zigTypeTag() != .ComptimeInt) {
...@@ -11659,7 +11659,7 @@ fn zirShr(...@@ -11659,7 +11659,7 @@ fn zirShr(
11659 if (air_tag == .shr_exact) {11659 if (air_tag == .shr_exact) {
11660 // Detect if any ones would be shifted out.11660 // Detect if any ones would be shifted out.
11661 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, target);11661 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)))) {
11663 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});11663 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});
11664 }11664 }
11665 }11665 }
...@@ -12414,7 +12414,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -12414,7 +12414,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
12414 const lhs_val = maybe_lhs_val orelse unreachable;12414 const lhs_val = maybe_lhs_val orelse unreachable;
12415 const rhs_val = maybe_rhs_val orelse unreachable;12415 const rhs_val = maybe_rhs_val orelse unreachable;
12416 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target) catch unreachable;12416 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, target) catch unreachable;
12417 if (rem.compareWithZero(.neq)) {12417 if (!rem.compareAllWithZero(.eq)) {
12418 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{12418 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{
12419 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),12419 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),
12420 });12420 });
...@@ -12452,7 +12452,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -12452,7 +12452,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
12452 .Int, .ComptimeInt, .ComptimeFloat => {12452 .Int, .ComptimeInt, .ComptimeFloat => {
12453 if (maybe_lhs_val) |lhs_val| {12453 if (maybe_lhs_val) |lhs_val| {
12454 if (!lhs_val.isUndef()) {12454 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))) {
12456 const zero_val = if (is_vector) b: {12456 const zero_val = if (is_vector) b: {
12457 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);12457 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
12458 } else Value.zero;12458 } else Value.zero;
...@@ -12464,7 +12464,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -12464,7 +12464,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
12464 if (rhs_val.isUndef()) {12464 if (rhs_val.isUndef()) {
12465 return sema.failWithUseOfUndef(block, rhs_src);12465 return sema.failWithUseOfUndef(block, rhs_src);
12466 }12466 }
12467 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {12467 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
12468 return sema.failWithDivideByZero(block, rhs_src);12468 return sema.failWithDivideByZero(block, rhs_src);
12469 }12469 }
12470 // TODO: if the RHS is one, return the LHS directly12470 // 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...@@ -12478,7 +12478,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
12478 if (lhs_val.isUndef()) {12478 if (lhs_val.isUndef()) {
12479 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {12479 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
12480 if (maybe_rhs_val) |rhs_val| {12480 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)) {
12482 return sema.addConstUndef(resolved_type);12482 return sema.addConstUndef(resolved_type);
12483 }12483 }
12484 }12484 }
...@@ -12587,7 +12587,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12587,7 +12587,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12587 if (lhs_val.isUndef()) {12587 if (lhs_val.isUndef()) {
12588 return sema.failWithUseOfUndef(block, rhs_src);12588 return sema.failWithUseOfUndef(block, rhs_src);
12589 } else {12589 } else {
12590 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {12590 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
12591 const zero_val = if (is_vector) b: {12591 const zero_val = if (is_vector) b: {
12592 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);12592 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
12593 } else Value.zero;12593 } else Value.zero;
...@@ -12599,7 +12599,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12599,7 +12599,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12599 if (rhs_val.isUndef()) {12599 if (rhs_val.isUndef()) {
12600 return sema.failWithUseOfUndef(block, rhs_src);12600 return sema.failWithUseOfUndef(block, rhs_src);
12601 }12601 }
12602 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {12602 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
12603 return sema.failWithDivideByZero(block, rhs_src);12603 return sema.failWithDivideByZero(block, rhs_src);
12604 }12604 }
12605 // TODO: if the RHS is one, return the LHS directly12605 // 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...@@ -12608,7 +12608,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12608 if (maybe_rhs_val) |rhs_val| {12608 if (maybe_rhs_val) |rhs_val| {
12609 if (is_int) {12609 if (is_int) {
12610 const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, target);12610 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))) {
12612 return sema.fail(block, src, "exact division produced remainder", .{});12612 return sema.fail(block, src, "exact division produced remainder", .{});
12613 }12613 }
12614 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target);12614 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...@@ -12619,7 +12619,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12619 return sema.addConstant(resolved_type, res);12619 return sema.addConstant(resolved_type, res);
12620 } else {12620 } else {
12621 const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target);12621 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))) {
12623 return sema.fail(block, src, "exact division produced remainder", .{});12623 return sema.fail(block, src, "exact division produced remainder", .{});
12624 }12624 }
12625 return sema.addConstant(12625 return sema.addConstant(
...@@ -12753,7 +12753,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12753,7 +12753,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12753 // If the lhs is undefined, result is undefined.12753 // If the lhs is undefined, result is undefined.
12754 if (maybe_lhs_val) |lhs_val| {12754 if (maybe_lhs_val) |lhs_val| {
12755 if (!lhs_val.isUndef()) {12755 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))) {
12757 const zero_val = if (is_vector) b: {12757 const zero_val = if (is_vector) b: {
12758 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);12758 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
12759 } else Value.zero;12759 } else Value.zero;
...@@ -12765,7 +12765,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12765,7 +12765,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12765 if (rhs_val.isUndef()) {12765 if (rhs_val.isUndef()) {
12766 return sema.failWithUseOfUndef(block, rhs_src);12766 return sema.failWithUseOfUndef(block, rhs_src);
12767 }12767 }
12768 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {12768 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
12769 return sema.failWithDivideByZero(block, rhs_src);12769 return sema.failWithDivideByZero(block, rhs_src);
12770 }12770 }
12771 // TODO: if the RHS is one, return the LHS directly12771 // 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...@@ -12774,7 +12774,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12774 if (lhs_val.isUndef()) {12774 if (lhs_val.isUndef()) {
12775 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {12775 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
12776 if (maybe_rhs_val) |rhs_val| {12776 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)) {
12778 return sema.addConstUndef(resolved_type);12778 return sema.addConstUndef(resolved_type);
12779 }12779 }
12780 }12780 }
...@@ -12870,7 +12870,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12870,7 +12870,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12870 // If the lhs is undefined, result is undefined.12870 // If the lhs is undefined, result is undefined.
12871 if (maybe_lhs_val) |lhs_val| {12871 if (maybe_lhs_val) |lhs_val| {
12872 if (!lhs_val.isUndef()) {12872 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))) {
12874 const zero_val = if (is_vector) b: {12874 const zero_val = if (is_vector) b: {
12875 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);12875 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
12876 } else Value.zero;12876 } else Value.zero;
...@@ -12882,7 +12882,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12882,7 +12882,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12882 if (rhs_val.isUndef()) {12882 if (rhs_val.isUndef()) {
12883 return sema.failWithUseOfUndef(block, rhs_src);12883 return sema.failWithUseOfUndef(block, rhs_src);
12884 }12884 }
12885 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {12885 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
12886 return sema.failWithDivideByZero(block, rhs_src);12886 return sema.failWithDivideByZero(block, rhs_src);
12887 }12887 }
12888 }12888 }
...@@ -12890,7 +12890,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12890,7 +12890,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12890 if (lhs_val.isUndef()) {12890 if (lhs_val.isUndef()) {
12891 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {12891 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
12892 if (maybe_rhs_val) |rhs_val| {12892 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)) {
12894 return sema.addConstUndef(resolved_type);12894 return sema.addConstUndef(resolved_type);
12895 }12895 }
12896 }12896 }
...@@ -12961,12 +12961,12 @@ fn addDivIntOverflowSafety(...@@ -12961,12 +12961,12 @@ fn addDivIntOverflowSafety(
12961 // If the LHS is comptime-known to be not equal to the min int,12961 // If the LHS is comptime-known to be not equal to the min int,
12962 // no overflow is possible.12962 // no overflow is possible.
12963 if (maybe_lhs_val) |lhs_val| {12963 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;
12965 }12965 }
1296612966
12967 // If the RHS is comptime-known to not be equal to -1, no overflow is possible.12967 // If the RHS is comptime-known to not be equal to -1, no overflow is possible.
12968 if (maybe_rhs_val) |rhs_val| {12968 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;
12970 }12970 }
1297112971
12972 var ok: Air.Inst.Ref = .none;12972 var ok: Air.Inst.Ref = .none;
...@@ -13111,7 +13111,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13111,7 +13111,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13111 if (lhs_val.isUndef()) {13111 if (lhs_val.isUndef()) {
13112 return sema.failWithUseOfUndef(block, lhs_src);13112 return sema.failWithUseOfUndef(block, lhs_src);
13113 }13113 }
13114 if (try lhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13114 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13115 const zero_val = if (is_vector) b: {13115 const zero_val = if (is_vector) b: {
13116 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13116 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13117 } else Value.zero;13117 } else Value.zero;
...@@ -13124,17 +13124,18 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13124,17 +13124,18 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13124 if (rhs_val.isUndef()) {13124 if (rhs_val.isUndef()) {
13125 return sema.failWithUseOfUndef(block, rhs_src);13125 return sema.failWithUseOfUndef(block, rhs_src);
13126 }13126 }
13127 switch (try rhs_val.orderAgainstZeroAdvanced(sema.kit(block, src))) {13127 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
13128 .lt => return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty),13128 return sema.failWithDivideByZero(block, rhs_src);
13129 .eq => return sema.failWithDivideByZero(block, rhs_src),13129 }
13130 .gt => {},13130 if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) {
13131 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
13131 }13132 }
13132 if (maybe_lhs_val) |lhs_val| {13133 if (maybe_lhs_val) |lhs_val| {
13133 const rem_result = try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src);13134 const rem_result = try sema.intRem(block, resolved_type, lhs_val, lhs_src, rhs_val, rhs_src);
13134 // If this answer could possibly be different by doing `intMod`,13135 // If this answer could possibly be different by doing `intMod`,
13135 // we must emit a compile error. Otherwise, it's OK.13136 // we must emit a compile error. Otherwise, it's OK.
13136 if ((try lhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) and13137 if (!(try lhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src))) and
13137 !(try rem_result.compareWithZeroAdvanced(.eq, sema.kit(block, src))))13138 !(try rem_result.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))))
13138 {13139 {
13139 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);13140 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
13140 }13141 }
...@@ -13152,14 +13153,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13152,14 +13153,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13152 if (rhs_val.isUndef()) {13153 if (rhs_val.isUndef()) {
13153 return sema.failWithUseOfUndef(block, rhs_src);13154 return sema.failWithUseOfUndef(block, rhs_src);
13154 }13155 }
13155 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13156 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
13156 return sema.failWithDivideByZero(block, rhs_src);13157 return sema.failWithDivideByZero(block, rhs_src);
13157 }13158 }
13158 if (try rhs_val.compareWithZeroAdvanced(.lt, sema.kit(block, src))) {13159 if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema.kit(block, src)))) {
13159 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);13160 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
13160 }13161 }
13161 if (maybe_lhs_val) |lhs_val| {13162 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)))) {
13163 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);13164 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
13164 }13165 }
13165 return sema.addConstant(13166 return sema.addConstant(
...@@ -13295,7 +13296,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13295,7 +13296,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13295 if (rhs_val.isUndef()) {13296 if (rhs_val.isUndef()) {
13296 return sema.failWithUseOfUndef(block, rhs_src);13297 return sema.failWithUseOfUndef(block, rhs_src);
13297 }13298 }
13298 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13299 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
13299 return sema.failWithDivideByZero(block, rhs_src);13300 return sema.failWithDivideByZero(block, rhs_src);
13300 }13301 }
13301 if (maybe_lhs_val) |lhs_val| {13302 if (maybe_lhs_val) |lhs_val| {
...@@ -13314,7 +13315,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13314,7 +13315,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13314 if (rhs_val.isUndef()) {13315 if (rhs_val.isUndef()) {
13315 return sema.failWithUseOfUndef(block, rhs_src);13316 return sema.failWithUseOfUndef(block, rhs_src);
13316 }13317 }
13317 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13318 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
13318 return sema.failWithDivideByZero(block, rhs_src);13319 return sema.failWithDivideByZero(block, rhs_src);
13319 }13320 }
13320 }13321 }
...@@ -13398,7 +13399,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13398,7 +13399,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13398 if (rhs_val.isUndef()) {13399 if (rhs_val.isUndef()) {
13399 return sema.failWithUseOfUndef(block, rhs_src);13400 return sema.failWithUseOfUndef(block, rhs_src);
13400 }13401 }
13401 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13402 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
13402 return sema.failWithDivideByZero(block, rhs_src);13403 return sema.failWithDivideByZero(block, rhs_src);
13403 }13404 }
13404 if (maybe_lhs_val) |lhs_val| {13405 if (maybe_lhs_val) |lhs_val| {
...@@ -13417,7 +13418,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13417,7 +13418,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13417 if (rhs_val.isUndef()) {13418 if (rhs_val.isUndef()) {
13418 return sema.failWithUseOfUndef(block, rhs_src);13419 return sema.failWithUseOfUndef(block, rhs_src);
13419 }13420 }
13420 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13421 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema.kit(block, src)))) {
13421 return sema.failWithDivideByZero(block, rhs_src);13422 return sema.failWithDivideByZero(block, rhs_src);
13422 }13423 }
13423 }13424 }
...@@ -13496,12 +13497,12 @@ fn zirOverflowArithmetic(...@@ -13496,12 +13497,12 @@ fn zirOverflowArithmetic(
13496 // to the result, even if it is undefined..13497 // to the result, even if it is undefined..
13497 // Otherwise, if either of the argument is undefined, undefined is returned.13498 // Otherwise, if either of the argument is undefined, undefined is returned.
13498 if (maybe_lhs_val) |lhs_val| {13499 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)))) {
13500 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };13501 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
13501 }13502 }
13502 }13503 }
13503 if (maybe_rhs_val) |rhs_val| {13504 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)))) {
13505 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };13506 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
13506 }13507 }
13507 }13508 }
...@@ -13524,7 +13525,7 @@ fn zirOverflowArithmetic(...@@ -13524,7 +13525,7 @@ fn zirOverflowArithmetic(
13524 if (maybe_rhs_val) |rhs_val| {13525 if (maybe_rhs_val) |rhs_val| {
13525 if (rhs_val.isUndef()) {13526 if (rhs_val.isUndef()) {
13526 break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };13527 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))) {
13528 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };13529 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
13529 } else if (maybe_lhs_val) |lhs_val| {13530 } else if (maybe_lhs_val) |lhs_val| {
13530 if (lhs_val.isUndef()) {13531 if (lhs_val.isUndef()) {
...@@ -13544,9 +13545,9 @@ fn zirOverflowArithmetic(...@@ -13544,9 +13545,9 @@ fn zirOverflowArithmetic(
13544 // Otherwise, if either of the arguments is undefined, both results are undefined.13545 // Otherwise, if either of the arguments is undefined, both results are undefined.
13545 if (maybe_lhs_val) |lhs_val| {13546 if (maybe_lhs_val) |lhs_val| {
13546 if (!lhs_val.isUndef()) {13547 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))) {
13548 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };13549 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)) {
13550 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };13551 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
13551 }13552 }
13552 }13553 }
...@@ -13554,9 +13555,9 @@ fn zirOverflowArithmetic(...@@ -13554,9 +13555,9 @@ fn zirOverflowArithmetic(
1355413555
13555 if (maybe_rhs_val) |rhs_val| {13556 if (maybe_rhs_val) |rhs_val| {
13556 if (!rhs_val.isUndef()) {13557 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))) {
13558 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };13559 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)) {
13560 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };13561 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
13561 }13562 }
13562 }13563 }
...@@ -13580,12 +13581,12 @@ fn zirOverflowArithmetic(...@@ -13580,12 +13581,12 @@ fn zirOverflowArithmetic(
13580 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.13581 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
13581 // Oterhwise if either of the arguments is undefined, both results are undefined.13582 // Oterhwise if either of the arguments is undefined, both results are undefined.
13582 if (maybe_lhs_val) |lhs_val| {13583 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)))) {
13584 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };13585 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
13585 }13586 }
13586 }13587 }
13587 if (maybe_rhs_val) |rhs_val| {13588 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)))) {
13589 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };13590 break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
13590 }13591 }
13591 }13592 }
...@@ -13728,7 +13729,7 @@ fn analyzeArithmetic(...@@ -13728,7 +13729,7 @@ fn analyzeArithmetic(
13728 // overflow (max_int), causing illegal behavior.13729 // overflow (max_int), causing illegal behavior.
13729 // For floats: either operand being undef makes the result undef.13730 // For floats: either operand being undef makes the result undef.
13730 if (maybe_lhs_val) |lhs_val| {13731 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)))) {
13732 return casted_rhs;13733 return casted_rhs;
13733 }13734 }
13734 }13735 }
...@@ -13740,7 +13741,7 @@ fn analyzeArithmetic(...@@ -13740,7 +13741,7 @@ fn analyzeArithmetic(
13740 return sema.addConstUndef(resolved_type);13741 return sema.addConstUndef(resolved_type);
13741 }13742 }
13742 }13743 }
13743 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13744 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13744 return casted_lhs;13745 return casted_lhs;
13745 }13746 }
13746 }13747 }
...@@ -13775,7 +13776,7 @@ fn analyzeArithmetic(...@@ -13775,7 +13776,7 @@ fn analyzeArithmetic(
13775 // If either of the operands are zero, the other operand is returned.13776 // If either of the operands are zero, the other operand is returned.
13776 // If either of the operands are undefined, the result is undefined.13777 // If either of the operands are undefined, the result is undefined.
13777 if (maybe_lhs_val) |lhs_val| {13778 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)))) {
13779 return casted_rhs;13780 return casted_rhs;
13780 }13781 }
13781 }13782 }
...@@ -13784,7 +13785,7 @@ fn analyzeArithmetic(...@@ -13784,7 +13785,7 @@ fn analyzeArithmetic(
13784 if (rhs_val.isUndef()) {13785 if (rhs_val.isUndef()) {
13785 return sema.addConstUndef(resolved_type);13786 return sema.addConstUndef(resolved_type);
13786 }13787 }
13787 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13788 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13788 return casted_lhs;13789 return casted_lhs;
13789 }13790 }
13790 if (maybe_lhs_val) |lhs_val| {13791 if (maybe_lhs_val) |lhs_val| {
...@@ -13800,7 +13801,7 @@ fn analyzeArithmetic(...@@ -13800,7 +13801,7 @@ fn analyzeArithmetic(
13800 // If either of the operands are zero, then the other operand is returned.13801 // If either of the operands are zero, then the other operand is returned.
13801 // If either of the operands are undefined, the result is undefined.13802 // If either of the operands are undefined, the result is undefined.
13802 if (maybe_lhs_val) |lhs_val| {13803 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)))) {
13804 return casted_rhs;13805 return casted_rhs;
13805 }13806 }
13806 }13807 }
...@@ -13808,7 +13809,7 @@ fn analyzeArithmetic(...@@ -13808,7 +13809,7 @@ fn analyzeArithmetic(
13808 if (rhs_val.isUndef()) {13809 if (rhs_val.isUndef()) {
13809 return sema.addConstUndef(resolved_type);13810 return sema.addConstUndef(resolved_type);
13810 }13811 }
13811 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13812 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13812 return casted_lhs;13813 return casted_lhs;
13813 }13814 }
13814 if (maybe_lhs_val) |lhs_val| {13815 if (maybe_lhs_val) |lhs_val| {
...@@ -13837,7 +13838,7 @@ fn analyzeArithmetic(...@@ -13837,7 +13838,7 @@ fn analyzeArithmetic(
13837 return sema.addConstUndef(resolved_type);13838 return sema.addConstUndef(resolved_type);
13838 }13839 }
13839 }13840 }
13840 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13841 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13841 return casted_lhs;13842 return casted_lhs;
13842 }13843 }
13843 }13844 }
...@@ -13875,7 +13876,7 @@ fn analyzeArithmetic(...@@ -13875,7 +13876,7 @@ fn analyzeArithmetic(
13875 if (rhs_val.isUndef()) {13876 if (rhs_val.isUndef()) {
13876 return sema.addConstUndef(resolved_type);13877 return sema.addConstUndef(resolved_type);
13877 }13878 }
13878 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13879 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13879 return casted_lhs;13880 return casted_lhs;
13880 }13881 }
13881 }13882 }
...@@ -13900,7 +13901,7 @@ fn analyzeArithmetic(...@@ -13900,7 +13901,7 @@ fn analyzeArithmetic(
13900 if (rhs_val.isUndef()) {13901 if (rhs_val.isUndef()) {
13901 return sema.addConstUndef(resolved_type);13902 return sema.addConstUndef(resolved_type);
13902 }13903 }
13903 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13904 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13904 return casted_lhs;13905 return casted_lhs;
13905 }13906 }
13906 }13907 }
...@@ -13929,13 +13930,13 @@ fn analyzeArithmetic(...@@ -13929,13 +13930,13 @@ fn analyzeArithmetic(
13929 // For floats: either operand being undef makes the result undef.13930 // For floats: either operand being undef makes the result undef.
13930 if (maybe_lhs_val) |lhs_val| {13931 if (maybe_lhs_val) |lhs_val| {
13931 if (!lhs_val.isUndef()) {13932 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))) {
13933 const zero_val = if (is_vector) b: {13934 const zero_val = if (is_vector) b: {
13934 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13935 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13935 } else Value.zero;13936 } else Value.zero;
13936 return sema.addConstant(resolved_type, zero_val);13937 return sema.addConstant(resolved_type, zero_val);
13937 }13938 }
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)) {
13939 return casted_rhs;13940 return casted_rhs;
13940 }13941 }
13941 }13942 }
...@@ -13949,13 +13950,13 @@ fn analyzeArithmetic(...@@ -13949,13 +13950,13 @@ fn analyzeArithmetic(
13949 return sema.addConstUndef(resolved_type);13950 return sema.addConstUndef(resolved_type);
13950 }13951 }
13951 }13952 }
13952 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {13953 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
13953 const zero_val = if (is_vector) b: {13954 const zero_val = if (is_vector) b: {
13954 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13955 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13955 } else Value.zero;13956 } else Value.zero;
13956 return sema.addConstant(resolved_type, zero_val);13957 return sema.addConstant(resolved_type, zero_val);
13957 }13958 }
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)) {
13959 return casted_lhs;13960 return casted_lhs;
13960 }13961 }
13961 if (maybe_lhs_val) |lhs_val| {13962 if (maybe_lhs_val) |lhs_val| {
...@@ -13989,13 +13990,13 @@ fn analyzeArithmetic(...@@ -13989,13 +13990,13 @@ fn analyzeArithmetic(
13989 // If either of the operands are undefined, result is undefined.13990 // If either of the operands are undefined, result is undefined.
13990 if (maybe_lhs_val) |lhs_val| {13991 if (maybe_lhs_val) |lhs_val| {
13991 if (!lhs_val.isUndef()) {13992 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))) {
13993 const zero_val = if (is_vector) b: {13994 const zero_val = if (is_vector) b: {
13994 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);13995 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13995 } else Value.zero;13996 } else Value.zero;
13996 return sema.addConstant(resolved_type, zero_val);13997 return sema.addConstant(resolved_type, zero_val);
13997 }13998 }
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)) {
13999 return casted_rhs;14000 return casted_rhs;
14000 }14001 }
14001 }14002 }
...@@ -14005,13 +14006,13 @@ fn analyzeArithmetic(...@@ -14005,13 +14006,13 @@ fn analyzeArithmetic(
14005 if (rhs_val.isUndef()) {14006 if (rhs_val.isUndef()) {
14006 return sema.addConstUndef(resolved_type);14007 return sema.addConstUndef(resolved_type);
14007 }14008 }
14008 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {14009 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
14009 const zero_val = if (is_vector) b: {14010 const zero_val = if (is_vector) b: {
14010 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);14011 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14011 } else Value.zero;14012 } else Value.zero;
14012 return sema.addConstant(resolved_type, zero_val);14013 return sema.addConstant(resolved_type, zero_val);
14013 }14014 }
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)) {
14015 return casted_lhs;14016 return casted_lhs;
14016 }14017 }
14017 if (maybe_lhs_val) |lhs_val| {14018 if (maybe_lhs_val) |lhs_val| {
...@@ -14032,13 +14033,13 @@ fn analyzeArithmetic(...@@ -14032,13 +14033,13 @@ fn analyzeArithmetic(
14032 // If either of the operands are undefined, result is undefined.14033 // If either of the operands are undefined, result is undefined.
14033 if (maybe_lhs_val) |lhs_val| {14034 if (maybe_lhs_val) |lhs_val| {
14034 if (!lhs_val.isUndef()) {14035 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))) {
14036 const zero_val = if (is_vector) b: {14037 const zero_val = if (is_vector) b: {
14037 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);14038 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14038 } else Value.zero;14039 } else Value.zero;
14039 return sema.addConstant(resolved_type, zero_val);14040 return sema.addConstant(resolved_type, zero_val);
14040 }14041 }
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)) {
14042 return casted_rhs;14043 return casted_rhs;
14043 }14044 }
14044 }14045 }
...@@ -14047,13 +14048,13 @@ fn analyzeArithmetic(...@@ -14047,13 +14048,13 @@ fn analyzeArithmetic(
14047 if (rhs_val.isUndef()) {14048 if (rhs_val.isUndef()) {
14048 return sema.addConstUndef(resolved_type);14049 return sema.addConstUndef(resolved_type);
14049 }14050 }
14050 if (try rhs_val.compareWithZeroAdvanced(.eq, sema.kit(block, src))) {14051 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema.kit(block, src))) {
14051 const zero_val = if (is_vector) b: {14052 const zero_val = if (is_vector) b: {
14052 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);14053 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14053 } else Value.zero;14054 } else Value.zero;
14054 return sema.addConstant(resolved_type, zero_val);14055 return sema.addConstant(resolved_type, zero_val);
14055 }14056 }
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)) {
14057 return casted_lhs;14058 return casted_lhs;
14058 }14059 }
14059 if (maybe_lhs_val) |lhs_val| {14060 if (maybe_lhs_val) |lhs_val| {
...@@ -14605,7 +14606,7 @@ fn cmpSelf(...@@ -14605,7 +14606,7 @@ fn cmpSelf(
14605 return sema.addConstant(result_ty, cmp_val);14606 return sema.addConstant(result_ty, cmp_val);
14606 }14607 }
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)) {
14609 return Air.Inst.Ref.bool_true;14610 return Air.Inst.Ref.bool_true;
14610 } else {14611 } else {
14611 return Air.Inst.Ref.bool_false;14612 return Air.Inst.Ref.bool_false;
...@@ -27811,7 +27812,7 @@ fn analyzeSlice(...@@ -27811,7 +27812,7 @@ fn analyzeSlice(
27811 sema.arena,27812 sema.arena,
27812 array_ty.arrayLenIncludingSentinel(),27813 array_ty.arrayLenIncludingSentinel(),
27813 );27814 );
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))) {
27815 const sentinel_label: []const u8 = if (array_ty.sentinel() != null)27816 const sentinel_label: []const u8 = if (array_ty.sentinel() != null)
27816 " +1 (sentinel)"27817 " +1 (sentinel)"
27817 else27818 else
...@@ -27854,7 +27855,7 @@ fn analyzeSlice(...@@ -27854,7 +27855,7 @@ fn analyzeSlice(
27854 .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel),27855 .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel),
27855 };27856 };
27856 const slice_len_val = Value.initPayload(&int_payload.base);27857 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))) {
27858 const sentinel_label: []const u8 = if (has_sentinel)27859 const sentinel_label: []const u8 = if (has_sentinel)
27859 " +1 (sentinel)"27860 " +1 (sentinel)"
27860 else27861 else
...@@ -27913,7 +27914,7 @@ fn analyzeSlice(...@@ -27913,7 +27914,7 @@ fn analyzeSlice(
27913 // requirement: start <= end27914 // requirement: start <= end
27914 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {27915 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
27915 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {27916 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))) {
27917 return sema.fail(27918 return sema.fail(
27918 block,27919 block,
27919 start_src,27920 start_src,
...@@ -28202,11 +28203,11 @@ fn cmpNumeric(...@@ -28202,11 +28203,11 @@ fn cmpNumeric(
28202 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,28203 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,
28203 // add/subtract 1.28204 // add/subtract 1.
28204 const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val|28205 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)))
28206 else28207 else
28207 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt());28208 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt());
28208 const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val|28209 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)))
28210 else28211 else
28211 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt());28212 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt());
28212 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;28213 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
...@@ -31933,13 +31934,13 @@ fn intInRange(...@@ -31933,13 +31934,13 @@ fn intInRange(
31933 int_val: Value,31934 int_val: Value,
31934 end: usize,31935 end: usize,
31935) !bool {31936) !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;
31937 var end_payload: Value.Payload.U64 = .{31938 var end_payload: Value.Payload.U64 = .{
31938 .base = .{ .tag = .int_u64 },31939 .base = .{ .tag = .int_u64 },
31939 .data = end,31940 .data = end,
31940 };31941 };
31941 const end_val = Value.initPayload(&end_payload.base);31942 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;
31943 return true;31944 return true;
31944}31945}
3194531946
...@@ -32057,8 +32058,10 @@ fn intAddWithOverflowScalar(...@@ -32057,8 +32058,10 @@ fn intAddWithOverflowScalar(
32057}32058}
3205832059
32059/// Asserts the values are comparable. Both operands have type `ty`.32060/// Asserts the values are comparable. Both operands have type `ty`.
32060/// Vector results will be reduced with AND.32061/// For vectors, returns true if the comparison is true for ALL elements.
32061fn compare(32062///
32063/// Note that `!compareAll(.eq, ...) != compareAll(.neq, ...)`
32064fn compareAll(
32062 sema: *Sema,32065 sema: *Sema,
32063 block: *Block,32066 block: *Block,
32064 src: LazySrcLoc,32067 src: LazySrcLoc,
src/type.zig+4-4
...@@ -5463,13 +5463,13 @@ pub const Type = extern union {...@@ -5463,13 +5463,13 @@ pub const Type = extern union {
5463 }5463 }
5464 const S = struct {5464 const S = struct {
5465 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {5465 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;
5467 var end_payload: Value.Payload.U64 = .{5467 var end_payload: Value.Payload.U64 = .{
5468 .base = .{ .tag = .int_u64 },5468 .base = .{ .tag = .int_u64 },
5469 .data = end,5469 .data = end,
5470 };5470 };
5471 const end_val = Value.initPayload(&end_payload.base);5471 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;
5473 return @intCast(usize, int_val.toUnsignedInt(m.getTarget()));5473 return @intCast(usize, int_val.toUnsignedInt(m.getTarget()));
5474 }5474 }
5475 };5475 };
...@@ -6455,12 +6455,12 @@ pub const Type = extern union {...@@ -6455,12 +6455,12 @@ pub const Type = extern union {
6455 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {6455 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
6456 switch (d.size) {6456 switch (d.size) {
6457 .Slice => {6457 .Slice => {
6458 if (sent.compareWithZero(.eq)) {6458 if (sent.compareAllWithZero(.eq)) {
6459 return Type.initTag(.const_slice_u8_sentinel_0);6459 return Type.initTag(.const_slice_u8_sentinel_0);
6460 }6460 }
6461 },6461 },
6462 .Many => {6462 .Many => {
6463 if (sent.compareWithZero(.eq)) {6463 if (sent.compareAllWithZero(.eq)) {
6464 return Type.initTag(.manyptr_const_u8_sentinel_0);6464 return Type.initTag(.manyptr_const_u8_sentinel_0);
6465 }6465 }
6466 },6466 },
src/value.zig+11-9
...@@ -2005,8 +2005,8 @@ pub const Value = extern union {...@@ -2005,8 +2005,8 @@ pub const Value = extern union {
2005 }2005 }
20062006
2007 /// Asserts the values are comparable. Both operands have type `ty`.2007 /// Asserts the values are comparable. Both operands have type `ty`.
2008 /// Vector results will be reduced with AND.2008 /// For vectors, returns true if comparison is true for ALL elements.
2009 pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool {2009 pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool {
2010 if (ty.zigTypeTag() == .Vector) {2010 if (ty.zigTypeTag() == .Vector) {
2011 var i: usize = 0;2011 var i: usize = 0;
2012 while (i < ty.vectorLen()) : (i += 1) {2012 while (i < ty.vectorLen()) : (i += 1) {
...@@ -2035,21 +2035,23 @@ pub const Value = extern union {...@@ -2035,21 +2035,23 @@ pub const Value = extern union {
2035 }2035 }
20362036
2037 /// Asserts the value is comparable.2037 /// Asserts the value is comparable.
2038 /// Vector results will be reduced with AND.2038 /// For vectors, returns true if comparison is true for ALL elements.
2039 pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {2039 ///
2040 return compareWithZeroAdvanced(lhs, op, null) catch unreachable;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;
2041 }2043 }
20422044
2043 pub fn compareWithZeroAdvanced(2045 pub fn compareAllWithZeroAdvanced(
2044 lhs: Value,2046 lhs: Value,
2045 op: std.math.CompareOperator,2047 op: std.math.CompareOperator,
2046 sema_kit: ?Module.WipAnalysis,2048 sema_kit: ?Module.WipAnalysis,
2047 ) Module.CompileError!bool {2049 ) Module.CompileError!bool {
2048 switch (lhs.tag()) {2050 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),
2050 .aggregate => {2052 .aggregate => {
2051 for (lhs.castTag(.aggregate).?.data) |elem_val| {2053 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;
2053 }2055 }
2054 return true;2056 return true;
2055 },2057 },
...@@ -2982,7 +2984,7 @@ pub const Value = extern union {...@@ -2982,7 +2984,7 @@ pub const Value = extern union {
2982 .int_i64,2984 .int_i64,
2983 .int_big_positive,2985 .int_big_positive,
2984 .int_big_negative,2986 .int_big_negative,
2985 => compareWithZero(self, .eq),2987 => compareAllWithZero(self, .eq),
29862988
2987 .undef => unreachable,2989 .undef => unreachable,
2988 .unreachable_value => unreachable,2990 .unreachable_value => unreachable,