X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fstat%2Ffirmstat.c;h=2bef6616b2a6b2aac1544c21496c3a604414b5fb;hb=8428d50114020cce61e2fccae4e23244a99db918;hp=a6733d8c0204c74edd248996e8159d72a6282d52;hpb=5af0c3e521bf6375f0249b661605f9f5570c6e4e;p=libfirm diff --git a/ir/stat/firmstat.c b/ir/stat/firmstat.c index a6733d8c0..2bef6616b 100644 --- a/ir/stat/firmstat.c +++ b/ir/stat/firmstat.c @@ -1,14 +1,28 @@ /* - * Project: libFIRM - * File name: ir/ir/firmstat.c - * Purpose: Statistics for Firm. - * Author: Michael Beck - * Created: - * CVS-ID: $Id$ - * Copyright: (c) 2004 Universität Karlsruhe - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. */ +/** + * @file + * @brief Statistics for Firm. + * @author Michael Beck + * @version $Id$ + */ #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -122,6 +136,7 @@ static int block_cmp(const void *elt, const void *key) { const block_entry_t *e1 = elt; const block_entry_t *e2 = key; + /* it's enough to compare the block number */ return e1->block_nr != e2->block_nr; } /* block_cmp */ @@ -181,6 +196,7 @@ static int opcode_cmp_2(const void *elt, const void *key) { static int address_mark_cmp(const void *elt, const void *key, size_t size) { const address_mark_entry_t *e1 = elt; const address_mark_entry_t *e2 = key; + (void) size; /* compare only the nodes, the rest is used as data container */ return e1->node != e2->node; @@ -244,7 +260,7 @@ static ir_op *opcode_find_entry(ir_opcode code, hmap_ir_op *hmap) { static void graph_clear_entry(graph_entry_t *elem, int all) { int i; - /* clear accumulated / non-acumulated counter */ + /* clear accumulated / non-accumulated counter */ for (i = all ? 0 : _gcnt_non_acc; i < _gcnt_last; ++i) { cnt_clr(&elem->cnt[i]); } /* for */ @@ -273,7 +289,7 @@ static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap) { graph_entry_t key; graph_entry_t *elem; - int i; + size_t i; key.irg = irg; @@ -511,6 +527,15 @@ static perm_stat_entry_t *perm_stat_get_entry(struct obstack *obst, ir_node *per return pset_insert(hmap, elem, HASH_PTR(perm)); } /* perm_stat_get_entry */ +/** + * Clear optimizations counter, + */ +static void clear_optimization_counter(void) { + int i; + for (i = 0; i < FS_OPT_MAX; ++i) + cnt_clr(&status->num_opts[i]); +} + /** * Returns the ir_op for an IR-node, * handles special cases and return pseudo op codes. @@ -593,6 +618,11 @@ static void undate_block_info(ir_node *node, graph_entry_t *graph) if (op == op_Block) { arity = get_irn_arity(node); b_entry = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(node), graph->block_hash); + /* mark start end block to allow to filter them out */ + if (node == get_irg_start_block(graph->irg)) + b_entry->is_start = 1; + else if (node == get_irg_end_block(graph->irg)) + b_entry->is_end = 1; /* count all incoming edges */ for (i = 0; i < arity; ++i) { @@ -618,7 +648,7 @@ static void undate_block_info(ir_node *node, graph_entry_t *graph) cnt_inc(&b_entry->cnt[bcnt_nodes]); /* don't count keep-alive edges */ - if (get_irn_op(node) == op_End) + if (is_End(node)) return; arity = get_irn_arity(node); @@ -703,20 +733,41 @@ static void update_extbb_info(ir_node *node, graph_entry_t *graph) } /* for */ } /* update_extbb_info */ -/** Calculates how many arguments of the call are const. */ -static int cnt_const_args(ir_node *call) { - int i, res = 0; +/** + * Calculates how many arguments of the call are const, updates + * param distribution. + */ +static void analyse_params_of_Call(graph_entry_t *graph, ir_node *call) { + int i, num_const_args = 0, num_local_adr = 0; int n = get_Call_n_params(call); for (i = 0; i < n; ++i) { ir_node *param = get_Call_param(call, i); - ir_op *op = get_irn_op(param); - if (op == op_Const || op == op_SymConst) - ++res; + if (is_irn_constlike(param)) + ++num_const_args; + else if (is_Sel(param)) { + ir_node *base = param; + + do { + base = get_Sel_ptr(base); + } while (is_Sel(base)); + + if (base == get_irg_frame(current_ir_graph)) + ++num_local_adr; + } + } /* for */ - return res; -} /* cnt_const_args */ + + if (num_const_args > 0) + cnt_inc(&graph->cnt[gcnt_call_with_cnst_arg]); + if (num_const_args == n) + cnt_inc(&graph->cnt[gcnt_call_with_all_cnst_arg]); + if (num_local_adr > 0) + cnt_inc(&graph->cnt[gcnt_call_with_local_adr]); + + stat_inc_int_distrib_tbl(status->dist_param_cnt, n); +} /* analyse_params_of_Call */ /** * Update info on calls. @@ -730,7 +781,6 @@ static void stat_update_call(ir_node *call, graph_entry_t *graph) ir_node *ptr = get_Call_ptr(call); ir_entity *ent = NULL; ir_graph *callee = NULL; - int num_const_args; /* * If the block is bad, the whole subgraph will collapse later @@ -754,6 +804,8 @@ static void stat_update_call(ir_node *call, graph_entry_t *graph) /* it is recursive, if it calls at least once */ if (callee == graph->irg) graph->is_recursive = 1; + if (callee == NULL) + cnt_inc(&graph->cnt[gcnt_external_calls]); } /* if */ } else { /* indirect call, be could not predict */ @@ -764,7 +816,7 @@ static void stat_update_call(ir_node *call, graph_entry_t *graph) } /* if */ /* check, if it's a chain-call: Then, the call-block - * must dominate the end block. */ + * must dominate the end block. */ { ir_node *curr = get_irg_end_block(graph->irg); int depth = get_Block_dom_depth(block); @@ -790,11 +842,7 @@ static void stat_update_call(ir_node *call, graph_entry_t *graph) } /* if */ } /* if */ - /* check, if arguments of the call are const */ - num_const_args = cnt_const_args(call); - - if (num_const_args > 0) - cnt_inc(&graph->cnt[gcnt_call_with_cnst_arg]); + analyse_params_of_Call(graph, call); } /* stat_update_call */ /** @@ -1048,7 +1096,7 @@ static void mark_address_calc(ir_node *node, void *env) { int i, n; unsigned mark_preds = MARK_REF_NON_ADR; - if (! mode_is_numP(mode)) + if (! mode_is_data(mode)) return; if (mode_is_reference(mode)) { @@ -1073,7 +1121,7 @@ static void mark_address_calc(ir_node *node, void *env) { ir_node *pred = get_irn_n(node, i); mode = get_irn_op_mode(pred); - if (! mode_is_numP(mode)) + if (! mode_is_data(mode)) continue; set_adr_mark(graph, pred, get_adr_mark(graph, pred) | mark_preds); @@ -1215,6 +1263,7 @@ static void update_graph_stat(graph_entry_t *global, graph_entry_t *graph) */ static void update_graph_stat_2(graph_entry_t *global, graph_entry_t *graph) { + (void) global; if (graph->is_deleted) { /* deleted, ignore */ return; @@ -1286,6 +1335,30 @@ static void stat_dump_consts(const constant_info_t *tbl) { } /* for */ } /* stat_dump_consts */ +/** + * Dumps the parameter distribution + */ +static void stat_dump_param_tbl(const distrib_tbl_t *tbl, graph_entry_t *global) { + dumper_t *dumper; + + for (dumper = status->dumper; dumper; dumper = dumper->next) { + if (dumper->dump_param_tbl) + dumper->dump_param_tbl(dumper, tbl, global); + } /* for */ +} /* stat_dump_param_tbl */ + +/** + * Dumps the optimization counter + */ +static void stat_dump_opt_cnt(const counter_t *tbl, unsigned len) { + dumper_t *dumper; + + for (dumper = status->dumper; dumper; dumper = dumper->next) { + if (dumper->dump_opt_cnt) + dumper->dump_opt_cnt(dumper, tbl, len); + } /* for */ +} /* stat_dump_opt_cnt */ + /** * Initialize the dumper. */ @@ -1339,6 +1412,7 @@ ir_op *stat_get_op_from_opcode(ir_opcode code) { * @param op the new IR opcode that was created. */ static void stat_new_ir_op(void *ctx, ir_op *op) { + (void) ctx; if (! status->stat_options) return; @@ -1361,6 +1435,8 @@ static void stat_new_ir_op(void *ctx, ir_op *op) { * @param op the IR opcode that is freed */ static void stat_free_ir_op(void *ctx, ir_op *op) { + (void) ctx; + (void) op; if (! status->stat_options) return; @@ -1378,11 +1454,13 @@ static void stat_free_ir_op(void *ctx, ir_op *op) { * @param node the new IR node that was created */ static void stat_new_node(void *ctx, ir_graph *irg, ir_node *node) { + (void) ctx; + (void) irg; if (! status->stat_options) return; /* do NOT count during dead node elimination */ - if (status->in_dead_node_elim > 0) + if (status->in_dead_node_elim) return; STAT_ENTER; @@ -1411,6 +1489,7 @@ static void stat_new_node(void *ctx, ir_graph *irg, ir_node *node) { * @param node the IR node that will be turned into an ID */ static void stat_turn_into_id(void *ctx, ir_node *node) { + (void) ctx; if (! status->stat_options) return; @@ -1441,6 +1520,7 @@ static void stat_turn_into_id(void *ctx, ir_node *node) { * @param ent the entity of this graph */ static void stat_new_graph(void *ctx, ir_graph *irg, ir_entity *ent) { + (void) ctx; if (! status->stat_options) return; @@ -1471,6 +1551,7 @@ static void stat_new_graph(void *ctx, ir_graph *irg, ir_entity *ent) { * information from being changed, it's "frozen" from now. */ static void stat_free_graph(void *ctx, ir_graph *irg) { + (void) ctx; if (! status->stat_options) return; @@ -1499,6 +1580,9 @@ static void stat_free_graph(void *ctx, ir_graph *irg) { */ static void stat_irg_walk(void *ctx, ir_graph *irg, generic_func *pre, generic_func *post) { + (void) ctx; + (void) pre; + (void) post; if (! status->stat_options) return; @@ -1536,6 +1620,10 @@ static void stat_irg_walk_blkwise(void *ctx, ir_graph *irg, generic_func *pre, g */ static void stat_irg_block_walk(void *ctx, ir_graph *irg, ir_node *node, generic_func *pre, generic_func *post) { + (void) ctx; + (void) node; + (void) pre; + (void) post; if (! status->stat_options) return; @@ -1553,11 +1641,16 @@ static void stat_irg_block_walk(void *ctx, ir_graph *irg, ir_node *node, generic * * @param n the IR node that will be removed * @param hmap the hash map containing ir_op* -> opt_entry_t* + * @param kind the optimization kind */ -static void removed_due_opt(ir_node *n, hmap_opt_entry_t *hmap) { +static void removed_due_opt(ir_node *n, hmap_opt_entry_t *hmap, hook_opt_kind kind) { ir_op *op = stat_get_irn_op(n); opt_entry_t *entry = opt_get_entry(op, hmap); + /* ignore CSE for Constants */ + if (kind == HOOK_OPT_CSE && (is_Const(n) || is_SymConst(n))) + return; + /* increase global value */ cnt_inc(&entry->count); } /* removed_due_opt */ @@ -1573,6 +1666,7 @@ static void stat_merge_nodes( ir_node **old_node_array, int old_num_entries, hook_opt_kind opt) { + (void) ctx; if (! status->stat_options) return; @@ -1581,6 +1675,7 @@ static void stat_merge_nodes( int i, j; graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash); + cnt_inc(&status->num_opts[opt]); if (status->reassoc_run) opt = HOOK_OPT_REASSOC; @@ -1602,7 +1697,7 @@ static void stat_merge_nodes( xopt = HOOK_OPT_CONFIRM_C; } /* if */ - removed_due_opt(old_node_array[i], graph->opt_hash[xopt]); + removed_due_opt(old_node_array[i], graph->opt_hash[xopt], xopt); } /* if */ } /* for */ } @@ -1616,6 +1711,7 @@ static void stat_merge_nodes( * @param flag if non-zero, reassociation is started else stopped */ static void stat_reassociate(void *ctx, int flag) { + (void) ctx; if (! status->stat_options) return; @@ -1633,6 +1729,7 @@ static void stat_reassociate(void *ctx, int flag) { * @param node the IR node that will be lowered */ static void stat_lower(void *ctx, ir_node *node) { + (void) ctx; if (! status->stat_options) return; @@ -1640,7 +1737,7 @@ static void stat_lower(void *ctx, ir_node *node) { { graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash); - removed_due_opt(node, graph->opt_hash[HOOK_LOWERED]); + removed_due_opt(node, graph->opt_hash[HOOK_LOWERED], HOOK_LOWERED); } STAT_LEAVE; } /* stat_lower */ @@ -1655,6 +1752,7 @@ static void stat_lower(void *ctx, ir_node *node) { */ static void stat_inline(void *ctx, ir_node *call, ir_graph *called_irg) { + (void) ctx; if (! status->stat_options) return; @@ -1676,6 +1774,7 @@ static void stat_inline(void *ctx, ir_node *call, ir_graph *called_irg) * @param ctx the hook context */ static void stat_tail_rec(void *ctx, ir_graph *irg, int n_calls) { + (void) ctx; if (! status->stat_options) return; @@ -1694,6 +1793,7 @@ static void stat_tail_rec(void *ctx, ir_graph *irg, int n_calls) { * @param ctx the hook context */ static void stat_strength_red(void *ctx, ir_graph *irg, ir_node *strong) { + (void) ctx; if (! status->stat_options) return; @@ -1702,7 +1802,7 @@ static void stat_strength_red(void *ctx, ir_graph *irg, ir_node *strong) { graph_entry_t *graph = graph_get_entry(irg, status->irg_hash); cnt_inc(&graph->cnt[gcnt_acc_strength_red]); - removed_due_opt(strong, graph->opt_hash[HOOK_OPT_STRENGTH_RED]); + removed_due_opt(strong, graph->opt_hash[HOOK_OPT_STRENGTH_RED], HOOK_OPT_STRENGTH_RED); } STAT_LEAVE; } /* stat_strength_red */ @@ -1713,13 +1813,12 @@ static void stat_strength_red(void *ctx, ir_graph *irg, ir_node *strong) { * @param ctx the hook context */ static void stat_dead_node_elim(void *ctx, ir_graph *irg, int start) { + (void) ctx; + (void) irg; if (! status->stat_options) return; - if (start) - ++status->in_dead_node_elim; - else - --status->in_dead_node_elim; + status->in_dead_node_elim = (start != 0); } /* stat_dead_node_elim */ /** @@ -1728,6 +1827,10 @@ static void stat_dead_node_elim(void *ctx, ir_graph *irg, int start) { static void stat_if_conversion(void *context, ir_graph *irg, ir_node *phi, int pos, ir_node *mux, if_result_t reason) { + (void) context; + (void) phi; + (void) pos; + (void) mux; if (! status->stat_options) return; @@ -1745,6 +1848,8 @@ static void stat_if_conversion(void *context, ir_graph *irg, ir_node *phi, */ static void stat_func_call(void *context, ir_graph *irg, ir_node *call) { + (void) context; + (void) call; if (! status->stat_options) return; @@ -1763,13 +1868,14 @@ static void stat_func_call(void *context, ir_graph *irg, ir_node *call) * @param ctx the hook context */ static void stat_arch_dep_replace_mul_with_shifts(void *ctx, ir_node *mul) { + (void) ctx; if (! status->stat_options) return; STAT_ENTER; { graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash); - removed_due_opt(mul, graph->opt_hash[HOOK_OPT_ARCH_DEP]); + removed_due_opt(mul, graph->opt_hash[HOOK_OPT_ARCH_DEP], HOOK_OPT_ARCH_DEP); } STAT_LEAVE; } /* stat_arch_dep_replace_mul_with_shifts */ @@ -1781,13 +1887,14 @@ static void stat_arch_dep_replace_mul_with_shifts(void *ctx, ir_node *mul) { * @param node the division node that will be optimized */ static void stat_arch_dep_replace_division_by_const(void *ctx, ir_node *node) { + (void) ctx; if (! status->stat_options) return; STAT_ENTER; { graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash); - removed_due_opt(node, graph->opt_hash[HOOK_OPT_ARCH_DEP]); + removed_due_opt(node, graph->opt_hash[HOOK_OPT_ARCH_DEP], HOOK_OPT_ARCH_DEP); } STAT_LEAVE; } /* stat_arch_dep_replace_division_by_const */ @@ -1962,7 +2069,7 @@ void stat_dump_snapshot(const char *name, const char *phase) ++p; l = p - name; - if (l > sizeof(fname) - 1) + if (l > (int) (sizeof(fname) - 1)) l = sizeof(fname) - 1; memcpy(fname, name, l); @@ -2022,6 +2129,13 @@ void stat_dump_snapshot(const char *name, const char *phase) if (status->stat_options & FIRMSTAT_COUNT_CONSTS) stat_dump_consts(&status->const_info); + /* dump the parameter distribution */ + stat_dump_param_tbl(status->dist_param_cnt, global); + + /* dump the optimization counter and clear them */ + stat_dump_opt_cnt(status->num_opts, ARR_SIZE(status->num_opts)); + clear_optimization_counter(); + stat_dump_finish(); stat_finish_pattern_history(fname); @@ -2161,6 +2275,11 @@ void firm_init_stat(unsigned enable_options) if (enable_options & FIRMSTAT_COUNT_CONSTS) stat_init_const_cnt(status); + /* distribution table for parameter counts */ + status->dist_param_cnt = stat_new_int_distrib_tbl(); + + clear_optimization_counter(); + #undef HOOK #undef X } /* firm_init_stat */