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
signature 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
26142614 .switch_cond_ref,
26152615 .switch_capture,
26162616 .switch_capture_ref,
2617 .switch_capture_multi,
2618 .switch_capture_multi_ref,
26192617 .switch_capture_tag,
26202618 .struct_init_empty,
26212619 .struct_init,
......@@ -6916,15 +6914,8 @@ fn switchExpr(
69166914 },
69176915 });
69186916 } else {
6919 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);
6920 const is_ptr_bits: u2 = @boolToInt(is_ptr);
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;
6917 const capture_tag: Zir.Inst.Tag = if (is_ptr) .switch_capture_ref else .switch_capture;
6918 const capture_index = if (is_multi_case) scalar_cases_len + multi_case_index else scalar_case_index;
69286919 capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
69296920 try astgen.instructions.append(gpa, .{
69306921 .tag = capture_tag,
src/Sema.zig+4-12
......@@ -1017,10 +1017,8 @@ fn analyzeBodyInner(
10171017 .switch_block => try sema.zirSwitchBlock(block, inst),
10181018 .switch_cond => try sema.zirSwitchCond(block, inst, false),
10191019 .switch_cond_ref => try sema.zirSwitchCond(block, inst, true),
1020 .switch_capture => try sema.zirSwitchCapture(block, inst, false, false),
1021 .switch_capture_ref => try sema.zirSwitchCapture(block, inst, false, true),
1022 .switch_capture_multi => try sema.zirSwitchCapture(block, inst, true, false),
1023 .switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true),
1020 .switch_capture => try sema.zirSwitchCapture(block, inst, false),
1021 .switch_capture_ref => try sema.zirSwitchCapture(block, inst, true),
10241022 .switch_capture_tag => try sema.zirSwitchCaptureTag(block, inst),
10251023 .type_info => try sema.zirTypeInfo(block, inst),
10261024 .size_of => try sema.zirSizeOf(block, inst),
......@@ -10089,7 +10087,6 @@ fn zirSwitchCapture(
1008910087 sema: *Sema,
1009010088 block: *Block,
1009110089 inst: Zir.Inst.Index,
10092 is_multi: bool,
1009310090 is_ref: bool,
1009410091) CompileError!Air.Inst.Ref {
1009510092 const tracy = trace(@src());
......@@ -10178,12 +10175,7 @@ fn zirSwitchCapture(
1017810175 }
1017910176 }
1018010177
10181 const items = if (is_multi)
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 };
10178 const items = switch_extra.data.getProng(sema.code, switch_extra.end, capture_info.prong_index).items;
1018710179
1018810180 switch (operand_ty.zigTypeTag(mod)) {
1018910181 .Union => {
......@@ -10252,7 +10244,7 @@ fn zirSwitchCapture(
1025210244 return block.addStructFieldVal(operand, first_field_index, first_field.ty);
1025310245 },
1025410246 .ErrorSet => {
10255 if (is_multi) {
10247 if (items.len > 1) {
1025610248 var names: Module.Fn.InferredErrorSet.NameMap = .{};
1025710249 try names.ensureUnusedCapacity(sema.arena, items.len);
1025810250 for (items) |item| {
src/Zir.zig+21-71
......@@ -687,15 +687,6 @@ pub const Inst = struct {
687687 /// If the `prong_index` field is max int, it means this is the capture
688688 /// for the else/`_` prong.
689689 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,
699690 /// Produces the capture value for an inline switch prong tag capture.
700691 /// Uses the `un_tok` field.
701692 switch_capture_tag,
......@@ -1146,8 +1137,6 @@ pub const Inst = struct {
11461137 .set_eval_branch_quota,
11471138 .switch_capture,
11481139 .switch_capture_ref,
1149 .switch_capture_multi,
1150 .switch_capture_multi_ref,
11511140 .switch_capture_tag,
11521141 .switch_block,
11531142 .switch_cond,
......@@ -1440,8 +1429,6 @@ pub const Inst = struct {
14401429 .typeof_log2_int_type,
14411430 .switch_capture,
14421431 .switch_capture_ref,
1443 .switch_capture_multi,
1444 .switch_capture_multi_ref,
14451432 .switch_capture_tag,
14461433 .switch_block,
14471434 .switch_cond,
......@@ -1700,8 +1687,6 @@ pub const Inst = struct {
17001687 .switch_cond_ref = .un_node,
17011688 .switch_capture = .switch_capture,
17021689 .switch_capture_ref = .switch_capture,
1703 .switch_capture_multi = .switch_capture,
1704 .switch_capture_multi_ref = .switch_capture,
17051690 .switch_capture_tag = .un_tok,
17061691 .array_base_ptr = .un_node,
17071692 .field_base_ptr = .un_node,
......@@ -2735,8 +2720,8 @@ pub const Inst = struct {
27352720 }
27362721 };
27372722
2738 pub const ScalarProng = struct {
2739 item: Ref,
2723 pub const MultiProng = struct {
2724 items: []const Ref,
27402725 body: []const Index,
27412726 };
27422727
......@@ -2744,56 +2729,13 @@ pub const Inst = struct {
27442729 /// change the definition of switch_capture instruction to store extra_index
27452730 /// instead of prong_index. This way, Sema won't be doing O(N^2) iterations
27462731 /// over the switch prongs.
2747 pub fn getScalarProng(
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(
2732 pub fn getProng(
27902733 self: SwitchBlock,
27912734 zir: Zir,
27922735 extra_end: usize,
27932736 prong_index: usize,
27942737 ) MultiProng {
2795 // +1 for self.bits.has_multi_cases == true
2796 var extra_index: usize = extra_end + 1;
2738 var extra_index: usize = extra_end + @boolToInt(self.bits.has_multi_cases);
27972739
27982740 if (self.bits.specialProng() != .none) {
27992741 const body_len = @truncate(u31, zir.extra[extra_index]);
......@@ -2802,15 +2744,22 @@ pub const Inst = struct {
28022744 extra_index += body.len;
28032745 }
28042746
2805 var scalar_i: usize = 0;
2806 while (scalar_i < self.bits.scalar_cases_len) : (scalar_i += 1) {
2747 var cur_idx: usize = 0;
2748 while (cur_idx < self.bits.scalar_cases_len) : (cur_idx += 1) {
2749 const items = zir.refSlice(extra_index, 1);
28072750 extra_index += 1;
28082751 const body_len = @truncate(u31, zir.extra[extra_index]);
28092752 extra_index += 1;
2753 const body = zir.extra[extra_index..][0..body_len];
28102754 extra_index += body_len;
2755 if (cur_idx == prong_index) {
2756 return .{
2757 .items = items,
2758 .body = body,
2759 };
2760 }
28112761 }
2812 var multi_i: u32 = 0;
2813 while (true) : (multi_i += 1) {
2762 while (true) : (cur_idx += 1) {
28142763 const items_len = zir.extra[extra_index];
28152764 extra_index += 1;
28162765 const ranges_len = zir.extra[extra_index];
......@@ -2825,11 +2774,12 @@ pub const Inst = struct {
28252774 const body = zir.extra[extra_index..][0..body_len];
28262775 extra_index += body_len;
28272776
2828 if (multi_i < prong_index) continue;
2829 return .{
2830 .items = items,
2831 .body = body,
2832 };
2777 if (cur_idx == prong_index) {
2778 return .{
2779 .items = items,
2780 .body = body,
2781 };
2782 }
28332783 }
28342784 }
28352785 };
src/print_zir.zig-2
......@@ -438,8 +438,6 @@ const Writer = struct {
438438
439439 .switch_capture,
440440 .switch_capture_ref,
441 .switch_capture_multi,
442 .switch_capture_multi_ref,
443441 => try self.writeSwitchCapture(stream, inst),
444442
445443 .dbg_stmt => try self.writeDbgStmt(stream, inst),