X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fstat%2Ffirmstat.c;h=530bec4ebc58d16cb4053b81ab63a55c6f67c7cf;hb=6a768b09064c37b361871ba888213cdd5ed5a700;hp=7397ab62bd84db4a08525f342008bea5e58c5d0e;hpb=c2803027e50766db5a7ed2c27650a4e0cc5e8311;p=libfirm diff --git a/ir/stat/firmstat.c b/ir/stat/firmstat.c index 7397ab62b..530bec4eb 100644 --- a/ir/stat/firmstat.c +++ b/ir/stat/firmstat.c @@ -119,7 +119,7 @@ static int opt_cmp(const void *elt, const void *key) } /** - * compare two elements of the block hash + * compare two elements of the block/extbb hash */ static int block_cmp(const void *elt, const void *key) { @@ -221,6 +221,19 @@ static void graph_clear_entry(graph_entry_t *elem, int all) cnt_clr(&elem->cnt_all_calls); cnt_clr(&elem->cnt_call_with_cnst_arg); cnt_clr(&elem->cnt_indirect_calls); + + if (elem->block_hash) { + del_pset(elem->block_hash); + elem->block_hash = NULL; + } + + if (elem->extbb_hash) { + del_pset(elem->extbb_hash); + elem->extbb_hash = NULL; + } + + obstack_free(&elem->recalc_cnts, NULL); + obstack_init(&elem->recalc_cnts); } /** @@ -244,16 +257,20 @@ static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap) /* allocate a new one */ elem = obstack_alloc(&status->cnts, sizeof(*elem)); memset(elem, 0, sizeof(*elem)); + obstack_init(&elem->recalc_cnts); /* clear counter */ graph_clear_entry(elem, 1); /* new hash table for opcodes here */ elem->opcode_hash = new_pset(opcode_cmp, 5); - elem->block_hash = new_pset(block_cmp, 5); elem->address_mark = new_set(address_mark_cmp, 5); elem->irg = irg; + /* these hash tables are created on demand */ + elem->block_hash = NULL; + elem->extbb_hash = NULL; + for (i = 0; i < sizeof(elem->opt_hash)/sizeof(elem->opt_hash[0]); ++i) elem->opt_hash[i] = new_pset(opt_cmp, 4); @@ -314,7 +331,7 @@ static void block_clear_entry(block_entry_t *elem) * @param block_nr an IR block number * @param hmap a hash map containing long -> block_entry_t */ -static block_entry_t *block_get_entry(long block_nr, hmap_block_entry_t *hmap) +static block_entry_t *block_get_entry(struct obstack *obst, long block_nr, hmap_block_entry_t *hmap) { block_entry_t key; block_entry_t *elem; @@ -325,7 +342,7 @@ static block_entry_t *block_get_entry(long block_nr, hmap_block_entry_t *hmap) if (elem) return elem; - elem = obstack_alloc(&status->cnts, sizeof(*elem)); + elem = obstack_alloc(obst, sizeof(*elem)); memset(elem, 0, sizeof(*elem)); /* clear new counter */ @@ -402,48 +419,47 @@ static void undate_block_info(ir_node *node, graph_entry_t *graph) /* check for block */ if (op == op_Block) { arity = get_irn_arity(node); - b_entry = block_get_entry(get_irn_node_nr(node), graph->block_hash); + b_entry = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(node), graph->block_hash); /* count all incoming edges */ for (i = 0; i < arity; ++i) { ir_node *pred = get_irn_n(node, i); ir_node *other_block = get_nodes_block(pred); - block_entry_t *b_entry_other = block_get_entry(get_irn_node_nr(other_block), graph->block_hash); + block_entry_t *b_entry_other = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(other_block), graph->block_hash); cnt_inc(&b_entry->cnt_in_edges); /* an edge coming from another block */ cnt_inc(&b_entry_other->cnt_out_edges); } return; } - else if (op == op_Phi && mode_is_datab(get_irn_mode(node))) { - /* count data Phi */ - ir_node *block = get_nodes_block(node); - block_entry_t *b_entry = block_get_entry(get_irn_node_nr(block), graph->block_hash); + block = get_nodes_block(node); + b_entry = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(block), graph->block_hash); + + if (op == op_Phi && mode_is_datab(get_irn_mode(node))) { + /* count data Phi per block */ cnt_inc(&b_entry->cnt_phi_data); } - block = get_nodes_block(node); - b_entry = block_get_entry(get_irn_node_nr(block), graph->block_hash); - - /* we have a new nodes */ + /* we have a new node in our block */ cnt_inc(&b_entry->cnt_nodes); + /* don't count keep-alive edges */ + if (get_irn_op(node) == op_End) + return; + arity = get_irn_arity(node); for (i = 0; i < arity; ++i) { ir_node *pred = get_irn_n(node, i); ir_node *other_block; - if (get_irn_op(pred) == op_Block) - continue; - other_block = get_nodes_block(pred); if (other_block == block) cnt_inc(&b_entry->cnt_edges); /* a in block edge */ else { - block_entry_t *b_entry_other = block_get_entry(get_irn_node_nr(other_block), graph->block_hash); + block_entry_t *b_entry_other = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(other_block), graph->block_hash); cnt_inc(&b_entry->cnt_in_edges); /* an edge coming from another block */ cnt_inc(&b_entry_other->cnt_out_edges); @@ -451,6 +467,69 @@ static void undate_block_info(ir_node *node, graph_entry_t *graph) } } +/** + * update the extended block counter + */ +static void undate_extbb_info(ir_node *node, graph_entry_t *graph) +{ + ir_op *op = get_irn_op(node); + ir_extblk *extbb; + extbb_entry_t *eb_entry; + int i, arity; + + /* check for block */ + if (op == op_Block) { + extbb = get_nodes_extbb(node); + arity = get_irn_arity(node); + eb_entry = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(extbb), graph->extbb_hash); + + /* count all incoming edges */ + for (i = 0; i < arity; ++i) { + ir_node *pred = get_irn_n(node, i); + ir_extblk *other_extbb = get_nodes_extbb(pred); + + if (extbb != other_extbb) { + extbb_entry_t *eb_entry_other = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(other_extbb), graph->extbb_hash); + + cnt_inc(&eb_entry->cnt_in_edges); /* an edge coming from another extbb */ + cnt_inc(&eb_entry_other->cnt_out_edges); + } + } + return; + } + + extbb = get_nodes_extbb(node); + eb_entry = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(extbb), graph->extbb_hash); + + if (op == op_Phi && mode_is_datab(get_irn_mode(node))) { + /* count data Phi per extbb */ + cnt_inc(&eb_entry->cnt_phi_data); + } + + /* we have a new node in our block */ + cnt_inc(&eb_entry->cnt_nodes); + + /* don't count keep-alive edges */ + if (get_irn_op(node) == op_End) + return; + + arity = get_irn_arity(node); + + for (i = 0; i < arity; ++i) { + ir_node *pred = get_irn_n(node, i); + ir_extblk *other_extbb = get_nodes_extbb(pred); + + if (other_extbb == extbb) + cnt_inc(&eb_entry->cnt_edges); /* a in extbb edge */ + else { + extbb_entry_t *eb_entry_other = block_get_entry(&graph->recalc_cnts, get_extbb_node_nr(other_extbb), graph->extbb_hash); + + cnt_inc(&eb_entry->cnt_in_edges); /* an edge coming from another extbb */ + cnt_inc(&eb_entry_other->cnt_out_edges); + } + } +} + /** calculates how many arguments of the call are const */ static int cnt_const_args(ir_node *call) { @@ -605,6 +684,11 @@ static void update_node_stat(ir_node *node, void *env) /* count block edges */ undate_block_info(node, graph); + /* count extended block edges */ + if (status->stat_options & FIRMSTAT_COUNT_EXTBB) { + undate_extbb_info(node, graph); + } + /* handle statistics for special node types */ if (op == op_Const) { @@ -741,15 +825,27 @@ static void update_graph_stat(graph_entry_t *global, graph_entry_t *graph) graph->is_recursive = 0; graph->is_chain_call = 1; + /* create new block counter */ + graph->block_hash = new_pset(block_cmp, 5); + /* we need dominator info */ if (graph->irg != get_const_code_irg()) if (get_irg_dom_state(graph->irg) != dom_consistent) compute_doms(graph->irg); + if (status->stat_options & FIRMSTAT_COUNT_EXTBB) { + /* we need extended basic blocks */ + compute_extbb(graph->irg); + + /* create new extbb counter */ + graph->extbb_hash = new_pset(block_cmp, 5); + } + /* count the nodes in the graph */ irg_walk_graph(graph->irg, update_node_stat, NULL, graph); #if 0 + /* Uncomment this code if chain-call means call exact one */ entry = opcode_get_entry(op_Call, graph->opcode_hash); /* check if we have more than 1 call */ @@ -777,7 +873,7 @@ static void update_graph_stat(graph_entry_t *global, graph_entry_t *graph) ir_graph *rem = current_ir_graph; if (get_irg_outs_state(graph->irg) != outs_consistent) - compute_outs(graph->irg); + compute_irg_outs(graph->irg); /* Must be done an the outs graph */ current_ir_graph = graph->irg; @@ -1084,7 +1180,7 @@ static void stat_free_graph(void *ctx, ir_graph *irg) * @param pre the pre walker * @param post the post walker */ -static void stat_irg_walk(void *ctx, ir_graph *irg, void *pre, void *post) +static void stat_irg_walk(void *ctx, ir_graph *irg, generic_func *pre, generic_func *post) { if (! status->stat_options) return; @@ -1106,7 +1202,7 @@ static void stat_irg_walk(void *ctx, ir_graph *irg, void *pre, void *post) * @param pre the pre walker * @param post the post walker */ -static void stat_irg_walk_blkwise(void *ctx, ir_graph *irg, void *pre, void *post) +static void stat_irg_walk_blkwise(void *ctx, ir_graph *irg, generic_func *pre, generic_func *post) { /* for now, do NOT differentiate between blockwise and normal */ stat_irg_walk(ctx, irg, pre, post); @@ -1121,7 +1217,7 @@ static void stat_irg_walk_blkwise(void *ctx, ir_graph *irg, void *pre, void *pos * @param pre the pre walker * @param post the post walker */ -static void stat_irg_block_walk(void *ctx, ir_graph *irg, ir_node *node, void *pre, void *post) +static void stat_irg_block_walk(void *ctx, ir_graph *irg, ir_node *node, generic_func *pre, generic_func *post) { if (! status->stat_options) return; @@ -1179,7 +1275,17 @@ static void stat_merge_nodes( /* nodes might be in new and old, these are NOT removed */ if (j >= new_num_entries) { - removed_due_opt(old_node_array[i], graph->opt_hash[opt]); + int xopt = opt; + + /* sometimes we did not detect, that it is replaced by a Const */ + if (opt == HOOK_OPT_CONFIRM && new_num_entries == 1) { + ir_op *op = get_irn_op(new_node_array[0]); + + if (op == op_Const || op == op_SymConst) + xopt = HOOK_OPT_CONFIRM_C; + } + + removed_due_opt(old_node_array[i], graph->opt_hash[xopt]); } } } @@ -1289,29 +1395,19 @@ static void stat_strength_red(void *ctx, ir_graph *irg, ir_node *strong, ir_node } /** - * Start the dead node elimination. + * Start/Stop the dead node elimination. * * @param ctx the hook context */ -static void stat_dead_node_elim_start(void *ctx, ir_graph *irg) +static void stat_dead_node_elim(void *ctx, ir_graph *irg, int start) { if (! status->stat_options) return; - ++status->in_dead_node_elim; -} - -/** - * Stops the dead node elimination. - * - * @param ctx the hook context - */ -static void stat_dead_node_elim_stop(void *ctx, ir_graph *irg) -{ - if (! status->stat_options) - return; - - --status->in_dead_node_elim; + if (start) + ++status->in_dead_node_elim; + else + --status->in_dead_node_elim; } /** @@ -1368,50 +1464,12 @@ static void stat_arch_dep_replace_mul_with_shifts(void *ctx, ir_node *mul) } /** - * A division was replaced by a series of Shifts/Muls - * - * @param ctx the hook context - * @param div the div node that will be optimized - */ -static void stat_arch_dep_replace_div_by_const(void *ctx, ir_node *div) -{ - if (! status->stat_options) - return; - - STAT_ENTER; - { - graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash); - removed_due_opt(div, graph->opt_hash[HOOK_OPT_ARCH_DEP]); - } - STAT_LEAVE; -} - -/** - * A modulo was replaced by a series of Shifts/Muls - * - * @param ctx the hook context - * @param mod the mod node that will be optimized - */ -static void stat_arch_dep_replace_mod_by_const(void *ctx, ir_node *mod) -{ - if (! status->stat_options) - return; - - STAT_ENTER; - { - graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash); - removed_due_opt(mod, graph->opt_hash[HOOK_OPT_ARCH_DEP]); - } - STAT_LEAVE; -} - -/** - * A DivMod was replaced by a series of Shifts/Muls + * A division by const was replaced * - * @param ctx the hook context - * @param divmod the divmod node that will be optimized + * @param ctx the hook context + * @param node the division node that will be optimized */ -static void stat_arch_dep_replace_DivMod_by_const(void *ctx, ir_node *divmod) +static void stat_arch_dep_replace_division_by_const(void *ctx, ir_node *node) { if (! status->stat_options) return; @@ -1419,14 +1477,18 @@ static void stat_arch_dep_replace_DivMod_by_const(void *ctx, ir_node *divmod) STAT_ENTER; { graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash); - removed_due_opt(divmod, graph->opt_hash[HOOK_OPT_ARCH_DEP]); + removed_due_opt(node, graph->opt_hash[HOOK_OPT_ARCH_DEP]); } STAT_LEAVE; } /* Dumps a statistics snapshot */ -void stat_dump_snapshot(const char *name) +void stat_dump_snapshot(const char *name, const char *phase) { + char fname[2048]; + const char *p; + int l; + if (! status->stat_options) return; @@ -1437,13 +1499,45 @@ void stat_dump_snapshot(const char *name) /* * The constant counter is only global, so we clear it here. - * Note that it does NOT contain teh constants in DELETED + * Note that it does NOT contain the constants in DELETED * graphs due to this. */ if (status->stat_options & FIRMSTAT_COUNT_CONSTS) stat_const_clear(status); - stat_dump_init(name); + /* build the name */ + p = strrchr(name, '/'); +#ifdef _WIN32 + { + const char *q; + + q = strrchr(name, '\\'); + + /* NULL might be not the smallest pointer */ + if (q && (!p || q > p)) + p = q; + } +#endif + if (p) { + ++p; + l = p - name; + + if (l > sizeof(fname) - 1) + l = sizeof(fname) - 1; + + memcpy(fname, name, l); + fname[l] = '\0'; + } + else { + fname[0] = '\0'; + p = name; + } + strncat(fname, "firmstat-", sizeof(fname)); + strncat(fname, phase, sizeof(fname)); + strncat(fname, "-", sizeof(fname)); + strncat(fname, p, sizeof(fname)); + + stat_dump_init(fname); /* calculate the graph statistics */ for (entry = pset_first(status->irg_hash); entry; entry = pset_next(status->irg_hash)) { @@ -1475,8 +1569,9 @@ void stat_dump_snapshot(const char *name) continue; } - if (! entry->is_deleted || status->stat_options & FIRMSTAT_COUNT_DELETED) + if (! entry->is_deleted || status->stat_options & FIRMSTAT_COUNT_DELETED) { stat_dump_graph(entry); + } if (! entry->is_deleted) { /* clear the counter that are not accumulated */ @@ -1529,29 +1624,26 @@ void init_stat(unsigned enable_options) status->stat_options = enable_options & FIRMSTAT_ENABLED ? enable_options : 0; /* register all hooks */ - HOOK(hook_new_ir_op, stat_new_ir_op); - HOOK(hook_free_ir_op, stat_free_ir_op); - HOOK(hook_new_node, stat_new_node); - HOOK(hook_turn_into_id, stat_turn_into_id); - HOOK(hook_new_graph, stat_new_graph); - HOOK(hook_free_graph, stat_free_graph); - HOOK(hook_irg_walk, stat_irg_walk); - HOOK(hook_irg_walk_blkwise, stat_irg_walk_blkwise); - HOOK(hook_irg_block_walk, stat_irg_block_walk); - HOOK(hook_merge_nodes, stat_merge_nodes); - HOOK(hook_reassociate, stat_reassociate); - HOOK(hook_lower, stat_lower); - HOOK(hook_inline, stat_inline); - HOOK(hook_tail_rec, stat_tail_rec); - HOOK(hook_strength_red, stat_strength_red); - HOOK(hook_dead_node_elim_start, stat_dead_node_elim_start); - HOOK(hook_dead_node_elim_stop, stat_dead_node_elim_stop); - HOOK(hook_if_conversion, stat_if_conversion); - HOOK(hook_func_call, stat_func_call); - HOOK(hook_arch_dep_replace_mul_with_shifts, stat_arch_dep_replace_mul_with_shifts); - HOOK(hook_arch_dep_replace_div_by_const, stat_arch_dep_replace_div_by_const); - HOOK(hook_arch_dep_replace_mod_by_const, stat_arch_dep_replace_mod_by_const); - HOOK(hook_arch_dep_replace_DivMod_by_const, stat_arch_dep_replace_DivMod_by_const); + HOOK(hook_new_ir_op, stat_new_ir_op); + HOOK(hook_free_ir_op, stat_free_ir_op); + HOOK(hook_new_node, stat_new_node); + HOOK(hook_turn_into_id, stat_turn_into_id); + HOOK(hook_new_graph, stat_new_graph); + HOOK(hook_free_graph, stat_free_graph); + HOOK(hook_irg_walk, stat_irg_walk); + HOOK(hook_irg_walk_blkwise, stat_irg_walk_blkwise); + HOOK(hook_irg_block_walk, stat_irg_block_walk); + HOOK(hook_merge_nodes, stat_merge_nodes); + HOOK(hook_reassociate, stat_reassociate); + HOOK(hook_lower, stat_lower); + HOOK(hook_inline, stat_inline); + HOOK(hook_tail_rec, stat_tail_rec); + HOOK(hook_strength_red, stat_strength_red); + HOOK(hook_dead_node_elim, stat_dead_node_elim); + HOOK(hook_if_conversion, stat_if_conversion); + HOOK(hook_func_call, stat_func_call); + HOOK(hook_arch_dep_replace_mul_with_shifts, stat_arch_dep_replace_mul_with_shifts); + HOOK(hook_arch_dep_replace_division_by_const, stat_arch_dep_replace_division_by_const); obstack_init(&status->cnts); @@ -1649,9 +1741,9 @@ void stat_term(void) { void init_stat(unsigned enable_options) {} /* Dumps a statistics snapshot */ -void stat_dump_snapshot(const char *name) {} +void stat_dump_snapshot(const char *name, const char *phase) {} -/* terminates the statustics module, frees all memory */ +/* terminates the statistics module, frees all memory */ void stat_term(void); #endif /* FIRM_STATISTICS */