authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-05-05 21:40:04+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-13 12:42:31+01:00
loga377bf87ce6f021f958087bcf080425845a7bae6
tree78a56f67bc486ed2330ea278a6b97a0f83561b24
parent387f9568ad0dabd426d382efb45b9c52a4ccc5bb
signaturelock-open Commit is signed but in an unrecognized format.

Zir: remove unnecessary switch_capture_multi instructions

By indexing from the very first switch case rather than into scalar and multi cases separately, the instructions for capturing in multi cases become unnecessary, freeing up 2 ZIR tags.

4 files changed, 27 insertions(+), 96 deletions(-)

src/AstGen.zig+2-11
...@@ -2614,8 +2614,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2614,8 +2614,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2614 .switch_cond_ref,2614 .switch_cond_ref,
2615 .switch_capture,2615 .switch_capture,
2616 .switch_capture_ref,2616 .switch_capture_ref,
2617 .switch_capture_multi,
2618 .switch_capture_multi_ref,
2619 .switch_capture_tag,2617 .switch_capture_tag,
2620 .struct_init_empty,2618 .struct_init_empty,
2621 .struct_init,2619 .struct_init,
...@@ -6916,15 +6914,8 @@ fn switchExpr(...@@ -6916,15 +6914,8 @@ fn switchExpr(
6916 },6914 },
6917 });6915 });
6918 } else {6916 } else {
6919 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);6917 const capture_tag: Zir.Inst.Tag = if (is_ptr) .switch_capture_ref else .switch_capture;
6920 const is_ptr_bits: u2 = @boolToInt(is_ptr);6918 const capture_index = if (is_multi_case) scalar_cases_len + multi_case_index else scalar_case_index;
6921 const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) {
6922 0b00 => .switch_capture,
6923 0b01 => .switch_capture_ref,
6924 0b10 => .switch_capture_multi,
6925 0b11 => .switch_capture_multi_ref,
6926 };
6927 const capture_index = if (is_multi_case) multi_case_index else scalar_case_index;
6928 capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);6919 capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
6929 try astgen.instructions.append(gpa, .{6920 try astgen.instructions.append(gpa, .{
6930 .tag = capture_tag,6921 .tag = capture_tag,
src/Sema.zig+4-12
...@@ -1017,10 +1017,8 @@ fn analyzeBodyInner(...@@ -1017,10 +1017,8 @@ fn analyzeBodyInner(
1017 .switch_block => try sema.zirSwitchBlock(block, inst),1017 .switch_block => try sema.zirSwitchBlock(block, inst),
1018 .switch_cond => try sema.zirSwitchCond(block, inst, false),1018 .switch_cond => try sema.zirSwitchCond(block, inst, false),
1019 .switch_cond_ref => try sema.zirSwitchCond(block, inst, true),1019 .switch_cond_ref => try sema.zirSwitchCond(block, inst, true),
1020 .switch_capture => try sema.zirSwitchCapture(block, inst, false, false),1020 .switch_capture => try sema.zirSwitchCapture(block, inst, false),
1021 .switch_capture_ref => try sema.zirSwitchCapture(block, inst, false, true),1021 .switch_capture_ref => try sema.zirSwitchCapture(block, inst, true),
1022 .switch_capture_multi => try sema.zirSwitchCapture(block, inst, true, false),
1023 .switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true),
1024 .switch_capture_tag => try sema.zirSwitchCaptureTag(block, inst),1022 .switch_capture_tag => try sema.zirSwitchCaptureTag(block, inst),
1025 .type_info => try sema.zirTypeInfo(block, inst),1023 .type_info => try sema.zirTypeInfo(block, inst),
1026 .size_of => try sema.zirSizeOf(block, inst),1024 .size_of => try sema.zirSizeOf(block, inst),
...@@ -10089,7 +10087,6 @@ fn zirSwitchCapture(...@@ -10089,7 +10087,6 @@ fn zirSwitchCapture(
10089 sema: *Sema,10087 sema: *Sema,
10090 block: *Block,10088 block: *Block,
10091 inst: Zir.Inst.Index,10089 inst: Zir.Inst.Index,
10092 is_multi: bool,
10093 is_ref: bool,10090 is_ref: bool,
10094) CompileError!Air.Inst.Ref {10091) CompileError!Air.Inst.Ref {
10095 const tracy = trace(@src());10092 const tracy = trace(@src());
...@@ -10178,12 +10175,7 @@ fn zirSwitchCapture(...@@ -10178,12 +10175,7 @@ fn zirSwitchCapture(
10178 }10175 }
10179 }10176 }
1018010177
10181 const items = if (is_multi)10178 const items = switch_extra.data.getProng(sema.code, switch_extra.end, capture_info.prong_index).items;
10182 switch_extra.data.getMultiProng(sema.code, switch_extra.end, capture_info.prong_index).items
10183 else
10184 &[_]Zir.Inst.Ref{
10185 switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item,
10186 };
1018710179
10188 switch (operand_ty.zigTypeTag(mod)) {10180 switch (operand_ty.zigTypeTag(mod)) {
10189 .Union => {10181 .Union => {
...@@ -10252,7 +10244,7 @@ fn zirSwitchCapture(...@@ -10252,7 +10244,7 @@ fn zirSwitchCapture(
10252 return block.addStructFieldVal(operand, first_field_index, first_field.ty);10244 return block.addStructFieldVal(operand, first_field_index, first_field.ty);
10253 },10245 },
10254 .ErrorSet => {10246 .ErrorSet => {
10255 if (is_multi) {10247 if (items.len > 1) {
10256 var names: Module.Fn.InferredErrorSet.NameMap = .{};10248 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10257 try names.ensureUnusedCapacity(sema.arena, items.len);10249 try names.ensureUnusedCapacity(sema.arena, items.len);
10258 for (items) |item| {10250 for (items) |item| {
src/Zir.zig+21-71
...@@ -687,15 +687,6 @@ pub const Inst = struct {...@@ -687,15 +687,6 @@ pub const Inst = struct {
687 /// If the `prong_index` field is max int, it means this is the capture687 /// If the `prong_index` field is max int, it means this is the capture
688 /// for the else/`_` prong.688 /// for the else/`_` prong.
689 switch_capture_ref,689 switch_capture_ref,
690 /// Produces the capture value for a switch prong.
691 /// The prong is one of the multi cases.
692 /// Uses the `switch_capture` field.
693 switch_capture_multi,
694 /// Produces the capture value for a switch prong.
695 /// The prong is one of the multi cases.
696 /// Result is a pointer to the value.
697 /// Uses the `switch_capture` field.
698 switch_capture_multi_ref,
699 /// Produces the capture value for an inline switch prong tag capture.690 /// Produces the capture value for an inline switch prong tag capture.
700 /// Uses the `un_tok` field.691 /// Uses the `un_tok` field.
701 switch_capture_tag,692 switch_capture_tag,
...@@ -1146,8 +1137,6 @@ pub const Inst = struct {...@@ -1146,8 +1137,6 @@ pub const Inst = struct {
1146 .set_eval_branch_quota,1137 .set_eval_branch_quota,
1147 .switch_capture,1138 .switch_capture,
1148 .switch_capture_ref,1139 .switch_capture_ref,
1149 .switch_capture_multi,
1150 .switch_capture_multi_ref,
1151 .switch_capture_tag,1140 .switch_capture_tag,
1152 .switch_block,1141 .switch_block,
1153 .switch_cond,1142 .switch_cond,
...@@ -1440,8 +1429,6 @@ pub const Inst = struct {...@@ -1440,8 +1429,6 @@ pub const Inst = struct {
1440 .typeof_log2_int_type,1429 .typeof_log2_int_type,
1441 .switch_capture,1430 .switch_capture,
1442 .switch_capture_ref,1431 .switch_capture_ref,
1443 .switch_capture_multi,
1444 .switch_capture_multi_ref,
1445 .switch_capture_tag,1432 .switch_capture_tag,
1446 .switch_block,1433 .switch_block,
1447 .switch_cond,1434 .switch_cond,
...@@ -1700,8 +1687,6 @@ pub const Inst = struct {...@@ -1700,8 +1687,6 @@ pub const Inst = struct {
1700 .switch_cond_ref = .un_node,1687 .switch_cond_ref = .un_node,
1701 .switch_capture = .switch_capture,1688 .switch_capture = .switch_capture,
1702 .switch_capture_ref = .switch_capture,1689 .switch_capture_ref = .switch_capture,
1703 .switch_capture_multi = .switch_capture,
1704 .switch_capture_multi_ref = .switch_capture,
1705 .switch_capture_tag = .un_tok,1690 .switch_capture_tag = .un_tok,
1706 .array_base_ptr = .un_node,1691 .array_base_ptr = .un_node,
1707 .field_base_ptr = .un_node,1692 .field_base_ptr = .un_node,
...@@ -2735,8 +2720,8 @@ pub const Inst = struct {...@@ -2735,8 +2720,8 @@ pub const Inst = struct {
2735 }2720 }
2736 };2721 };
27372722
2738 pub const ScalarProng = struct {2723 pub const MultiProng = struct {
2739 item: Ref,2724 items: []const Ref,
2740 body: []const Index,2725 body: []const Index,
2741 };2726 };
27422727
...@@ -2744,56 +2729,13 @@ pub const Inst = struct {...@@ -2744,56 +2729,13 @@ pub const Inst = struct {
2744 /// change the definition of switch_capture instruction to store extra_index2729 /// change the definition of switch_capture instruction to store extra_index
2745 /// instead of prong_index. This way, Sema won't be doing O(N^2) iterations2730 /// instead of prong_index. This way, Sema won't be doing O(N^2) iterations
2746 /// over the switch prongs.2731 /// over the switch prongs.
2747 pub fn getScalarProng(2732 pub fn getProng(
2748 self: SwitchBlock,
2749 zir: Zir,
2750 extra_end: usize,
2751 prong_index: usize,
2752 ) ScalarProng {
2753 var extra_index: usize = extra_end;
2754
2755 if (self.bits.has_multi_cases) {
2756 extra_index += 1;
2757 }
2758
2759 if (self.bits.specialProng() != .none) {
2760 const body_len = @truncate(u31, zir.extra[extra_index]);
2761 extra_index += 1;
2762 const body = zir.extra[extra_index..][0..body_len];
2763 extra_index += body.len;
2764 }
2765
2766 var scalar_i: usize = 0;
2767 while (true) : (scalar_i += 1) {
2768 const item = @intToEnum(Ref, zir.extra[extra_index]);
2769 extra_index += 1;
2770 const body_len = @truncate(u31, zir.extra[extra_index]);
2771 extra_index += 1;
2772 const body = zir.extra[extra_index..][0..body_len];
2773 extra_index += body.len;
2774
2775 if (scalar_i < prong_index) continue;
2776
2777 return .{
2778 .item = item,
2779 .body = body,
2780 };
2781 }
2782 }
2783
2784 pub const MultiProng = struct {
2785 items: []const Ref,
2786 body: []const Index,
2787 };
2788
2789 pub fn getMultiProng(
2790 self: SwitchBlock,2733 self: SwitchBlock,
2791 zir: Zir,2734 zir: Zir,
2792 extra_end: usize,2735 extra_end: usize,
2793 prong_index: usize,2736 prong_index: usize,
2794 ) MultiProng {2737 ) MultiProng {
2795 // +1 for self.bits.has_multi_cases == true2738 var extra_index: usize = extra_end + @boolToInt(self.bits.has_multi_cases);
2796 var extra_index: usize = extra_end + 1;
27972739
2798 if (self.bits.specialProng() != .none) {2740 if (self.bits.specialProng() != .none) {
2799 const body_len = @truncate(u31, zir.extra[extra_index]);2741 const body_len = @truncate(u31, zir.extra[extra_index]);
...@@ -2802,15 +2744,22 @@ pub const Inst = struct {...@@ -2802,15 +2744,22 @@ pub const Inst = struct {
2802 extra_index += body.len;2744 extra_index += body.len;
2803 }2745 }
28042746
2805 var scalar_i: usize = 0;2747 var cur_idx: usize = 0;
2806 while (scalar_i < self.bits.scalar_cases_len) : (scalar_i += 1) {2748 while (cur_idx < self.bits.scalar_cases_len) : (cur_idx += 1) {
2749 const items = zir.refSlice(extra_index, 1);
2807 extra_index += 1;2750 extra_index += 1;
2808 const body_len = @truncate(u31, zir.extra[extra_index]);2751 const body_len = @truncate(u31, zir.extra[extra_index]);
2809 extra_index += 1;2752 extra_index += 1;
2753 const body = zir.extra[extra_index..][0..body_len];
2810 extra_index += body_len;2754 extra_index += body_len;
2755 if (cur_idx == prong_index) {
2756 return .{
2757 .items = items,
2758 .body = body,
2759 };
2760 }
2811 }2761 }
2812 var multi_i: u32 = 0;2762 while (true) : (cur_idx += 1) {
2813 while (true) : (multi_i += 1) {
2814 const items_len = zir.extra[extra_index];2763 const items_len = zir.extra[extra_index];
2815 extra_index += 1;2764 extra_index += 1;
2816 const ranges_len = zir.extra[extra_index];2765 const ranges_len = zir.extra[extra_index];
...@@ -2825,11 +2774,12 @@ pub const Inst = struct {...@@ -2825,11 +2774,12 @@ pub const Inst = struct {
2825 const body = zir.extra[extra_index..][0..body_len];2774 const body = zir.extra[extra_index..][0..body_len];
2826 extra_index += body_len;2775 extra_index += body_len;
28272776
2828 if (multi_i < prong_index) continue;2777 if (cur_idx == prong_index) {
2829 return .{2778 return .{
2830 .items = items,2779 .items = items,
2831 .body = body,2780 .body = body,
2832 };2781 };
2782 }
2833 }2783 }
2834 }2784 }
2835 };2785 };
src/print_zir.zig-2
...@@ -438,8 +438,6 @@ const Writer = struct {...@@ -438,8 +438,6 @@ const Writer = struct {
438438
439 .switch_capture,439 .switch_capture,
440 .switch_capture_ref,440 .switch_capture_ref,
441 .switch_capture_multi,
442 .switch_capture_multi_ref,
443 => try self.writeSwitchCapture(stream, inst),441 => try self.writeSwitchCapture(stream, inst),
444442
445 .dbg_stmt => try self.writeDbgStmt(stream, inst),443 .dbg_stmt => try self.writeDbgStmt(stream, inst),