beware of NaN's
[libfirm] / ir / stat / firmstat.c
index 3c7170e..f665ee9 100644 (file)
@@ -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.
  *
@@ -73,6 +73,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 +99,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 +139,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 */
 
@@ -195,6 +199,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;
@@ -258,7 +263,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 */
@@ -287,7 +292,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;
 
@@ -525,6 +530,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.
@@ -553,29 +567,35 @@ 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) {
                        /* special case, a Sel of a Sel, count on extra counter */
@@ -607,6 +627,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) {
@@ -632,7 +657,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);
@@ -788,6 +813,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 */
@@ -798,7 +825,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);
@@ -1078,7 +1105,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)) {
@@ -1103,7 +1130,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);
@@ -1245,6 +1272,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;
@@ -1323,10 +1351,22 @@ 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_const_tbl)
+               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.
@@ -1381,6 +1421,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;
 
@@ -1403,6 +1444,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;
 
@@ -1420,6 +1463,8 @@ 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;
 
@@ -1453,6 +1498,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;
 
@@ -1483,6 +1529,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;
 
@@ -1513,6 +1560,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;
 
@@ -1541,6 +1589,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;
 
@@ -1578,6 +1629,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;
 
@@ -1595,11 +1650,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 */
@@ -1615,6 +1675,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;
 
@@ -1623,6 +1684,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;
 
@@ -1644,7 +1706,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 */
        }
@@ -1658,6 +1720,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;
 
@@ -1675,6 +1738,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;
 
@@ -1682,7 +1746,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 */
@@ -1697,6 +1761,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;
 
@@ -1718,6 +1783,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;
 
@@ -1736,6 +1802,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;
 
@@ -1744,7 +1811,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 */
@@ -1755,6 +1822,8 @@ 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;
 
@@ -1767,6 +1836,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;
 
@@ -1784,6 +1857,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;
 
@@ -1802,13 +1877,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 */
@@ -1820,13 +1896,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 */
@@ -2001,7 +2078,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);
@@ -2064,6 +2141,10 @@ void stat_dump_snapshot(const char *name, const char *phase)
                /* 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);
@@ -2158,6 +2239,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;
@@ -2165,6 +2249,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;
@@ -2173,6 +2258,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 */
@@ -2206,6 +2292,8 @@ void firm_init_stat(unsigned enable_options)
        /* distribution table for parameter counts */
        status->dist_param_cnt = stat_new_int_distrib_tbl();
 
+       clear_optimization_counter();
+
 #undef HOOK
 #undef X
 }  /* firm_init_stat */