}
/**
- * 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)
{
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);
}
/**
/* 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);
* @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;
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 */
/* 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);
}
}
+/**
+ * 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)
{
/* 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) {
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 */
* @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;
* @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);
* @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;
}
/**
- * 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;
}
/**
}
/**
- * 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
+ * A division by const was replaced
*
- * @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
- *
- * @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;
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;
}
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 */
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);