authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-05-30 15:47:18-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-01 08:24:01+01:00
log32a57bfeaa9a9cd2b1a4c0e25d829824d8b96c8d
tree8f6d0ee5031c30c45b55e896d6a92e9013d529a1
parentd9b6d1ed33d18eb13fa2cb39da3e7a381742975b
signaturelock-open Commit is signed but in an unrecognized format.

Legalize: update for new Block API


2 files changed, 139 insertions(+), 174 deletions(-)

src/Air.zig+4-4
...@@ -1241,10 +1241,10 @@ pub const CondBr = struct {...@@ -1241,10 +1241,10 @@ pub const CondBr = struct {
1241 else_body_len: u32,1241 else_body_len: u32,
1242 branch_hints: BranchHints,1242 branch_hints: BranchHints,
1243 pub const BranchHints = packed struct(u32) {1243 pub const BranchHints = packed struct(u32) {
1244 true: std.builtin.BranchHint,1244 true: std.builtin.BranchHint = .none,
1245 false: std.builtin.BranchHint,1245 false: std.builtin.BranchHint = .none,
1246 then_cov: CoveragePoint,1246 then_cov: CoveragePoint = .none,
1247 else_cov: CoveragePoint,1247 else_cov: CoveragePoint = .none,
1248 _: u24 = 0,1248 _: u24 = 0,
1249 };1249 };
1250};1250};
src/Air/Legalize.zig+135-170
...@@ -575,20 +575,20 @@ inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag:...@@ -575,20 +575,20 @@ inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag:
575fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag: ScalarizeDataTag) Error!Air.Inst.Data {575fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag: ScalarizeDataTag) Error!Air.Inst.Data {
576 const pt = l.pt;576 const pt = l.pt;
577 const zcu = pt.zcu;577 const zcu = pt.zcu;
578 const gpa = zcu.gpa;
579578
580 const orig = l.air_instructions.get(@intFromEnum(orig_inst));579 const orig = l.air_instructions.get(@intFromEnum(orig_inst));
581 const res_ty = l.typeOfIndex(orig_inst);580 const res_ty = l.typeOfIndex(orig_inst);
582 const arity = switch (data_tag) {
583 .un_op, .ty_op => 1,
584 .bin_op, .ty_pl_vector_cmp => 2,
585 .pl_op_bin => 3,
586 };
587 const expected_instructions_len = l.air_instructions.len + (6 + arity + 8);
588 try l.air_instructions.ensureTotalCapacity(gpa, expected_instructions_len);
589581
590 var res_block_buf: [4]Air.Inst.Index = undefined;582 var inst_buf: [
591 var res_block: Block = .init(&res_block_buf);583 5 + switch (data_tag) {
584 .un_op, .ty_op => 1,
585 .bin_op, .ty_pl_vector_cmp => 2,
586 .pl_op_bin => 3,
587 } + 9
588 ]Air.Inst.Index = undefined;
589 try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
590
591 var res_block: Block = .init(&inst_buf);
592 {592 {
593 const res_alloc_inst = res_block.add(l, .{593 const res_alloc_inst = res_block.add(l, .{
594 .tag = .alloc,594 .tag = .alloc,
...@@ -606,39 +606,38 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -606,39 +606,38 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
606 } },606 } },
607 });607 });
608608
609 const loop_inst: Air.Inst.Index = @enumFromInt(l.air_instructions.len + (3 + arity + 7));609 var loop: Loop = .init(l, &res_block);
610 var loop_block_buf: [3 + arity + 2]Air.Inst.Index = undefined;610 loop.block = .init(res_block.stealRemainingCapacity());
611 var loop_block: Block = .init(&loop_block_buf);
612 {611 {
613 const cur_index_inst = loop_block.add(l, .{612 const cur_index_inst = loop.block.add(l, .{
614 .tag = .load,613 .tag = .load,
615 .data = .{ .ty_op = .{614 .data = .{ .ty_op = .{
616 .ty = .usize_type,615 .ty = .usize_type,
617 .operand = index_alloc_inst.toRef(),616 .operand = index_alloc_inst.toRef(),
618 } },617 } },
619 });618 });
620 _ = loop_block.add(l, .{619 _ = loop.block.add(l, .{
621 .tag = .vector_store_elem,620 .tag = .vector_store_elem,
622 .data = .{ .vector_store_elem = .{621 .data = .{ .vector_store_elem = .{
623 .vector_ptr = res_alloc_inst.toRef(),622 .vector_ptr = res_alloc_inst.toRef(),
624 .payload = try l.addExtra(Air.Bin, .{623 .payload = try l.addExtra(Air.Bin, .{
625 .lhs = cur_index_inst.toRef(),624 .lhs = cur_index_inst.toRef(),
626 .rhs = loop_block.add(l, res_elem: switch (data_tag) {625 .rhs = res_elem: switch (data_tag) {
627 .un_op => .{626 .un_op => loop.block.add(l, .{
628 .tag = orig.tag,627 .tag = orig.tag,
629 .data = .{ .un_op = loop_block.add(l, .{628 .data = .{ .un_op = loop.block.add(l, .{
630 .tag = .array_elem_val,629 .tag = .array_elem_val,
631 .data = .{ .bin_op = .{630 .data = .{ .bin_op = .{
632 .lhs = orig.data.un_op,631 .lhs = orig.data.un_op,
633 .rhs = cur_index_inst.toRef(),632 .rhs = cur_index_inst.toRef(),
634 } },633 } },
635 }).toRef() },634 }).toRef() },
636 },635 }),
637 .ty_op => .{636 .ty_op => loop.block.add(l, .{
638 .tag = orig.tag,637 .tag = orig.tag,
639 .data = .{ .ty_op = .{638 .data = .{ .ty_op = .{
640 .ty = Air.internedToRef(orig.data.ty_op.ty.toType().scalarType(zcu).toIntern()),639 .ty = Air.internedToRef(orig.data.ty_op.ty.toType().scalarType(zcu).toIntern()),
641 .operand = loop_block.add(l, .{640 .operand = loop.block.add(l, .{
642 .tag = .array_elem_val,641 .tag = .array_elem_val,
643 .data = .{ .bin_op = .{642 .data = .{ .bin_op = .{
644 .lhs = orig.data.ty_op.operand,643 .lhs = orig.data.ty_op.operand,
...@@ -646,18 +645,18 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -646,18 +645,18 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
646 } },645 } },
647 }).toRef(),646 }).toRef(),
648 } },647 } },
649 },648 }),
650 .bin_op => .{649 .bin_op => loop.block.add(l, .{
651 .tag = orig.tag,650 .tag = orig.tag,
652 .data = .{ .bin_op = .{651 .data = .{ .bin_op = .{
653 .lhs = loop_block.add(l, .{652 .lhs = loop.block.add(l, .{
654 .tag = .array_elem_val,653 .tag = .array_elem_val,
655 .data = .{ .bin_op = .{654 .data = .{ .bin_op = .{
656 .lhs = orig.data.bin_op.lhs,655 .lhs = orig.data.bin_op.lhs,
657 .rhs = cur_index_inst.toRef(),656 .rhs = cur_index_inst.toRef(),
658 } },657 } },
659 }).toRef(),658 }).toRef(),
660 .rhs = loop_block.add(l, .{659 .rhs = loop.block.add(l, .{
661 .tag = .array_elem_val,660 .tag = .array_elem_val,
662 .data = .{ .bin_op = .{661 .data = .{ .bin_op = .{
663 .lhs = orig.data.bin_op.rhs,662 .lhs = orig.data.bin_op.rhs,
...@@ -665,61 +664,47 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -665,61 +664,47 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
665 } },664 } },
666 }).toRef(),665 }).toRef(),
667 } },666 } },
668 },667 }),
669 .ty_pl_vector_cmp => {668 .ty_pl_vector_cmp => {
670 const extra = l.extraData(Air.VectorCmp, orig.data.ty_pl.payload).data;669 const extra = l.extraData(Air.VectorCmp, orig.data.ty_pl.payload).data;
671 break :res_elem .{670 break :res_elem try loop.block.addCmp(
672 .tag = switch (orig.tag) {671 l,
672 extra.compareOperator(),
673 loop.block.add(l, .{
674 .tag = .array_elem_val,
675 .data = .{ .bin_op = .{
676 .lhs = extra.lhs,
677 .rhs = cur_index_inst.toRef(),
678 } },
679 }).toRef(),
680 loop.block.add(l, .{
681 .tag = .array_elem_val,
682 .data = .{ .bin_op = .{
683 .lhs = extra.rhs,
684 .rhs = cur_index_inst.toRef(),
685 } },
686 }).toRef(),
687 .{ .optimized = switch (orig.tag) {
673 else => unreachable,688 else => unreachable,
674 .cmp_vector => switch (extra.compareOperator()) {689 .cmp_vector => false,
675 .lt => .cmp_lt,690 .cmp_vector_optimized => true,
676 .lte => .cmp_lte,
677 .eq => .cmp_eq,
678 .gte => .cmp_gte,
679 .gt => .cmp_gt,
680 .neq => .cmp_neq,
681 },
682 .cmp_vector_optimized => switch (extra.compareOperator()) {
683 .lt => .cmp_lt_optimized,
684 .lte => .cmp_lte_optimized,
685 .eq => .cmp_eq_optimized,
686 .gte => .cmp_gte_optimized,
687 .gt => .cmp_gt_optimized,
688 .neq => .cmp_neq_optimized,
689 },
690 },
691 .data = .{ .bin_op = .{
692 .lhs = loop_block.add(l, .{
693 .tag = .array_elem_val,
694 .data = .{ .bin_op = .{
695 .lhs = extra.lhs,
696 .rhs = cur_index_inst.toRef(),
697 } },
698 }).toRef(),
699 .rhs = loop_block.add(l, .{
700 .tag = .array_elem_val,
701 .data = .{ .bin_op = .{
702 .lhs = extra.rhs,
703 .rhs = cur_index_inst.toRef(),
704 } },
705 }).toRef(),
706 } },691 } },
707 };692 );
708 },693 },
709 .pl_op_bin => {694 .pl_op_bin => {
710 const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data;695 const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data;
711 break :res_elem .{696 break :res_elem loop.block.add(l, .{
712 .tag = orig.tag,697 .tag = orig.tag,
713 .data = .{ .pl_op = .{698 .data = .{ .pl_op = .{
714 .payload = try l.addExtra(Air.Bin, .{699 .payload = try l.addExtra(Air.Bin, .{
715 .lhs = loop_block.add(l, .{700 .lhs = loop.block.add(l, .{
716 .tag = .array_elem_val,701 .tag = .array_elem_val,
717 .data = .{ .bin_op = .{702 .data = .{ .bin_op = .{
718 .lhs = extra.lhs,703 .lhs = extra.lhs,
719 .rhs = cur_index_inst.toRef(),704 .rhs = cur_index_inst.toRef(),
720 } },705 } },
721 }).toRef(),706 }).toRef(),
722 .rhs = loop_block.add(l, .{707 .rhs = loop.block.add(l, .{
723 .tag = .array_elem_val,708 .tag = .array_elem_val,
724 .data = .{ .bin_op = .{709 .data = .{ .bin_op = .{
725 .lhs = extra.rhs,710 .lhs = extra.rhs,
...@@ -727,7 +712,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -727,7 +712,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
727 } },712 } },
728 }).toRef(),713 }).toRef(),
729 }),714 }),
730 .operand = loop_block.add(l, .{715 .operand = loop.block.add(l, .{
731 .tag = .array_elem_val,716 .tag = .array_elem_val,
732 .data = .{ .bin_op = .{717 .data = .{ .bin_op = .{
733 .lhs = orig.data.pl_op.operand,718 .lhs = orig.data.pl_op.operand,
...@@ -735,28 +720,32 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -735,28 +720,32 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
735 } },720 } },
736 }).toRef(),721 }).toRef(),
737 } },722 } },
738 };723 });
739 },724 },
740 }).toRef(),725 }.toRef(),
741 }),726 }),
742 } },727 } },
743 });728 });
744 const not_done_inst = loop_block.add(l, .{
745 .tag = .cmp_lt,
746 .data = .{ .bin_op = .{
747 .lhs = cur_index_inst.toRef(),
748 .rhs = try pt.intRef(.usize, res_ty.vectorLen(zcu) - 1),
749 } },
750 });
751729
752 var not_done_block_buf: [3]Air.Inst.Index = undefined;730 var loop_cond_br: CondBr = .init(
753 var not_done_block: Block = .init(&not_done_block_buf);731 l,
732 (try loop.block.addCmp(
733 l,
734 .lt,
735 cur_index_inst.toRef(),
736 try pt.intRef(.usize, res_ty.vectorLen(zcu) - 1),
737 .{},
738 )).toRef(),
739 &loop.block,
740 .{},
741 );
742 loop_cond_br.then_block = .init(loop.block.stealRemainingCapacity());
754 {743 {
755 _ = not_done_block.add(l, .{744 _ = loop_cond_br.then_block.add(l, .{
756 .tag = .store,745 .tag = .store,
757 .data = .{ .bin_op = .{746 .data = .{ .bin_op = .{
758 .lhs = index_alloc_inst.toRef(),747 .lhs = index_alloc_inst.toRef(),
759 .rhs = not_done_block.add(l, .{748 .rhs = loop_cond_br.then_block.add(l, .{
760 .tag = .add,749 .tag = .add,
761 .data = .{ .bin_op = .{750 .data = .{ .bin_op = .{
762 .lhs = cur_index_inst.toRef(),751 .lhs = cur_index_inst.toRef(),
...@@ -765,19 +754,18 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -765,19 +754,18 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
765 }).toRef(),754 }).toRef(),
766 } },755 } },
767 });756 });
768 _ = not_done_block.add(l, .{757 _ = loop_cond_br.then_block.add(l, .{
769 .tag = .repeat,758 .tag = .repeat,
770 .data = .{ .repeat = .{ .loop_inst = loop_inst } },759 .data = .{ .repeat = .{ .loop_inst = loop.inst } },
771 });760 });
772 }761 }
773 var done_block_buf: [2]Air.Inst.Index = undefined;762 loop_cond_br.else_block = .init(loop_cond_br.then_block.stealRemainingCapacity());
774 var done_block: Block = .init(&done_block_buf);
775 {763 {
776 _ = done_block.add(l, .{764 _ = loop_cond_br.else_block.add(l, .{
777 .tag = .br,765 .tag = .br,
778 .data = .{ .br = .{766 .data = .{ .br = .{
779 .block_inst = orig_inst,767 .block_inst = orig_inst,
780 .operand = done_block.add(l, .{768 .operand = loop_cond_br.else_block.add(l, .{
781 .tag = .load,769 .tag = .load,
782 .data = .{ .ty_op = .{770 .data = .{ .ty_op = .{
783 .ty = Air.internedToRef(res_ty.toIntern()),771 .ty = Air.internedToRef(res_ty.toIntern()),
...@@ -787,32 +775,19 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_...@@ -787,32 +775,19 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_
787 } },775 } },
788 });776 });
789 }777 }
790 _ = loop_block.add(l, .{778 try loop_cond_br.finish(l);
791 .tag = .cond_br,
792 .data = .{ .pl_op = .{
793 .operand = not_done_inst.toRef(),
794 .payload = try l.addCondBrBodies(not_done_block.body(), done_block.body()),
795 } },
796 });
797 }779 }
798 assert(loop_inst == res_block.add(l, .{780 try loop.finish(l);
799 .tag = .loop,
800 .data = .{ .ty_pl = .{
801 .ty = .noreturn_type,
802 .payload = try l.addBlockBody(loop_block.body()),
803 } },
804 }));
805 }781 }
806 assert(l.air_instructions.len == expected_instructions_len);
807 return .{ .ty_pl = .{782 return .{ .ty_pl = .{
808 .ty = Air.internedToRef(res_ty.toIntern()),783 .ty = Air.internedToRef(res_ty.toIntern()),
809 .payload = try l.addBlockBody(res_block.body()),784 .payload = try l.addBlockBody(res_block.body()),
810 } };785 } };
811}786}
787
812fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data {788fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data {
813 const pt = l.pt;789 const pt = l.pt;
814 const zcu = pt.zcu;790 const zcu = pt.zcu;
815 const gpa = zcu.gpa;
816 const ty_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].ty_op;791 const ty_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].ty_op;
817792
818 const operand_ref = ty_op.operand;793 const operand_ref = ty_op.operand;
...@@ -882,12 +857,12 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In...@@ -882,12 +857,12 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
882 // })857 // })
883 // })858 // })
884859
885 try l.air_instructions.ensureUnusedCapacity(gpa, 12);860 var inst_buf: [12]Air.Inst.Index = undefined;
886 var body_inst_buf: [12]Air.Inst.Index = undefined;861 try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
887 var condbr_buf: [2]CondBr = undefined;862 var condbr_buf: [2]CondBr = undefined;
888 var condbr_idx: usize = 0;863 var condbr_idx: usize = 0;
889864
890 var main_block: Block = .init(&body_inst_buf);865 var main_block: Block = .init(&inst_buf);
891 var cur_block: *Block = &main_block;866 var cur_block: *Block = &main_block;
892867
893 const panic_id: Zcu.SimplePanicId = if (dest_is_enum) .invalid_enum_value else .cast_truncated_data;868 const panic_id: Zcu.SimplePanicId = if (dest_is_enum) .invalid_enum_value else .cast_truncated_data;
...@@ -898,11 +873,11 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In...@@ -898,11 +873,11 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
898 condbr_idx += 1;873 condbr_idx += 1;
899 const below_min_inst: Air.Inst.Index = if (have_min_check) inst: {874 const below_min_inst: Air.Inst.Index = if (have_min_check) inst: {
900 const min_val_ref = Air.internedToRef((try dest_int_ty.minInt(pt, operand_ty)).toIntern());875 const min_val_ref = Air.internedToRef((try dest_int_ty.minInt(pt, operand_ty)).toIntern());
901 break :inst try cur_block.addCmp(l, is_vector, .lt, operand_ref, min_val_ref);876 break :inst try cur_block.addCmp(l, .lt, operand_ref, min_val_ref, .{ .vector = is_vector });
902 } else undefined;877 } else undefined;
903 const above_max_inst: Air.Inst.Index = if (have_max_check) inst: {878 const above_max_inst: Air.Inst.Index = if (have_max_check) inst: {
904 const max_val_ref = Air.internedToRef((try dest_int_ty.maxInt(pt, operand_ty)).toIntern());879 const max_val_ref = Air.internedToRef((try dest_int_ty.maxInt(pt, operand_ty)).toIntern());
905 break :inst try cur_block.addCmp(l, is_vector, .gt, operand_ref, max_val_ref);880 break :inst try cur_block.addCmp(l, .gt, operand_ref, max_val_ref, .{ .vector = is_vector });
906 } else undefined;881 } else undefined;
907 const out_of_range_inst: Air.Inst.Index = inst: {882 const out_of_range_inst: Air.Inst.Index = inst: {
908 if (have_min_check and have_max_check) break :inst cur_block.add(l, .{883 if (have_min_check and have_max_check) break :inst cur_block.add(l, .{
...@@ -923,10 +898,7 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In...@@ -923,10 +898,7 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
923 .operation = .Or,898 .operation = .Or,
924 } },899 } },
925 }) else out_of_range_inst;900 }) else out_of_range_inst;
926 condbr.* = .init(l, scalar_out_of_range_inst.toRef(), cur_block, .{901 condbr.* = .init(l, scalar_out_of_range_inst.toRef(), cur_block, .{ .true = .cold });
927 .true = .cold,
928 .false = .none,
929 });
930 condbr.then_block = .init(cur_block.stealRemainingCapacity());902 condbr.then_block = .init(cur_block.stealRemainingCapacity());
931 try condbr.then_block.addPanic(l, panic_id);903 try condbr.then_block.addPanic(l, panic_id);
932 condbr.else_block = .init(condbr.then_block.stealRemainingCapacity());904 condbr.else_block = .init(condbr.then_block.stealRemainingCapacity());
...@@ -957,10 +929,7 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In...@@ -957,10 +929,7 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
957 });929 });
958 const condbr = &condbr_buf[condbr_idx];930 const condbr = &condbr_buf[condbr_idx];
959 condbr_idx += 1;931 condbr_idx += 1;
960 condbr.* = .init(l, is_named_inst.toRef(), cur_block, .{932 condbr.* = .init(l, is_named_inst.toRef(), cur_block, .{ .false = .cold });
961 .true = .none,
962 .false = .cold,
963 });
964 condbr.else_block = .init(cur_block.stealRemainingCapacity());933 condbr.else_block = .init(cur_block.stealRemainingCapacity());
965 try condbr.else_block.addPanic(l, panic_id);934 try condbr.else_block.addPanic(l, panic_id);
966 condbr.then_block = .init(condbr.else_block.stealRemainingCapacity());935 condbr.then_block = .init(condbr.else_block.stealRemainingCapacity());
...@@ -986,7 +955,6 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In...@@ -986,7 +955,6 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In
986fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_op_tag: Air.Inst.Tag) Error!Air.Inst.Data {955fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_op_tag: Air.Inst.Tag) Error!Air.Inst.Data {
987 const pt = l.pt;956 const pt = l.pt;
988 const zcu = pt.zcu;957 const zcu = pt.zcu;
989 const gpa = zcu.gpa;
990 const bin_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].bin_op;958 const bin_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].bin_op;
991959
992 const operand_ty = l.typeOf(bin_op.lhs);960 const operand_ty = l.typeOf(bin_op.lhs);
...@@ -1009,10 +977,10 @@ fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_...@@ -1009,10 +977,10 @@ fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_
1009 // %8 = struct_field_val(%1, .@"0")977 // %8 = struct_field_val(%1, .@"0")
1010 // %9 = br(%z, %8)978 // %9 = br(%z, %8)
1011 // })979 // })
1012 try l.air_instructions.ensureUnusedCapacity(gpa, 9);980 var inst_buf: [9]Air.Inst.Index = undefined;
1013 var body_inst_buf: [9]Air.Inst.Index = undefined;981 try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len);
1014982
1015 var main_block: Block = .init(&body_inst_buf);983 var main_block: Block = .init(&inst_buf);
1016984
1017 const overflow_op_inst = main_block.add(l, .{985 const overflow_op_inst = main_block.add(l, .{
1018 .tag = overflow_op_tag,986 .tag = overflow_op_tag,
...@@ -1041,12 +1009,9 @@ fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_...@@ -1041,12 +1009,9 @@ fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_
1041 .operation = .Or,1009 .operation = .Or,
1042 } },1010 } },
1043 }) else overflow_bits_inst;1011 }) else overflow_bits_inst;
1044 const any_overflow_inst = try main_block.addCmp(l, false, .eq, any_overflow_bit_inst.toRef(), .one_u1);1012 const any_overflow_inst = try main_block.addCmp(l, .eq, any_overflow_bit_inst.toRef(), .one_u1, .{});
10451013
1046 var condbr: CondBr = .init(l, any_overflow_inst.toRef(), &main_block, .{1014 var condbr: CondBr = .init(l, any_overflow_inst.toRef(), &main_block, .{ .true = .cold });
1047 .true = .cold,
1048 .false = .none,
1049 });
1050 condbr.then_block = .init(main_block.stealRemainingCapacity());1015 condbr.then_block = .init(main_block.stealRemainingCapacity());
1051 try condbr.then_block.addPanic(l, .integer_overflow);1016 try condbr.then_block.addPanic(l, .integer_overflow);
1052 condbr.else_block = .init(condbr.then_block.stealRemainingCapacity());1017 condbr.else_block = .init(condbr.then_block.stealRemainingCapacity());
...@@ -1130,19 +1095,19 @@ const Block = struct {...@@ -1130,19 +1095,19 @@ const Block = struct {
1130 fn addCmp(1095 fn addCmp(
1131 b: *Block,1096 b: *Block,
1132 l: *Legalize,1097 l: *Legalize,
1133 is_vector: bool,
1134 op: std.math.CompareOperator,1098 op: std.math.CompareOperator,
1135 lhs: Air.Inst.Ref,1099 lhs: Air.Inst.Ref,
1136 rhs: Air.Inst.Ref,1100 rhs: Air.Inst.Ref,
1101 opts: struct { optimized: bool = false, vector: bool = false },
1137 ) Error!Air.Inst.Index {1102 ) Error!Air.Inst.Index {
1138 const pt = l.pt;1103 const pt = l.pt;
1139 if (is_vector) {1104 if (opts.vector) {
1140 const bool_vec_ty = try pt.vectorType(.{1105 const bool_vec_ty = try pt.vectorType(.{
1141 .child = .bool_type,1106 .child = .bool_type,
1142 .len = l.typeOf(lhs).vectorLen(pt.zcu),1107 .len = l.typeOf(lhs).vectorLen(pt.zcu),
1143 });1108 });
1144 return b.add(l, .{1109 return b.add(l, .{
1145 .tag = .cmp_vector,1110 .tag = if (opts.optimized) .cmp_vector_optimized else .cmp_vector,
1146 .data = .{ .ty_pl = .{1111 .data = .{ .ty_pl = .{
1147 .ty = Air.internedToRef(bool_vec_ty.toIntern()),1112 .ty = Air.internedToRef(bool_vec_ty.toIntern()),
1148 .payload = try l.addExtra(Air.VectorCmp, .{1113 .payload = try l.addExtra(Air.VectorCmp, .{
...@@ -1155,12 +1120,12 @@ const Block = struct {...@@ -1155,12 +1120,12 @@ const Block = struct {
1155 }1120 }
1156 return b.add(l, .{1121 return b.add(l, .{
1157 .tag = switch (op) {1122 .tag = switch (op) {
1158 .lt => .cmp_lt,1123 .lt => if (opts.optimized) .cmp_lt_optimized else .cmp_lt,
1159 .lte => .cmp_lte,1124 .lte => if (opts.optimized) .cmp_lte_optimized else .cmp_lte,
1160 .eq => .cmp_eq,1125 .eq => if (opts.optimized) .cmp_eq_optimized else .cmp_eq,
1161 .gte => .cmp_gte,1126 .gte => if (opts.optimized) .cmp_gte_optimized else .cmp_gte,
1162 .gt => .cmp_gt,1127 .gt => if (opts.optimized) .cmp_gt_optimized else .cmp_gt,
1163 .neq => .cmp_neq,1128 .neq => if (opts.optimized) .cmp_neq_optimized else .cmp_neq,
1164 },1129 },
1165 .data = .{ .bin_op = .{1130 .data = .{ .bin_op = .{
1166 .lhs = lhs,1131 .lhs = lhs,
...@@ -1184,20 +1149,40 @@ const Block = struct {...@@ -1184,20 +1149,40 @@ const Block = struct {
1184 }1149 }
1185};1150};
11861151
1152const Loop = struct {
1153 inst: Air.Inst.Index,
1154 block: Block,
1155
1156 /// The return value has `block` initialized to `undefined`; it is the caller's reponsibility
1157 /// to initialize it.
1158 fn init(l: *Legalize, parent_block: *Block) Loop {
1159 return .{
1160 .inst = parent_block.add(l, .{
1161 .tag = .loop,
1162 .data = .{ .ty_pl = .{
1163 .ty = .noreturn_type,
1164 .payload = undefined,
1165 } },
1166 }),
1167 .block = undefined,
1168 };
1169 }
1170
1171 fn finish(loop: Loop, l: *Legalize) Error!void {
1172 const data = &l.air_instructions.items(.data)[@intFromEnum(loop.inst)];
1173 data.ty_pl.payload = try l.addBlockBody(loop.block.body());
1174 }
1175};
1176
1187const CondBr = struct {1177const CondBr = struct {
1188 inst: Air.Inst.Index,1178 inst: Air.Inst.Index,
1189 hints: BranchHints,1179 hints: Air.CondBr.BranchHints,
1190 then_block: Block,1180 then_block: Block,
1191 else_block: Block,1181 else_block: Block,
11921182
1193 const BranchHints = struct {
1194 true: std.builtin.BranchHint,
1195 false: std.builtin.BranchHint,
1196 };
1197
1198 /// The return value has `then_block` and `else_block` initialized to `undefined`; it is the1183 /// The return value has `then_block` and `else_block` initialized to `undefined`; it is the
1199 /// caller's reponsibility to initialize them.1184 /// caller's reponsibility to initialize them.
1200 fn init(l: *Legalize, operand: Air.Inst.Ref, parent_block: *Block, hints: BranchHints) CondBr {1185 fn init(l: *Legalize, operand: Air.Inst.Ref, parent_block: *Block, hints: Air.CondBr.BranchHints) CondBr {
1201 return .{1186 return .{
1202 .inst = parent_block.add(l, .{1187 .inst = parent_block.add(l, .{
1203 .tag = .cond_br,1188 .tag = .cond_br,
...@@ -1213,17 +1198,19 @@ const CondBr = struct {...@@ -1213,17 +1198,19 @@ const CondBr = struct {
1213 }1198 }
12141199
1215 fn finish(cond_br: CondBr, l: *Legalize) Error!void {1200 fn finish(cond_br: CondBr, l: *Legalize) Error!void {
1201 const then_body = cond_br.then_block.body();
1202 const else_body = cond_br.else_block.body();
1203 try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, 3 + then_body.len + else_body.len);
1204
1216 const data = &l.air_instructions.items(.data)[@intFromEnum(cond_br.inst)];1205 const data = &l.air_instructions.items(.data)[@intFromEnum(cond_br.inst)];
1217 data.pl_op.payload = try l.addCondBrBodiesHints(1206 data.pl_op.payload = @intCast(l.air_extra.items.len);
1218 cond_br.then_block.body(),1207 l.air_extra.appendSliceAssumeCapacity(&.{
1219 cond_br.else_block.body(),1208 @intCast(then_body.len),
1220 .{1209 @intCast(else_body.len),
1221 .true = cond_br.hints.true,1210 @bitCast(cond_br.hints),
1222 .false = cond_br.hints.false,1211 });
1223 .then_cov = .none,1212 l.air_extra.appendSliceAssumeCapacity(@ptrCast(then_body));
1224 .else_cov = .none,1213 l.air_extra.appendSliceAssumeCapacity(@ptrCast(else_body));
1225 },
1226 );
1227 }1214 }
1228};1215};
12291216
...@@ -1252,28 +1239,6 @@ fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 {...@@ -1252,28 +1239,6 @@ fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 {
1252 return @intCast(l.air_extra.items.len);1239 return @intCast(l.air_extra.items.len);
1253}1240}
12541241
1255fn addCondBrBodies(l: *Legalize, then_body: []const Air.Inst.Index, else_body: []const Air.Inst.Index) Error!u32 {
1256 return l.addCondBrBodiesHints(then_body, else_body, .{
1257 .true = .none,
1258 .false = .none,
1259 .then_cov = .none,
1260 .else_cov = .none,
1261 });
1262}
1263fn addCondBrBodiesHints(l: *Legalize, then_body: []const Air.Inst.Index, else_body: []const Air.Inst.Index, hints: Air.CondBr.BranchHints) Error!u32 {
1264 try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, 3 + then_body.len + else_body.len);
1265 defer {
1266 l.air_extra.appendSliceAssumeCapacity(&.{
1267 @intCast(then_body.len),
1268 @intCast(else_body.len),
1269 @bitCast(hints),
1270 });
1271 l.air_extra.appendSliceAssumeCapacity(@ptrCast(then_body));
1272 l.air_extra.appendSliceAssumeCapacity(@ptrCast(else_body));
1273 }
1274 return @intCast(l.air_extra.items.len);
1275}
1276
1277// inline to propagate comptime `tag`s1242// inline to propagate comptime `tag`s
1278inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag {1243inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag {
1279 const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {};1244 const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {};