authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 02:34:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 02:34:01-07:00
log108af28c1bcac4b082f25dd4cdcf578091b99616
tree7ec79fd29988dcf56dd084a706c10b3ee36267d2
parent179443bd61c85c7d808304dc334bb407aa793988

optimization: avoid codegening unused functions


3 files changed, 40 insertions(+), 0 deletions(-)

src/all_types.hpp+2
......@@ -972,6 +972,7 @@ struct FnTableEntry {
972972 bool is_inline;
973973 bool internal_linkage;
974974 bool is_extern;
975 uint32_t ref_count; // if this is 0 we don't have to codegen it
975976
976977 // reminder: hash tables must be initialized before use
977978 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
......@@ -1000,6 +1001,7 @@ struct BuiltinFnEntry {
10001001 int param_count;
10011002 TypeTableEntry *return_type;
10021003 TypeTableEntry **param_types;
1004 uint32_t ref_count;
10031005 LLVMValueRef fn_val;
10041006};
10051007
src/analyze.cpp+6
......@@ -1123,6 +1123,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
11231123 fn_table_entry->is_extern = is_extern;
11241124 fn_table_entry->label_table.init(8);
11251125 fn_table_entry->member_of_struct = struct_type;
1126 fn_table_entry->ref_count = (proto_node->data.fn_proto.visib_mod == VisibModExport) ? 1 : 0;
11261127
11271128 if (struct_type) {
11281129 buf_resize(&fn_table_entry->symbol_name, 0);
......@@ -2244,6 +2245,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode
22442245}
22452246
22462247static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
2248 fn->ref_count += 1;
22472249 Expr *expr = get_resolved_expr(node);
22482250 expr->const_val.ok = true;
22492251 expr->const_val.data.x_fn = fn;
......@@ -3658,6 +3660,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
36583660 return g->builtin_types.entry_invalid;
36593661 }
36603662
3663 builtin_fn->ref_count += 1;
3664
36613665 switch (builtin_fn->id) {
36623666 case BuiltinFnIdInvalid:
36633667 zig_unreachable();
......@@ -3913,6 +3917,8 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
39133917
39143918 node->data.fn_call_expr.fn_entry = fn_table_entry;
39153919
3920 fn_table_entry->ref_count += 1;
3921
39163922 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
39173923
39183924}
src/codegen.cpp+32
......@@ -2582,9 +2582,28 @@ static void gen_const_globals(CodeGen *g) {
25822582 }
25832583}
25842584
2585static void delete_unused_builtin_fns(CodeGen *g) {
2586 auto it = g->builtin_fn_table.entry_iterator();
2587 for (;;) {
2588 auto *entry = it.next();
2589 if (!entry)
2590 break;
2591
2592 BuiltinFnEntry *builtin_fn = entry->value;
2593 if (builtin_fn->ref_count == 0 &&
2594 builtin_fn->fn_val)
2595 {
2596 LLVMDeleteFunction(entry->value->fn_val);
2597 }
2598 }
2599}
2600
25852601static void do_code_gen(CodeGen *g) {
25862602 assert(!g->errors.length);
25872603
2604 delete_unused_builtin_fns(g);
2605
2606
25882607 gen_const_globals(g);
25892608
25902609 // Generate module level variables
......@@ -2633,6 +2652,12 @@ static void do_code_gen(CodeGen *g) {
26332652 // Generate function prototypes
26342653 for (int fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {
26352654 FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i);
2655 if (fn_table_entry->ref_count == 0) {
2656 // huge time saver
2657 LLVMDeleteFunction(fn_table_entry->fn_value);
2658 continue;
2659 }
2660
26362661 AstNode *proto_node = fn_table_entry->proto_node;
26372662 assert(proto_node->type == NodeTypeFnProto);
26382663 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
......@@ -2681,6 +2706,11 @@ static void do_code_gen(CodeGen *g) {
26812706 // Generate function definitions.
26822707 for (int fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {
26832708 FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i);
2709 if (fn_table_entry->ref_count == 0) {
2710 // huge time saver
2711 continue;
2712 }
2713
26842714 ImportTableEntry *import = fn_table_entry->import_entry;
26852715 AstNode *fn_def_node = fn_table_entry->fn_def_node;
26862716 LLVMValueRef fn = fn_table_entry->fn_value;
......@@ -3064,6 +3094,7 @@ static void define_builtin_fns(CodeGen *g) {
30643094 builtin_fn->param_types[0] = nullptr; // manually checked later
30653095 builtin_fn->param_types[1] = nullptr; // manually checked later
30663096 builtin_fn->param_types[2] = g->builtin_types.entry_isize;
3097 builtin_fn->ref_count = 1;
30673098
30683099 LLVMTypeRef param_types[] = {
30693100 LLVMPointerType(LLVMInt8Type(), 0),
......@@ -3087,6 +3118,7 @@ static void define_builtin_fns(CodeGen *g) {
30873118 builtin_fn->param_types[0] = nullptr; // manually checked later
30883119 builtin_fn->param_types[1] = g->builtin_types.entry_u8;
30893120 builtin_fn->param_types[2] = g->builtin_types.entry_isize;
3121 builtin_fn->ref_count = 1;
30903122
30913123 LLVMTypeRef param_types[] = {
30923124 LLVMPointerType(LLVMInt8Type(), 0),