Skip to content

Commit 4b6740e

Browse files
committed
sometimes free stuff from Zig IR pass 1
Total bytes used in stage1 std lib tests: 3.418 -> 3.198 GiB (saving 225 MiB) There's still this from pass 1 not getting freed: Const: 6909049 items, 72 bytes each, total 474.407 MiB This is due to 2 things hanging on to references to IrAnalyze pointers: * ZigVar->owner_exec->analysis * LazyValue->ira The LazyValue one could be solved by memoizing the results after the lazy value is resolved, and then it could unref the IrAnalyze. ZigVars that are determined to be comptime const, could have their const_value set to that value, instead of using the mem_slot_index mechanism. This would prevent an IrAnalyze ref in some cases.
1 parent 5026b1a commit 4b6740e

File tree

4 files changed

+400
-22
lines changed

4 files changed

+400
-22
lines changed

src/all_types.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,7 @@ struct ZigFn {
15651565
// in the case of async functions this is the implicit return type according to the
15661566
// zig source code, not according to zig ir
15671567
ZigType *src_implicit_return_type;
1568-
IrExecutable ir_executable;
1568+
IrExecutable *ir_executable;
15691569
IrExecutable analyzed_executable;
15701570
size_t prealloc_bbc;
15711571
size_t prealloc_backward_branch_quota;
@@ -2204,6 +2204,8 @@ struct ZigVar {
22042204
bool src_is_const;
22052205
bool gen_is_const;
22062206
bool is_thread_local;
2207+
bool is_comptime_memoized;
2208+
bool is_comptime_memoized_value;
22072209
};
22082210

22092211
struct ErrorTableEntry {

src/analyze.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,14 +3275,15 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i
32753275
}
32763276

32773277
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {
3278-
ZigFn *fn_entry = allocate<ZigFn>(1);
3278+
ZigFn *fn_entry = allocate<ZigFn>(1, "ZigFn");
3279+
fn_entry->ir_executable = allocate<IrExecutable>(1, "IrExecutablePass1");
32793280

32803281
fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota;
32813282

32823283
fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc;
32833284
fn_entry->analyzed_executable.backward_branch_quota = &fn_entry->prealloc_backward_branch_quota;
32843285
fn_entry->analyzed_executable.fn_entry = fn_entry;
3285-
fn_entry->ir_executable.fn_entry = fn_entry;
3286+
fn_entry->ir_executable->fn_entry = fn_entry;
32863287
fn_entry->fn_inline = inline_value;
32873288

32883289
return fn_entry;
@@ -4610,7 +4611,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
46104611
assert(!fn_type->data.fn.is_generic);
46114612
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
46124613

4613-
ZigType *block_return_type = ir_analyze(g, &fn->ir_executable,
4614+
ZigType *block_return_type = ir_analyze(g, fn->ir_executable,
46144615
&fn->analyzed_executable, fn_type_id->return_type, return_type_node);
46154616
fn->src_implicit_return_type = block_return_type;
46164617

@@ -4706,15 +4707,15 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
47064707
assert(!fn_type->data.fn.is_generic);
47074708

47084709
ir_gen_fn(g, fn_table_entry);
4709-
if (fn_table_entry->ir_executable.first_err_trace_msg != nullptr) {
4710+
if (fn_table_entry->ir_executable->first_err_trace_msg != nullptr) {
47104711
fn_table_entry->anal_state = FnAnalStateInvalid;
47114712
return;
47124713
}
47134714
if (g->verbose_ir) {
47144715
fprintf(stderr, "\n");
47154716
ast_render(stderr, fn_table_entry->body_node, 4);
47164717
fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name));
4717-
ir_print(g, stderr, &fn_table_entry->ir_executable, 4, IrPassSrc);
4718+
ir_print(g, stderr, fn_table_entry->ir_executable, 4, IrPassSrc);
47184719
fprintf(stderr, "}\n");
47194720
}
47204721

@@ -6453,20 +6454,31 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
64536454
}
64546455

64556456
bool ir_get_var_is_comptime(ZigVar *var) {
6457+
if (var->is_comptime_memoized)
6458+
return var->is_comptime_memoized_value;
6459+
6460+
var->is_comptime_memoized = true;
6461+
64566462
// The is_comptime field can be left null, which means not comptime.
6457-
if (var->is_comptime == nullptr)
6458-
return false;
6463+
if (var->is_comptime == nullptr) {
6464+
var->is_comptime_memoized_value = false;
6465+
return var->is_comptime_memoized_value;
6466+
}
64596467
// When the is_comptime field references an instruction that has to get analyzed, this
64606468
// is the value.
64616469
if (var->is_comptime->child != nullptr) {
64626470
assert(var->is_comptime->child->value->type->id == ZigTypeIdBool);
6463-
return var->is_comptime->child->value->data.x_bool;
6471+
var->is_comptime_memoized_value = var->is_comptime->child->value->data.x_bool;
6472+
var->is_comptime = nullptr;
6473+
return var->is_comptime_memoized_value;
64646474
}
64656475
// As an optimization, is_comptime values which are constant are allowed
64666476
// to be omitted from analysis. In this case, there is no child instruction
64676477
// and we simply look at the unanalyzed const parent instruction.
64686478
assert(var->is_comptime->value->type->id == ZigTypeIdBool);
6469-
return var->is_comptime->value->data.x_bool;
6479+
var->is_comptime_memoized_value = var->is_comptime->value->data.x_bool;
6480+
var->is_comptime = nullptr;
6481+
return var->is_comptime_memoized_value;
64706482
}
64716483

64726484
bool const_values_equal_ptr(ZigValue *a, ZigValue *b) {

0 commit comments

Comments
 (0)