Skip to content

Commit a377bf8

Browse files
committed
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.
1 parent 387f956 commit a377bf8

4 files changed

Lines changed: 27 additions & 96 deletions

File tree

src/AstGen.zig

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 21 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -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,65 +2720,22 @@ 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

27432728
/// TODO performance optimization: instead of having this helper method
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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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),

0 commit comments

Comments
 (0)