X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fstat%2Ffirmstat.c;h=55f61937ca35cf8c7ffab60dc35e7adae6e3d5f6;hb=00ac040bae07059a0dc7ed804c424702a1fcaa36;hp=bd2fcbb5644b79dfad97ade68bcd74af0ef2530d;hpb=5995f50798657ea4237af8cb725e9a6995991e9c;p=libfirm diff --git a/ir/stat/firmstat.c b/ir/stat/firmstat.c index bd2fcbb56..55f61937c 100644 --- a/ir/stat/firmstat.c +++ b/ir/stat/firmstat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -23,9 +23,7 @@ * @author Michael Beck * @version $Id$ */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include "config.h" #ifdef FIRM_STATISTICS @@ -73,6 +71,9 @@ static ir_op _op_ModC; /** The Div by Const node. */ static ir_op _op_DivModC; +/** The Quot by Const node. */ +static ir_op _op_QuotC; + /** The memory Proj node. */ static ir_op _op_ProjM; @@ -96,7 +97,7 @@ static ir_op _op_SelSelSel; /** * global status */ -static const int status_disable = 0; +static const unsigned status_disable = 0; static stat_info_t *status = (stat_info_t *)&status_disable; /** @@ -136,6 +137,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 */ @@ -208,6 +210,7 @@ static void opcode_clear_entry(node_entry_t *elem) { cnt_clr(&elem->cnt_alive); cnt_clr(&elem->new_node); cnt_clr(&elem->into_Id); + cnt_clr(&elem->normalized); } /* opcode_clear_entry */ /** @@ -259,7 +262,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 */ @@ -563,34 +566,40 @@ static ir_op *stat_get_irn_op(ir_node *node) } /* if */ break; case iro_Mul: - if (get_irn_op(get_Mul_left(node)) == op_Const || get_irn_op(get_Mul_right(node)) == op_Const) { + if (is_Const(get_Mul_left(node)) || is_Const(get_Mul_right(node))) { /* special case, a Multiply by a const, count on extra counter */ op = status->op_MulC ? status->op_MulC : op; } /* if */ break; case iro_Div: - if (get_irn_op(get_Div_right(node)) == op_Const) { + if (is_Const(get_Div_right(node))) { /* special case, a division by a const, count on extra counter */ op = status->op_DivC ? status->op_DivC : op; } /* if */ break; case iro_Mod: - if (get_irn_op(get_Mod_right(node)) == op_Const) { + if (is_Const(get_Mod_right(node))) { /* special case, a module by a const, count on extra counter */ op = status->op_ModC ? status->op_ModC : op; } /* if */ break; case iro_DivMod: - if (get_irn_op(get_DivMod_right(node)) == op_Const) { + if (is_Const(get_DivMod_right(node))) { /* special case, a division/modulo by a const, count on extra counter */ op = status->op_DivModC ? status->op_DivModC : op; } /* if */ break; + case iro_Quot: + if (is_Const(get_Quot_right(node))) { + /* special case, a floating point division by a const, count on extra counter */ + op = status->op_QuotC ? status->op_QuotC : op; + } /* if */ + break; case iro_Sel: - if (get_irn_op(get_Sel_ptr(node)) == op_Sel) { + if (is_Sel(get_Sel_ptr(node))) { /* special case, a Sel of a Sel, count on extra counter */ op = status->op_SelSel ? status->op_SelSel : op; - if (get_irn_op(get_Sel_ptr(get_Sel_ptr(node))) == op_Sel) { + if (is_Sel(get_Sel_ptr(get_Sel_ptr(node)))) { /* special case, a Sel of a Sel of a Sel, count on extra counter */ op = status->op_SelSelSel ? status->op_SelSelSel : op; } /* if */ @@ -617,6 +626,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) { @@ -642,7 +656,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); @@ -707,7 +721,7 @@ static void update_extbb_info(ir_node *node, graph_entry_t *graph) cnt_inc(&eb_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); @@ -789,7 +803,7 @@ static void stat_update_call(ir_node *call, graph_entry_t *graph) /* found a call, this function is not a leaf */ graph->is_leaf = 0; - if (get_irn_op(ptr) == op_SymConst) { + if (is_SymConst(ptr)) { if (get_SymConst_kind(ptr) == symconst_addr_ent) { /* ok, we seems to know the entity */ ent = get_SymConst_entity(ptr); @@ -798,6 +812,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 */ @@ -808,7 +824,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); @@ -855,7 +871,7 @@ static void stat_update_call_2(ir_node *call, graph_entry_t *graph) if (is_Bad(block)) return; - if (get_irn_op(ptr) == op_SymConst) { + if (is_SymConst(ptr)) { if (get_SymConst_kind(ptr) == symconst_addr_ent) { /* ok, we seems to know the entity */ ent = get_SymConst_entity(ptr); @@ -953,7 +969,7 @@ static void update_node_stat(ir_node *node, void *env) node_entry_t *entry; ir_op *op = stat_get_irn_op(node); - int arity = get_irn_arity(node); + int i, arity = get_irn_arity(node); entry = opcode_get_entry(op, graph->opcode_hash); @@ -972,12 +988,6 @@ static void update_node_stat(ir_node *node, void *env) /* handle statistics for special node types */ switch (op->code) { - case iro_Const: - if (status->stat_options & FIRMSTAT_COUNT_CONSTS) { - /* check properties of constants */ - stat_update_const(status, node, graph); - } /* if */ - break; case iro_Call: /* check for properties that depends on calls like recursion/leaf/indirect call */ stat_update_call(node, graph); @@ -990,9 +1000,33 @@ static void update_node_stat(ir_node *node, void *env) /* check address properties */ stat_update_address(get_Store_ptr(node), graph); break; + case iro_Phi: + /* check for non-strict Phi nodes */ + for (i = arity - 1; i >= 0; --i) { + ir_node *pred = get_Phi_pred(node, i); + if (is_Unknown(pred)) { + /* found an Unknown predecessor, graph is not strict */ + graph->is_strict = 0; + break; + } + } default: ; } /* switch */ + + /* we want to count the constant IN nodes, not the CSE'ed constant's itself */ + if (status->stat_options & FIRMSTAT_COUNT_CONSTS) { + int i; + + for (i = get_irn_arity(node) - 1; i >= 0; --i) { + ir_node *pred = get_irn_n(node, i); + + if (is_Const(pred)) { + /* check properties of constants */ + stat_update_const(status, pred, graph); + } /* if */ + } /* for */ + } /* if */ } /* update_node_stat */ /** @@ -1161,6 +1195,7 @@ static void update_graph_stat(graph_entry_t *global, graph_entry_t *graph) graph->is_leaf_call = LCS_UNKNOWN; graph->is_recursive = 0; graph->is_chain_call = 1; + graph->is_strict = 1; /* create new block counter */ graph->block_hash = new_pset(block_cmp, 5); @@ -1274,15 +1309,13 @@ static void update_graph_stat_2(graph_entry_t *global, graph_entry_t *graph) * Register a dumper. */ static void stat_register_dumper(const dumper_t *dumper) { - dumper_t *p = xmalloc(sizeof(*p)); + dumper_t *p = XMALLOC(dumper_t); - if (p) { - memcpy(p, dumper, sizeof(*p)); + memcpy(p, dumper, sizeof(*p)); - p->next = status->dumper; - p->status = status; - status->dumper = p; - } + p->next = status->dumper; + p->status = status; + status->dumper = p; /* FIXME: memory leak */ } /* stat_register_dumper */ @@ -1504,6 +1537,36 @@ static void stat_turn_into_id(void *ctx, ir_node *node) { STAT_LEAVE; } /* stat_turn_into_id */ +/** + * Hook: A node is normalized + * + * @param ctx the hook context + * @param node the IR node that was normalized + */ +static void stat_normalize(void *ctx, ir_node *node) { + (void) ctx; + if (! status->stat_options) + return; + + STAT_ENTER; + { + node_entry_t *entry; + graph_entry_t *graph; + ir_op *op = stat_get_irn_op(node); + + /* increase global value */ + graph = graph_get_entry(NULL, status->irg_hash); + entry = opcode_get_entry(op, graph->opcode_hash); + cnt_inc(&entry->normalized); + + /* increase local value */ + graph = graph_get_entry(current_ir_graph, status->irg_hash); + entry = opcode_get_entry(op, graph->opcode_hash); + cnt_inc(&entry->normalized); + } + STAT_LEAVE; +} /* stat_normalize */ + /** * Hook: A new graph was created * @@ -1527,6 +1590,7 @@ static void stat_new_graph(void *ctx, ir_graph *irg, ir_entity *ent) { graph->is_leaf_call = 0; graph->is_recursive = 0; graph->is_chain_call = 0; + graph->is_strict = 1; graph->is_analyzed = 0; } STAT_LEAVE; @@ -1633,12 +1697,18 @@ 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) { - ir_op *op = stat_get_irn_op(n); - opt_entry_t *entry = opt_get_entry(op, hmap); +static void removed_due_opt(ir_node *n, hmap_opt_entry_t *hmap, hook_opt_kind kind) { + opt_entry_t *entry; + ir_op *op = stat_get_irn_op(n); + + /* ignore CSE for Constants */ + if (kind == HOOK_OPT_CSE && (is_Const(n) || is_SymConst(n))) + return; /* increase global value */ + entry = opt_get_entry(op, hmap); cnt_inc(&entry->count); } /* removed_due_opt */ @@ -1684,7 +1754,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 */ } @@ -1724,7 +1794,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 */ @@ -1789,7 +1859,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 */ @@ -1862,7 +1932,7 @@ static void stat_arch_dep_replace_mul_with_shifts(void *ctx, ir_node *mul) { 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 */ @@ -1881,7 +1951,7 @@ static void stat_arch_dep_replace_division_by_const(void *ctx, ir_node *node) { 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 */ @@ -2155,8 +2225,7 @@ void firm_init_stat(unsigned enable_options) if (! (enable_options & FIRMSTAT_ENABLED)) return; - status = xmalloc(sizeof(*status)); - memset(status, 0, sizeof(*status)); + status = XMALLOCZ(stat_info_t); /* enable statistics */ status->stat_options = enable_options & FIRMSTAT_ENABLED ? enable_options : 0; @@ -2166,6 +2235,7 @@ void firm_init_stat(unsigned enable_options) 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_normalize, stat_normalize); HOOK(hook_new_graph, stat_new_graph); HOOK(hook_free_graph, stat_free_graph); HOOK(hook_irg_walk, stat_irg_walk); @@ -2217,6 +2287,9 @@ void firm_init_stat(unsigned enable_options) _op_DivModC.code = --num; _op_DivModC.name = new_id_from_chars(X("DivModC")); + _op_QuotC.code = --num; + _op_QuotC.name = new_id_from_chars(X("QuotC")); + status->op_Phi0 = &_op_Phi0; status->op_PhiM = &_op_PhiM; status->op_ProjM = &_op_ProjM; @@ -2224,6 +2297,7 @@ void firm_init_stat(unsigned enable_options) status->op_DivC = &_op_DivC; status->op_ModC = &_op_ModC; status->op_DivModC = &_op_DivModC; + status->op_QuotC = &_op_QuotC; } else { status->op_Phi0 = NULL; status->op_PhiM = NULL; @@ -2232,6 +2306,7 @@ void firm_init_stat(unsigned enable_options) status->op_DivC = NULL; status->op_ModC = NULL; status->op_DivModC = NULL; + status->op_QuotC = NULL; } /* if */ /* for Florian: count the Sel depth */