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 {...@@ -972,6 +972,7 @@ struct FnTableEntry {
972 bool is_inline;972 bool is_inline;
973 bool internal_linkage;973 bool internal_linkage;
974 bool is_extern;974 bool is_extern;
975 uint32_t ref_count; // if this is 0 we don't have to codegen it
975976
976 // reminder: hash tables must be initialized before use977 // reminder: hash tables must be initialized before use
977 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;978 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
...@@ -1000,6 +1001,7 @@ struct BuiltinFnEntry {...@@ -1000,6 +1001,7 @@ struct BuiltinFnEntry {
1000 int param_count;1001 int param_count;
1001 TypeTableEntry *return_type;1002 TypeTableEntry *return_type;
1002 TypeTableEntry **param_types;1003 TypeTableEntry **param_types;
1004 uint32_t ref_count;
1003 LLVMValueRef fn_val;1005 LLVMValueRef fn_val;
1004};1006};
10051007
src/analyze.cpp+6
...@@ -1123,6 +1123,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -1123,6 +1123,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
1123 fn_table_entry->is_extern = is_extern;1123 fn_table_entry->is_extern = is_extern;
1124 fn_table_entry->label_table.init(8);1124 fn_table_entry->label_table.init(8);
1125 fn_table_entry->member_of_struct = struct_type;1125 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
1127 if (struct_type) {1128 if (struct_type) {
1128 buf_resize(&fn_table_entry->symbol_name, 0);1129 buf_resize(&fn_table_entry->symbol_name, 0);
...@@ -2244,6 +2245,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode...@@ -2244,6 +2245,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode
2244}2245}
22452246
2246static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {2247static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
2248 fn->ref_count += 1;
2247 Expr *expr = get_resolved_expr(node);2249 Expr *expr = get_resolved_expr(node);
2248 expr->const_val.ok = true;2250 expr->const_val.ok = true;
2249 expr->const_val.data.x_fn = fn;2251 expr->const_val.data.x_fn = fn;
...@@ -3658,6 +3660,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -3658,6 +3660,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
3658 return g->builtin_types.entry_invalid;3660 return g->builtin_types.entry_invalid;
3659 }3661 }
36603662
3663 builtin_fn->ref_count += 1;
3664
3661 switch (builtin_fn->id) {3665 switch (builtin_fn->id) {
3662 case BuiltinFnIdInvalid:3666 case BuiltinFnIdInvalid:
3663 zig_unreachable();3667 zig_unreachable();
...@@ -3913,6 +3917,8 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,...@@ -3913,6 +3917,8 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
39133917
3914 node->data.fn_call_expr.fn_entry = fn_table_entry;3918 node->data.fn_call_expr.fn_entry = fn_table_entry;
39153919
3920 fn_table_entry->ref_count += 1;
3921
3916 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);3922 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
39173923
3918}3924}
src/codegen.cpp+32
...@@ -2582,9 +2582,28 @@ static void gen_const_globals(CodeGen *g) {...@@ -2582,9 +2582,28 @@ static void gen_const_globals(CodeGen *g) {
2582 }2582 }
2583}2583}
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
2585static void do_code_gen(CodeGen *g) {2601static void do_code_gen(CodeGen *g) {
2586 assert(!g->errors.length);2602 assert(!g->errors.length);
25872603
2604 delete_unused_builtin_fns(g);
2605
2606
2588 gen_const_globals(g);2607 gen_const_globals(g);
25892608
2590 // Generate module level variables2609 // Generate module level variables
...@@ -2633,6 +2652,12 @@ static void do_code_gen(CodeGen *g) {...@@ -2633,6 +2652,12 @@ static void do_code_gen(CodeGen *g) {
2633 // Generate function prototypes2652 // Generate function prototypes
2634 for (int fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {2653 for (int fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {
2635 FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i);2654 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
2636 AstNode *proto_node = fn_table_entry->proto_node;2661 AstNode *proto_node = fn_table_entry->proto_node;
2637 assert(proto_node->type == NodeTypeFnProto);2662 assert(proto_node->type == NodeTypeFnProto);
2638 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;2663 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
...@@ -2681,6 +2706,11 @@ static void do_code_gen(CodeGen *g) {...@@ -2681,6 +2706,11 @@ static void do_code_gen(CodeGen *g) {
2681 // Generate function definitions.2706 // Generate function definitions.
2682 for (int fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {2707 for (int fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) {
2683 FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i);2708 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
2684 ImportTableEntry *import = fn_table_entry->import_entry;2714 ImportTableEntry *import = fn_table_entry->import_entry;
2685 AstNode *fn_def_node = fn_table_entry->fn_def_node;2715 AstNode *fn_def_node = fn_table_entry->fn_def_node;
2686 LLVMValueRef fn = fn_table_entry->fn_value;2716 LLVMValueRef fn = fn_table_entry->fn_value;
...@@ -3064,6 +3094,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -3064,6 +3094,7 @@ static void define_builtin_fns(CodeGen *g) {
3064 builtin_fn->param_types[0] = nullptr; // manually checked later3094 builtin_fn->param_types[0] = nullptr; // manually checked later
3065 builtin_fn->param_types[1] = nullptr; // manually checked later3095 builtin_fn->param_types[1] = nullptr; // manually checked later
3066 builtin_fn->param_types[2] = g->builtin_types.entry_isize;3096 builtin_fn->param_types[2] = g->builtin_types.entry_isize;
3097 builtin_fn->ref_count = 1;
30673098
3068 LLVMTypeRef param_types[] = {3099 LLVMTypeRef param_types[] = {
3069 LLVMPointerType(LLVMInt8Type(), 0),3100 LLVMPointerType(LLVMInt8Type(), 0),
...@@ -3087,6 +3118,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -3087,6 +3118,7 @@ static void define_builtin_fns(CodeGen *g) {
3087 builtin_fn->param_types[0] = nullptr; // manually checked later3118 builtin_fn->param_types[0] = nullptr; // manually checked later
3088 builtin_fn->param_types[1] = g->builtin_types.entry_u8;3119 builtin_fn->param_types[1] = g->builtin_types.entry_u8;
3089 builtin_fn->param_types[2] = g->builtin_types.entry_isize;3120 builtin_fn->param_types[2] = g->builtin_types.entry_isize;
3121 builtin_fn->ref_count = 1;
30903122
3091 LLVMTypeRef param_types[] = {3123 LLVMTypeRef param_types[] = {
3092 LLVMPointerType(LLVMInt8Type(), 0),3124 LLVMPointerType(LLVMInt8Type(), 0),