authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-05-23 16:42:34+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-05-28 15:10:22-04:00
log7c31f9d4ff56146dc21818967aab7123e0cd5dfe
tree640ea0dca179a6d3b73abf67d1d8e2c4c544937f
parent7bfdb7f26d85b8f9df8dfb39de70160d1881208b

Sema: don't emit AIR `reduce` for single-element vectors

This is equivalent to `array_elem_val`, and doing that conversion in Sema (seems reasonable since it's just a simple branch) is much easier for the self-hosted x86_64 backend then actually handling this case.

1 files changed, 41 insertions(+), 126 deletions(-)

src/Sema.zig+41-126
...@@ -753,6 +753,29 @@ pub const Block = struct {...@@ -753,6 +753,29 @@ pub const Block = struct {
753 });753 });
754 }754 }
755755
756 fn addReduce(block: *Block, operand: Air.Inst.Ref, operation: std.builtin.ReduceOp) !Air.Inst.Ref {
757 const sema = block.sema;
758 const zcu = sema.pt.zcu;
759 const vector_ty = sema.typeOf(operand);
760 switch (vector_ty.vectorLen(zcu)) {
761 0 => unreachable,
762 1 => return block.addBinOp(.array_elem_val, operand, .zero_usize),
763 else => {},
764 }
765 const allow_optimized = switch (vector_ty.childType(zcu).zigTypeTag(zcu)) {
766 .float => true,
767 .bool, .int => false,
768 else => unreachable,
769 };
770 return block.addInst(.{
771 .tag = if (allow_optimized and block.float_mode == .optimized) .reduce_optimized else .reduce,
772 .data = .{ .reduce = .{
773 .operand = operand,
774 .operation = operation,
775 } },
776 });
777 }
778
756 fn addAggregateInit(779 fn addAggregateInit(
757 block: *Block,780 block: *Block,
758 aggregate_ty: Type,781 aggregate_ty: Type,
...@@ -10307,10 +10330,7 @@ fn intCast(...@@ -10307,10 +10330,7 @@ fn intCast(
10307 const zeros = try sema.splat(operand_ty, try pt.intValue(operand_scalar_ty, 0));10330 const zeros = try sema.splat(operand_ty, try pt.intValue(operand_scalar_ty, 0));
10308 const zero_inst = Air.internedToRef(zeros.toIntern());10331 const zero_inst = Air.internedToRef(zeros.toIntern());
10309 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);10332 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
10310 const all_in_range = try block.addInst(.{10333 const all_in_range = try block.addReduce(is_in_range, .And);
10311 .tag = .reduce,
10312 .data = .{ .reduce = .{ .operand = is_in_range, .operation = .And } },
10313 });
10314 break :ok all_in_range;10334 break :ok all_in_range;
10315 } else ok: {10335 } else ok: {
10316 const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());10336 const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());
...@@ -10374,13 +10394,7 @@ fn intCast(...@@ -10374,13 +10394,7 @@ fn intCast(
1037410394
10375 const ok = if (is_vector) ok: {10395 const ok = if (is_vector) ok: {
10376 const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte);10396 const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte);
10377 const all_in_range = try block.addInst(.{10397 const all_in_range = try block.addReduce(is_in_range, .And);
10378 .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
10379 .data = .{ .reduce = .{
10380 .operand = is_in_range,
10381 .operation = .And,
10382 } },
10383 });
10384 break :ok all_in_range;10398 break :ok all_in_range;
10385 } else ok: {10399 } else ok: {
10386 const is_in_range = try block.addBinOp(.cmp_lte, diff_unsigned, dest_range);10400 const is_in_range = try block.addBinOp(.cmp_lte, diff_unsigned, dest_range);
...@@ -10391,13 +10405,7 @@ fn intCast(...@@ -10391,13 +10405,7 @@ fn intCast(
10391 } else {10405 } else {
10392 const ok = if (is_vector) ok: {10406 const ok = if (is_vector) ok: {
10393 const is_in_range = try block.addCmpVector(operand, dest_max, .lte);10407 const is_in_range = try block.addCmpVector(operand, dest_max, .lte);
10394 const all_in_range = try block.addInst(.{10408 const all_in_range = try block.addReduce(is_in_range, .And);
10395 .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
10396 .data = .{ .reduce = .{
10397 .operand = is_in_range,
10398 .operation = .And,
10399 } },
10400 });
10401 break :ok all_in_range;10409 break :ok all_in_range;
10402 } else ok: {10410 } else ok: {
10403 const is_in_range = try block.addBinOp(.cmp_lte, operand, dest_max);10411 const is_in_range = try block.addBinOp(.cmp_lte, operand, dest_max);
...@@ -10413,13 +10421,7 @@ fn intCast(...@@ -10413,13 +10421,7 @@ fn intCast(
10413 const zero_val = try sema.splat(operand_ty, scalar_zero);10421 const zero_val = try sema.splat(operand_ty, scalar_zero);
10414 const zero_inst = Air.internedToRef(zero_val.toIntern());10422 const zero_inst = Air.internedToRef(zero_val.toIntern());
10415 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);10423 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
10416 const all_in_range = try block.addInst(.{10424 const all_in_range = try block.addReduce(is_in_range, .And);
10417 .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
10418 .data = .{ .reduce = .{
10419 .operand = is_in_range,
10420 .operation = .And,
10421 } },
10422 });
10423 break :ok all_in_range;10425 break :ok all_in_range;
10424 } else ok: {10426 } else ok: {
10425 const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());10427 const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());
...@@ -14330,13 +14332,7 @@ fn zirShl(...@@ -14330,13 +14332,7 @@ fn zirShl(
14330 const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {14332 const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {
14331 const bit_count_inst = Air.internedToRef((try sema.splat(rhs_ty, bit_count_val)).toIntern());14333 const bit_count_inst = Air.internedToRef((try sema.splat(rhs_ty, bit_count_val)).toIntern());
14332 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);14334 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
14333 break :ok try block.addInst(.{14335 break :ok try block.addReduce(lt, .And);
14334 .tag = .reduce,
14335 .data = .{ .reduce = .{
14336 .operand = lt,
14337 .operation = .And,
14338 } },
14339 });
14340 } else ok: {14336 } else ok: {
14341 const bit_count_inst = Air.internedToRef(bit_count_val.toIntern());14337 const bit_count_inst = Air.internedToRef(bit_count_val.toIntern());
14342 break :ok try block.addBinOp(.cmp_lt, rhs, bit_count_inst);14338 break :ok try block.addBinOp(.cmp_lt, rhs, bit_count_inst);
...@@ -14358,13 +14354,7 @@ fn zirShl(...@@ -14358,13 +14354,7 @@ fn zirShl(
14358 });14354 });
14359 const ov_bit = try sema.tupleFieldValByIndex(block, op_ov, 1, op_ov_tuple_ty);14355 const ov_bit = try sema.tupleFieldValByIndex(block, op_ov, 1, op_ov_tuple_ty);
14360 const any_ov_bit = if (lhs_ty.zigTypeTag(zcu) == .vector)14356 const any_ov_bit = if (lhs_ty.zigTypeTag(zcu) == .vector)
14361 try block.addInst(.{14357 try block.addReduce(ov_bit, .Or)
14362 .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
14363 .data = .{ .reduce = .{
14364 .operand = ov_bit,
14365 .operation = .Or,
14366 } },
14367 })
14368 else14358 else
14369 ov_bit;14359 ov_bit;
14370 const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());14360 const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());
...@@ -14490,13 +14480,7 @@ fn zirShr(...@@ -14490,13 +14480,7 @@ fn zirShr(
14490 const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {14480 const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {
14491 const bit_count_inst = Air.internedToRef((try sema.splat(rhs_ty, bit_count_val)).toIntern());14481 const bit_count_inst = Air.internedToRef((try sema.splat(rhs_ty, bit_count_val)).toIntern());
14492 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);14482 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
14493 break :ok try block.addInst(.{14483 break :ok try block.addReduce(lt, .And);
14494 .tag = .reduce,
14495 .data = .{ .reduce = .{
14496 .operand = lt,
14497 .operation = .And,
14498 } },
14499 });
14500 } else ok: {14484 } else ok: {
14501 const bit_count_inst = Air.internedToRef(bit_count_val.toIntern());14485 const bit_count_inst = Air.internedToRef(bit_count_val.toIntern());
14502 break :ok try block.addBinOp(.cmp_lt, rhs, bit_count_inst);14486 break :ok try block.addBinOp(.cmp_lt, rhs, bit_count_inst);
...@@ -14509,13 +14493,7 @@ fn zirShr(...@@ -14509,13 +14493,7 @@ fn zirShr(
1450914493
14510 const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {14494 const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {
14511 const eql = try block.addCmpVector(lhs, back, .eq);14495 const eql = try block.addCmpVector(lhs, back, .eq);
14512 break :ok try block.addInst(.{14496 break :ok try block.addReduce(eql, .And);
14513 .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
14514 .data = .{ .reduce = .{
14515 .operand = eql,
14516 .operation = .And,
14517 } },
14518 });
14519 } else try block.addBinOp(.cmp_eq, lhs, back);14497 } else try block.addBinOp(.cmp_eq, lhs, back);
14520 try sema.addSafetyCheck(block, src, ok, .shr_overflow);14498 try sema.addSafetyCheck(block, src, ok, .shr_overflow);
14521 }14499 }
...@@ -15565,16 +15543,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15565,16 +15543,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1556515543
15566 if (resolved_type.zigTypeTag(zcu) == .vector) {15544 if (resolved_type.zigTypeTag(zcu) == .vector) {
15567 const eql = try block.addCmpVector(result, floored, .eq);15545 const eql = try block.addCmpVector(result, floored, .eq);
15568 break :ok try block.addInst(.{15546 break :ok try block.addReduce(eql, .And);
15569 .tag = switch (block.float_mode) {
15570 .strict => .reduce,
15571 .optimized => .reduce_optimized,
15572 },
15573 .data = .{ .reduce = .{
15574 .operand = eql,
15575 .operation = .And,
15576 } },
15577 });
15578 } else {15547 } else {
15579 const is_in_range = try block.addBinOp(switch (block.float_mode) {15548 const is_in_range = try block.addBinOp(switch (block.float_mode) {
15580 .strict => .cmp_eq,15549 .strict => .cmp_eq,
...@@ -15594,13 +15563,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15594,13 +15563,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15594 const zero_val = try sema.splat(resolved_type, scalar_zero);15563 const zero_val = try sema.splat(resolved_type, scalar_zero);
15595 const zero = Air.internedToRef(zero_val.toIntern());15564 const zero = Air.internedToRef(zero_val.toIntern());
15596 const eql = try block.addCmpVector(remainder, zero, .eq);15565 const eql = try block.addCmpVector(remainder, zero, .eq);
15597 break :ok try block.addInst(.{15566 break :ok try block.addReduce(eql, .And);
15598 .tag = .reduce,
15599 .data = .{ .reduce = .{
15600 .operand = eql,
15601 .operation = .And,
15602 } },
15603 });
15604 } else {15567 } else {
15605 const zero = Air.internedToRef(scalar_zero.toIntern());15568 const zero = Air.internedToRef(scalar_zero.toIntern());
15606 const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);15569 const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
...@@ -15829,13 +15792,7 @@ fn addDivIntOverflowSafety(...@@ -15829,13 +15792,7 @@ fn addDivIntOverflowSafety(
15829 break :ok try block.addCmpVector(casted_rhs, neg_one_ref, .neq);15792 break :ok try block.addCmpVector(casted_rhs, neg_one_ref, .neq);
15830 };15793 };
1583115794
15832 const ok = try block.addInst(.{15795 const ok = try block.addReduce(try block.addBinOp(.bool_or, lhs_ok, rhs_ok), .And);
15833 .tag = .reduce,
15834 .data = .{ .reduce = .{
15835 .operand = try block.addBinOp(.bool_or, lhs_ok, rhs_ok),
15836 .operation = .And,
15837 } },
15838 });
15839 try sema.addSafetyCheck(block, src, ok, .integer_overflow);15796 try sema.addSafetyCheck(block, src, ok, .integer_overflow);
15840 } else {15797 } else {
15841 const lhs_ok: Air.Inst.Ref = if (maybe_lhs_val == null) ok: {15798 const lhs_ok: Air.Inst.Ref = if (maybe_lhs_val == null) ok: {
...@@ -15886,13 +15843,7 @@ fn addDivByZeroSafety(...@@ -15886,13 +15843,7 @@ fn addDivByZeroSafety(
15886 const zero_val = try sema.splat(resolved_type, scalar_zero);15843 const zero_val = try sema.splat(resolved_type, scalar_zero);
15887 const zero = Air.internedToRef(zero_val.toIntern());15844 const zero = Air.internedToRef(zero_val.toIntern());
15888 const ok = try block.addCmpVector(casted_rhs, zero, .neq);15845 const ok = try block.addCmpVector(casted_rhs, zero, .neq);
15889 break :ok try block.addInst(.{15846 break :ok try block.addReduce(ok, .And);
15890 .tag = if (is_int) .reduce else .reduce_optimized,
15891 .data = .{ .reduce = .{
15892 .operand = ok,
15893 .operation = .And,
15894 } },
15895 });
15896 } else ok: {15847 } else ok: {
15897 const zero = Air.internedToRef(scalar_zero.toIntern());15848 const zero = Air.internedToRef(scalar_zero.toIntern());
15898 break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);15849 break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);
...@@ -16579,13 +16530,7 @@ fn analyzeArithmetic(...@@ -16579,13 +16530,7 @@ fn analyzeArithmetic(
16579 });16530 });
16580 const ov_bit = try sema.tupleFieldValByIndex(block, op_ov, 1, op_ov_tuple_ty);16531 const ov_bit = try sema.tupleFieldValByIndex(block, op_ov, 1, op_ov_tuple_ty);
16581 const any_ov_bit = if (resolved_type.zigTypeTag(zcu) == .vector)16532 const any_ov_bit = if (resolved_type.zigTypeTag(zcu) == .vector)
16582 try block.addInst(.{16533 try block.addReduce(ov_bit, .Or)
16583 .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
16584 .data = .{ .reduce = .{
16585 .operand = ov_bit,
16586 .operation = .Or,
16587 } },
16588 })
16589 else16534 else
16590 ov_bit;16535 ov_bit;
16591 const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());16536 const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());
...@@ -22406,13 +22351,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -22406,13 +22351,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
22406 const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt);22351 const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt);
22407 const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt);22352 const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt);
22408 const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);22353 const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);
22409 break :ok try block.addInst(.{22354 break :ok try block.addReduce(ok, .And);
22410 .tag = .reduce,
22411 .data = .{ .reduce = .{
22412 .operand = ok,
22413 .operation = .And,
22414 } },
22415 });
22416 } else ok: {22355 } else ok: {
22417 const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern()));22356 const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern()));
22418 const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern()));22357 const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern()));
...@@ -22555,13 +22494,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22555,13 +22494,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22555 const is_non_zero = if (is_vector) all_non_zero: {22494 const is_non_zero = if (is_vector) all_non_zero: {
22556 const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());22495 const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22557 const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq);22496 const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq);
22558 break :all_non_zero try block.addInst(.{22497 break :all_non_zero try block.addReduce(is_non_zero, .And);
22559 .tag = .reduce,
22560 .data = .{ .reduce = .{
22561 .operand = is_non_zero,
22562 .operation = .And,
22563 } },
22564 });
22565 } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);22498 } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
22566 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);22499 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
22567 }22500 }
...@@ -22578,13 +22511,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22578,13 +22511,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22578 const is_aligned = if (is_vector) all_aligned: {22511 const is_aligned = if (is_vector) all_aligned: {
22579 const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());22512 const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22580 const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);22513 const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);
22581 break :all_aligned try block.addInst(.{22514 break :all_aligned try block.addReduce(is_aligned, .And);
22582 .tag = .reduce,
22583 .data = .{ .reduce = .{
22584 .operand = is_aligned,
22585 .operation = .And,
22586 } },
22587 });
22588 } else try block.addBinOp(.cmp_eq, remainder, .zero_usize);22515 } else try block.addBinOp(.cmp_eq, remainder, .zero_usize);
22589 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);22516 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
22590 }22517 }
...@@ -24540,13 +24467,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -24540,13 +24467,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
24540 }24467 }
2454124468
24542 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), operand_src);24469 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), operand_src);
24543 return block.addInst(.{24470 return block.addReduce(operand, operation);
24544 .tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
24545 .data = .{ .reduce = .{
24546 .operand = operand,
24547 .operation = operation,
24548 } },
24549 });
24550}24471}
2455124472
24552fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {24473fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -27324,13 +27245,7 @@ fn addSafetyCheckSentinelMismatch(...@@ -27324,13 +27245,7 @@ fn addSafetyCheckSentinelMismatch(
2732427245
27325 const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: {27246 const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: {
27326 const eql = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);27247 const eql = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
27327 break :ok try parent_block.addInst(.{27248 break :ok try parent_block.addReduce(eql, .And);
27328 .tag = .reduce,
27329 .data = .{ .reduce = .{
27330 .operand = eql,
27331 .operation = .And,
27332 } },
27333 });
27334 } else ok: {27249 } else ok: {
27335 assert(sentinel_ty.isSelfComparable(zcu, true));27250 assert(sentinel_ty.isSelfComparable(zcu, true));
27336 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);27251 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);