| ... | @@ -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: |
| 575 | fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime data_tag: ScalarizeDataTag) Error!Air.Inst.Data { | 575 | fn 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; | | |
| 579 | | 578 | |
| 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); | | |
| 589 | | 581 | |
| 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 | }); |
| 608 | | 608 | |
| 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 | }); | | |
| 751 | | 729 | |
| 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 | |
| 812 | fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data { | 788 | fn 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; |
| 817 | | 792 | |
| 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 | // }) |
| 884 | | 859 | |
| 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; |
| 889 | | 864 | |
| 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; |
| 892 | | 867 | |
| 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 |
| 986 | fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_op_tag: Air.Inst.Tag) Error!Air.Inst.Data { | 955 | fn 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; |
| 991 | | 959 | |
| 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); |
| 1014 | | 982 | |
| 1015 | var main_block: Block = .init(&body_inst_buf); | 983 | var main_block: Block = .init(&inst_buf); |
| 1016 | | 984 | |
| 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, .{}); |
| 1045 | | 1013 | |
| 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 | }; |
| 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 | const CondBr = struct { | 1177 | const 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, |
| 1192 | | 1182 | |
| 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 the | 1183 | /// 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 | } |
| 1214 | | 1199 | |
| 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 | }; |
| 1229 | | 1216 | |
| ... | @@ -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 | } |
| 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 | // inline to propagate comptime `tag`s | 1242 | // inline to propagate comptime `tag`s |
| 1278 | inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag { | 1243 | inline 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 {}; |