authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-11 21:23:47+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-16 11:26:32+00:00
log2e27967a81d325047e6d82f8c0722a8a654d1ac7
treec22414dd9d53298085a27932f071edcbdde2b912
parent51e96a823ce21a6b027bfdf55d94c3872a103703
signaturelock-open Commit is signed but in an unrecognized format.

AstGen: avoid emitting multiple `ret_type` instructions

This is a small optimization to generated ZIR. In any function where the return type is not a trivial Ref, we know it is almost certainly not `void` (unless the user aliased it or did something else weird to fool AstGen), and thus the return type is very likely to be required for return value RLS at some point. Thus, we can just emit one `ret_type` at the start of the function and use it throughout. This sees a very small improvement in overall ZIR bytes.

1 files changed, 22 insertions(+), 3 deletions(-)

src/AstGen.zig+22-3
...@@ -44,6 +44,9 @@ compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},...@@ -44,6 +44,9 @@ compile_errors: ArrayListUnmanaged(Zir.Inst.CompileErrors.Item) = .{},
44/// The topmost block of the current function.44/// The topmost block of the current function.
45fn_block: ?*GenZir = null,45fn_block: ?*GenZir = null,
46fn_var_args: bool = false,46fn_var_args: bool = false,
47/// The return type of the current function. This may be a trivial `Ref`, or
48/// otherwise it refers to a `ret_type` instruction.
49fn_ret_ty: Zir.Inst.Ref = .none,
47/// Maps string table indexes to the first `@import` ZIR instruction50/// Maps string table indexes to the first `@import` ZIR instruction
48/// that uses this string as the operand.51/// that uses this string as the operand.
49imports: std.AutoArrayHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .{},52imports: std.AutoArrayHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .{},
...@@ -4284,8 +4287,19 @@ fn fnDecl(...@@ -4284,8 +4287,19 @@ fn fnDecl(
4284 fn_gz.instructions_top = ret_gz.instructions.items.len;4287 fn_gz.instructions_top = ret_gz.instructions.items.len;
42854288
4286 const prev_fn_block = astgen.fn_block;4289 const prev_fn_block = astgen.fn_block;
4290 const prev_fn_ret_ty = astgen.fn_ret_ty;
4287 astgen.fn_block = &fn_gz;4291 astgen.fn_block = &fn_gz;
4288 defer astgen.fn_block = prev_fn_block;4292 astgen.fn_ret_ty = if (is_inferred_error or ret_ref.toIndex() != null) r: {
4293 // We're essentially guaranteed to need the return type at some point,
4294 // since the return type is likely not `void` or `noreturn` so there
4295 // will probably be an explicit return requiring RLS. Fetch this
4296 // return type now so the rest of the function can use it.
4297 break :r try fn_gz.addNode(.ret_type, decl_node);
4298 } else ret_ref;
4299 defer {
4300 astgen.fn_block = prev_fn_block;
4301 astgen.fn_ret_ty = prev_fn_ret_ty;
4302 }
42894303
4290 const prev_var_args = astgen.fn_var_args;4304 const prev_var_args = astgen.fn_var_args;
4291 astgen.fn_var_args = is_var_args;4305 astgen.fn_var_args = is_var_args;
...@@ -4732,8 +4746,13 @@ fn testDecl(...@@ -4732,8 +4746,13 @@ fn testDecl(
4732 defer fn_block.unstack();4746 defer fn_block.unstack();
47334747
4734 const prev_fn_block = astgen.fn_block;4748 const prev_fn_block = astgen.fn_block;
4749 const prev_fn_ret_ty = astgen.fn_ret_ty;
4735 astgen.fn_block = &fn_block;4750 astgen.fn_block = &fn_block;
4736 defer astgen.fn_block = prev_fn_block;4751 astgen.fn_ret_ty = .anyerror_void_error_union_type;
4752 defer {
4753 astgen.fn_block = prev_fn_block;
4754 astgen.fn_ret_ty = prev_fn_ret_ty;
4755 }
47374756
4738 astgen.advanceSourceCursorToNode(body_node);4757 astgen.advanceSourceCursorToNode(body_node);
4739 const lbrace_line = astgen.source_line - decl_block.decl_line;4758 const lbrace_line = astgen.source_line - decl_block.decl_line;
...@@ -8038,7 +8057,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -8038,7 +8057,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
8038 .rl = .{ .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) } },8057 .rl = .{ .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) } },
8039 .ctx = .@"return",8058 .ctx = .@"return",
8040 } else .{8059 } else .{
8041 .rl = .{ .ty = try gz.addNode(.ret_type, node) },8060 .rl = .{ .ty = astgen.fn_ret_ty },
8042 .ctx = .@"return",8061 .ctx = .@"return",
8043 };8062 };
8044 const prev_anon_name_strategy = gz.anon_name_strategy;8063 const prev_anon_name_strategy = gz.anon_name_strategy;