| ... | ... | @@ -575,20 +575,20 @@ inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag: |
| 575 | 575 | fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag: ScalarizeDataTag) Error!Air.Inst.Data { |
| 576 | 576 | const pt = l.pt; |
| 577 | 577 | const zcu = pt.zcu; |
| 578 | | const gpa = zcu.gpa; |
| 579 | 578 | |
| 580 | 579 | const orig = l.air_instructions.get(@intFromEnum(orig_inst)); |
| 581 | 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); |
| 589 | 581 | |
| 590 | | var res_block_buf: [4]Air.Inst.Index = undefined; |
| 591 | | var res_block: Block = .init(&res_block_buf); |
| 582 | var inst_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 | 593 | const res_alloc_inst = res_block.add(l, .{ |
| 594 | 594 | .tag = .alloc, |
| ... | ... | @@ -606,39 +606,38 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_ |
| 606 | 606 | } }, |
| 607 | 607 | }); |
| 608 | 608 | |
| 609 | | const loop_inst: Air.Inst.Index = @enumFromInt(l.air_instructions.len + (3 + arity + 7)); |
| 610 | | var loop_block_buf: [3 + arity + 2]Air.Inst.Index = undefined; |
| 611 | | var loop_block: Block = .init(&loop_block_buf); |
| 609 | var loop: Loop = .init(l, &res_block); |
| 610 | loop.block = .init(res_block.stealRemainingCapacity()); |
| 612 | 611 | { |
| 613 | | const cur_index_inst = loop_block.add(l, .{ |
| 612 | const cur_index_inst = loop.block.add(l, .{ |
| 614 | 613 | .tag = .load, |
| 615 | 614 | .data = .{ .ty_op = .{ |
| 616 | 615 | .ty = .usize_type, |
| 617 | 616 | .operand = index_alloc_inst.toRef(), |
| 618 | 617 | } }, |
| 619 | 618 | }); |
| 620 | | _ = loop_block.add(l, .{ |
| 619 | _ = loop.block.add(l, .{ |
| 621 | 620 | .tag = .vector_store_elem, |
| 622 | 621 | .data = .{ .vector_store_elem = .{ |
| 623 | 622 | .vector_ptr = res_alloc_inst.toRef(), |
| 624 | 623 | .payload = try l.addExtra(Air.Bin, .{ |
| 625 | 624 | .lhs = cur_index_inst.toRef(), |
| 626 | | .rhs = loop_block.add(l, res_elem: switch (data_tag) { |
| 627 | | .un_op => .{ |
| 625 | .rhs = res_elem: switch (data_tag) { |
| 626 | .un_op => loop.block.add(l, .{ |
| 628 | 627 | .tag = orig.tag, |
| 629 | | .data = .{ .un_op = loop_block.add(l, .{ |
| 628 | .data = .{ .un_op = loop.block.add(l, .{ |
| 630 | 629 | .tag = .array_elem_val, |
| 631 | 630 | .data = .{ .bin_op = .{ |
| 632 | 631 | .lhs = orig.data.un_op, |
| 633 | 632 | .rhs = cur_index_inst.toRef(), |
| 634 | 633 | } }, |
| 635 | 634 | }).toRef() }, |
| 636 | | }, |
| 637 | | .ty_op => .{ |
| 635 | }), |
| 636 | .ty_op => loop.block.add(l, .{ |
| 638 | 637 | .tag = orig.tag, |
| 639 | 638 | .data = .{ .ty_op = .{ |
| 640 | 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 | 641 | .tag = .array_elem_val, |
| 643 | 642 | .data = .{ .bin_op = .{ |
| 644 | 643 | .lhs = orig.data.ty_op.operand, |
| ... | ... | @@ -646,18 +645,18 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_ |
| 646 | 645 | } }, |
| 647 | 646 | }).toRef(), |
| 648 | 647 | } }, |
| 649 | | }, |
| 650 | | .bin_op => .{ |
| 648 | }), |
| 649 | .bin_op => loop.block.add(l, .{ |
| 651 | 650 | .tag = orig.tag, |
| 652 | 651 | .data = .{ .bin_op = .{ |
| 653 | | .lhs = loop_block.add(l, .{ |
| 652 | .lhs = loop.block.add(l, .{ |
| 654 | 653 | .tag = .array_elem_val, |
| 655 | 654 | .data = .{ .bin_op = .{ |
| 656 | 655 | .lhs = orig.data.bin_op.lhs, |
| 657 | 656 | .rhs = cur_index_inst.toRef(), |
| 658 | 657 | } }, |
| 659 | 658 | }).toRef(), |
| 660 | | .rhs = loop_block.add(l, .{ |
| 659 | .rhs = loop.block.add(l, .{ |
| 661 | 660 | .tag = .array_elem_val, |
| 662 | 661 | .data = .{ .bin_op = .{ |
| 663 | 662 | .lhs = orig.data.bin_op.rhs, |
| ... | ... | @@ -665,61 +664,47 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_ |
| 665 | 664 | } }, |
| 666 | 665 | }).toRef(), |
| 667 | 666 | } }, |
| 668 | | }, |
| 667 | }), |
| 669 | 668 | .ty_pl_vector_cmp => { |
| 670 | 669 | const extra = l.extraData(Air.VectorCmp, orig.data.ty_pl.payload).data; |
| 671 | | break :res_elem .{ |
| 672 | | .tag = switch (orig.tag) { |
| 670 | break :res_elem try loop.block.addCmp( |
| 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 | 688 | else => unreachable, |
| 674 | | .cmp_vector => switch (extra.compareOperator()) { |
| 675 | | .lt => .cmp_lt, |
| 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(), |
| 689 | .cmp_vector => false, |
| 690 | .cmp_vector_optimized => true, |
| 706 | 691 | } }, |
| 707 | | }; |
| 692 | ); |
| 708 | 693 | }, |
| 709 | 694 | .pl_op_bin => { |
| 710 | 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 | 697 | .tag = orig.tag, |
| 713 | 698 | .data = .{ .pl_op = .{ |
| 714 | 699 | .payload = try l.addExtra(Air.Bin, .{ |
| 715 | | .lhs = loop_block.add(l, .{ |
| 700 | .lhs = loop.block.add(l, .{ |
| 716 | 701 | .tag = .array_elem_val, |
| 717 | 702 | .data = .{ .bin_op = .{ |
| 718 | 703 | .lhs = extra.lhs, |
| 719 | 704 | .rhs = cur_index_inst.toRef(), |
| 720 | 705 | } }, |
| 721 | 706 | }).toRef(), |
| 722 | | .rhs = loop_block.add(l, .{ |
| 707 | .rhs = loop.block.add(l, .{ |
| 723 | 708 | .tag = .array_elem_val, |
| 724 | 709 | .data = .{ .bin_op = .{ |
| 725 | 710 | .lhs = extra.rhs, |
| ... | ... | @@ -727,7 +712,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_ |
| 727 | 712 | } }, |
| 728 | 713 | }).toRef(), |
| 729 | 714 | }), |
| 730 | | .operand = loop_block.add(l, .{ |
| 715 | .operand = loop.block.add(l, .{ |
| 731 | 716 | .tag = .array_elem_val, |
| 732 | 717 | .data = .{ .bin_op = .{ |
| 733 | 718 | .lhs = orig.data.pl_op.operand, |
| ... | ... | @@ -735,28 +720,32 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_ |
| 735 | 720 | } }, |
| 736 | 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 | | }); |
| 751 | 729 | |
| 752 | | var not_done_block_buf: [3]Air.Inst.Index = undefined; |
| 753 | | var not_done_block: Block = .init(&not_done_block_buf); |
| 730 | var loop_cond_br: CondBr = .init( |
| 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 | 745 | .tag = .store, |
| 757 | 746 | .data = .{ .bin_op = .{ |
| 758 | 747 | .lhs = index_alloc_inst.toRef(), |
| 759 | | .rhs = not_done_block.add(l, .{ |
| 748 | .rhs = loop_cond_br.then_block.add(l, .{ |
| 760 | 749 | .tag = .add, |
| 761 | 750 | .data = .{ .bin_op = .{ |
| 762 | 751 | .lhs = cur_index_inst.toRef(), |
| ... | ... | @@ -765,19 +754,18 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_ |
| 765 | 754 | }).toRef(), |
| 766 | 755 | } }, |
| 767 | 756 | }); |
| 768 | | _ = not_done_block.add(l, .{ |
| 757 | _ = loop_cond_br.then_block.add(l, .{ |
| 769 | 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; |
| 774 | | var done_block: Block = .init(&done_block_buf); |
| 762 | loop_cond_br.else_block = .init(loop_cond_br.then_block.stealRemainingCapacity()); |
| 775 | 763 | { |
| 776 | | _ = done_block.add(l, .{ |
| 764 | _ = loop_cond_br.else_block.add(l, .{ |
| 777 | 765 | .tag = .br, |
| 778 | 766 | .data = .{ .br = .{ |
| 779 | 767 | .block_inst = orig_inst, |
| 780 | | .operand = done_block.add(l, .{ |
| 768 | .operand = loop_cond_br.else_block.add(l, .{ |
| 781 | 769 | .tag = .load, |
| 782 | 770 | .data = .{ .ty_op = .{ |
| 783 | 771 | .ty = Air.internedToRef(res_ty.toIntern()), |
| ... | ... | @@ -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, .{ |
| 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 | | }); |
| 778 | try loop_cond_br.finish(l); |
| 797 | 779 | } |
| 798 | | assert(loop_inst == res_block.add(l, .{ |
| 799 | | .tag = .loop, |
| 800 | | .data = .{ .ty_pl = .{ |
| 801 | | .ty = .noreturn_type, |
| 802 | | .payload = try l.addBlockBody(loop_block.body()), |
| 803 | | } }, |
| 804 | | })); |
| 780 | try loop.finish(l); |
| 805 | 781 | } |
| 806 | | assert(l.air_instructions.len == expected_instructions_len); |
| 807 | 782 | return .{ .ty_pl = .{ |
| 808 | 783 | .ty = Air.internedToRef(res_ty.toIntern()), |
| 809 | 784 | .payload = try l.addBlockBody(res_block.body()), |
| 810 | 785 | } }; |
| 811 | 786 | } |
| 787 | |
| 812 | 788 | fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data { |
| 813 | 789 | const pt = l.pt; |
| 814 | 790 | const zcu = pt.zcu; |
| 815 | | const gpa = zcu.gpa; |
| 816 | 791 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].ty_op; |
| 817 | 792 | |
| 818 | 793 | const operand_ref = ty_op.operand; |
| ... | ... | @@ -882,12 +857,12 @@ fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.In |
| 882 | 857 | // }) |
| 883 | 858 | // }) |
| 884 | 859 | |
| 885 | | try l.air_instructions.ensureUnusedCapacity(gpa, 12); |
| 886 | | var body_inst_buf: [12]Air.Inst.Index = undefined; |
| 860 | var inst_buf: [12]Air.Inst.Index = undefined; |
| 861 | try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len); |
| 887 | 862 | var condbr_buf: [2]CondBr = undefined; |
| 888 | 863 | var condbr_idx: usize = 0; |
| 889 | 864 | |
| 890 | | var main_block: Block = .init(&body_inst_buf); |
| 865 | var main_block: Block = .init(&inst_buf); |
| 891 | 866 | var cur_block: *Block = &main_block; |
| 892 | 867 | |
| 893 | 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 | 873 | condbr_idx += 1; |
| 899 | 874 | const below_min_inst: Air.Inst.Index = if (have_min_check) inst: { |
| 900 | 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 | 877 | } else undefined; |
| 903 | 878 | const above_max_inst: Air.Inst.Index = if (have_max_check) inst: { |
| 904 | 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 | 881 | } else undefined; |
| 907 | 882 | const out_of_range_inst: Air.Inst.Index = inst: { |
| 908 | 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 | 898 | .operation = .Or, |
| 924 | 899 | } }, |
| 925 | 900 | }) else out_of_range_inst; |
| 926 | | condbr.* = .init(l, scalar_out_of_range_inst.toRef(), cur_block, .{ |
| 927 | | .true = .cold, |
| 928 | | .false = .none, |
| 929 | | }); |
| 901 | condbr.* = .init(l, scalar_out_of_range_inst.toRef(), cur_block, .{ .true = .cold }); |
| 930 | 902 | condbr.then_block = .init(cur_block.stealRemainingCapacity()); |
| 931 | 903 | try condbr.then_block.addPanic(l, panic_id); |
| 932 | 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 | 929 | }); |
| 958 | 930 | const condbr = &condbr_buf[condbr_idx]; |
| 959 | 931 | condbr_idx += 1; |
| 960 | | condbr.* = .init(l, is_named_inst.toRef(), cur_block, .{ |
| 961 | | .true = .none, |
| 962 | | .false = .cold, |
| 963 | | }); |
| 932 | condbr.* = .init(l, is_named_inst.toRef(), cur_block, .{ .false = .cold }); |
| 964 | 933 | condbr.else_block = .init(cur_block.stealRemainingCapacity()); |
| 965 | 934 | try condbr.else_block.addPanic(l, panic_id); |
| 966 | 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 | 955 | fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_op_tag: Air.Inst.Tag) Error!Air.Inst.Data { |
| 987 | 956 | const pt = l.pt; |
| 988 | 957 | const zcu = pt.zcu; |
| 989 | | const gpa = zcu.gpa; |
| 990 | 958 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].bin_op; |
| 991 | 959 | |
| 992 | 960 | const operand_ty = l.typeOf(bin_op.lhs); |
| ... | ... | @@ -1009,10 +977,10 @@ fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_ |
| 1009 | 977 | // %8 = struct_field_val(%1, .@"0") |
| 1010 | 978 | // %9 = br(%z, %8) |
| 1011 | 979 | // }) |
| 1012 | | try l.air_instructions.ensureUnusedCapacity(gpa, 9); |
| 1013 | | var body_inst_buf: [9]Air.Inst.Index = undefined; |
| 980 | var inst_buf: [9]Air.Inst.Index = undefined; |
| 981 | try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len); |
| 1014 | 982 | |
| 1015 | | var main_block: Block = .init(&body_inst_buf); |
| 983 | var main_block: Block = .init(&inst_buf); |
| 1016 | 984 | |
| 1017 | 985 | const overflow_op_inst = main_block.add(l, .{ |
| 1018 | 986 | .tag = overflow_op_tag, |
| ... | ... | @@ -1041,12 +1009,9 @@ fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_ |
| 1041 | 1009 | .operation = .Or, |
| 1042 | 1010 | } }, |
| 1043 | 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, .{}); |
| 1045 | 1013 | |
| 1046 | | var condbr: CondBr = .init(l, any_overflow_inst.toRef(), &main_block, .{ |
| 1047 | | .true = .cold, |
| 1048 | | .false = .none, |
| 1049 | | }); |
| 1014 | var condbr: CondBr = .init(l, any_overflow_inst.toRef(), &main_block, .{ .true = .cold }); |
| 1050 | 1015 | condbr.then_block = .init(main_block.stealRemainingCapacity()); |
| 1051 | 1016 | try condbr.then_block.addPanic(l, .integer_overflow); |
| 1052 | 1017 | condbr.else_block = .init(condbr.then_block.stealRemainingCapacity()); |
| ... | ... | @@ -1130,19 +1095,19 @@ const Block = struct { |
| 1130 | 1095 | fn addCmp( |
| 1131 | 1096 | b: *Block, |
| 1132 | 1097 | l: *Legalize, |
| 1133 | | is_vector: bool, |
| 1134 | 1098 | op: std.math.CompareOperator, |
| 1135 | 1099 | lhs: Air.Inst.Ref, |
| 1136 | 1100 | rhs: Air.Inst.Ref, |
| 1101 | opts: struct { optimized: bool = false, vector: bool = false }, |
| 1137 | 1102 | ) Error!Air.Inst.Index { |
| 1138 | 1103 | const pt = l.pt; |
| 1139 | | if (is_vector) { |
| 1104 | if (opts.vector) { |
| 1140 | 1105 | const bool_vec_ty = try pt.vectorType(.{ |
| 1141 | 1106 | .child = .bool_type, |
| 1142 | 1107 | .len = l.typeOf(lhs).vectorLen(pt.zcu), |
| 1143 | 1108 | }); |
| 1144 | 1109 | return b.add(l, .{ |
| 1145 | | .tag = .cmp_vector, |
| 1110 | .tag = if (opts.optimized) .cmp_vector_optimized else .cmp_vector, |
| 1146 | 1111 | .data = .{ .ty_pl = .{ |
| 1147 | 1112 | .ty = Air.internedToRef(bool_vec_ty.toIntern()), |
| 1148 | 1113 | .payload = try l.addExtra(Air.VectorCmp, .{ |
| ... | ... | @@ -1155,12 +1120,12 @@ const Block = struct { |
| 1155 | 1120 | } |
| 1156 | 1121 | return b.add(l, .{ |
| 1157 | 1122 | .tag = switch (op) { |
| 1158 | | .lt => .cmp_lt, |
| 1159 | | .lte => .cmp_lte, |
| 1160 | | .eq => .cmp_eq, |
| 1161 | | .gte => .cmp_gte, |
| 1162 | | .gt => .cmp_gt, |
| 1163 | | .neq => .cmp_neq, |
| 1123 | .lt => if (opts.optimized) .cmp_lt_optimized else .cmp_lt, |
| 1124 | .lte => if (opts.optimized) .cmp_lte_optimized else .cmp_lte, |
| 1125 | .eq => if (opts.optimized) .cmp_eq_optimized else .cmp_eq, |
| 1126 | .gte => if (opts.optimized) .cmp_gte_optimized else .cmp_gte, |
| 1127 | .gt => if (opts.optimized) .cmp_gt_optimized else .cmp_gt, |
| 1128 | .neq => if (opts.optimized) .cmp_neq_optimized else .cmp_neq, |
| 1164 | 1129 | }, |
| 1165 | 1130 | .data = .{ .bin_op = .{ |
| 1166 | 1131 | .lhs = lhs, |
| ... | ... | @@ -1184,20 +1149,40 @@ const Block = struct { |
| 1184 | 1149 | } |
| 1185 | 1150 | }; |
| 1186 | 1151 | |
| 1152 | const 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 | |
| 1187 | 1177 | const CondBr = struct { |
| 1188 | 1178 | inst: Air.Inst.Index, |
| 1189 | | hints: BranchHints, |
| 1179 | hints: Air.CondBr.BranchHints, |
| 1190 | 1180 | then_block: Block, |
| 1191 | 1181 | else_block: Block, |
| 1192 | 1182 | |
| 1193 | | const BranchHints = struct { |
| 1194 | | true: std.builtin.BranchHint, |
| 1195 | | false: std.builtin.BranchHint, |
| 1196 | | }; |
| 1197 | | |
| 1198 | 1183 | /// The return value has `then_block` and `else_block` initialized to `undefined`; it is the |
| 1199 | 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 | 1186 | return .{ |
| 1202 | 1187 | .inst = parent_block.add(l, .{ |
| 1203 | 1188 | .tag = .cond_br, |
| ... | ... | @@ -1213,17 +1198,19 @@ const CondBr = struct { |
| 1213 | 1198 | } |
| 1214 | 1199 | |
| 1215 | 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 | 1205 | const data = &l.air_instructions.items(.data)[@intFromEnum(cond_br.inst)]; |
| 1217 | | data.pl_op.payload = try l.addCondBrBodiesHints( |
| 1218 | | cond_br.then_block.body(), |
| 1219 | | cond_br.else_block.body(), |
| 1220 | | .{ |
| 1221 | | .true = cond_br.hints.true, |
| 1222 | | .false = cond_br.hints.false, |
| 1223 | | .then_cov = .none, |
| 1224 | | .else_cov = .none, |
| 1225 | | }, |
| 1226 | | ); |
| 1206 | data.pl_op.payload = @intCast(l.air_extra.items.len); |
| 1207 | l.air_extra.appendSliceAssumeCapacity(&.{ |
| 1208 | @intCast(then_body.len), |
| 1209 | @intCast(else_body.len), |
| 1210 | @bitCast(cond_br.hints), |
| 1211 | }); |
| 1212 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(then_body)); |
| 1213 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(else_body)); |
| 1227 | 1214 | } |
| 1228 | 1215 | }; |
| 1229 | 1216 | |
| ... | ... | @@ -1252,28 +1239,6 @@ fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 { |
| 1252 | 1239 | return @intCast(l.air_extra.items.len); |
| 1253 | 1240 | } |
| 1254 | 1241 | |
| 1255 | | fn 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 | | } |
| 1263 | | fn 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 | 1242 | // inline to propagate comptime `tag`s |
| 1278 | 1243 | inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag { |
| 1279 | 1244 | const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {}; |