* @author Michael Beck
* @version $Id$
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
#ifdef FIRM_STATISTICS
#include <stdio.h>
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
+#include <stdlib.h>
+#include <string.h>
#include "irouts.h"
#include "irdump.h"
#include "hashptr.h"
#include "firmstat_t.h"
+#include "irpass_t.h"
#include "pattern.h"
#include "dags.h"
#include "stat_dmp.h"
cnt_clr(&elem->cnt_alive);
cnt_clr(&elem->new_node);
cnt_clr(&elem->into_Id);
+ cnt_clr(&elem->normalized);
} /* opcode_clear_entry */
/**
- * Returns the associates node_entry_t for an ir_op
+ * Returns the associates node_entry_t for an ir_op (and allocates
+ * one if not yet available).
*
* @param op the IR operation
* @param hmap a hash map containing ir_op* -> node_entry_t*
if (elem)
return elem;
- elem = obstack_alloc(&status->cnts, sizeof(*elem));
- memset(elem, 0, sizeof(*elem));
+ elem = OALLOCZ(&status->cnts, node_entry_t);
/* clear counter */
opcode_clear_entry(elem);
/**
* Returns the associated graph_entry_t for an IR graph.
*
- * @param irg the IR graph
+ * @param irg the IR graph, NULL for the global counter
* @param hmap the hash map containing ir_graph* -> graph_entry_t*
*/
static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap)
} /* if */
/* allocate a new one */
- elem = obstack_alloc(&status->cnts, sizeof(*elem));
- memset(elem, 0, sizeof(*elem));
+ elem = OALLOCZ(&status->cnts, graph_entry_t);
obstack_init(&elem->recalc_cnts);
/* clear counter */
if (elem)
return elem;
- elem = obstack_alloc(&status->cnts, sizeof(*elem));
- memset(elem, 0, sizeof(*elem));
+ elem = OALLOCZ(&status->cnts, opt_entry_t);
/* clear new counter */
opt_clear_entry(elem);
if (elem)
return elem;
- elem = obstack_alloc(obst, sizeof(*elem));
- memset(elem, 0, sizeof(*elem));
+ elem = OALLOCZ(obst, block_entry_t);
/* clear new counter */
block_clear_entry(elem);
if (elem)
return elem;
- elem = obstack_alloc(obst, sizeof(*elem));
- memset(elem, 0, sizeof(*elem));
+ elem = OALLOCZ(obst, be_block_entry_t);
/* clear new counter */
be_block_clear_entry(elem);
if (elem)
return elem;
- elem = obstack_alloc(obst, sizeof(*elem));
- memset(elem, 0, sizeof(*elem));
+ elem = OALLOCZ(obst, perm_class_entry_t);
/* clear new counter */
perm_class_clear_entry(elem);
if (elem)
return elem;
- elem = obstack_alloc(obst, sizeof(*elem));
- memset(elem, 0, sizeof(*elem));
+ elem = OALLOCZ(obst, perm_stat_entry_t);
/* clear new counter */
perm_stat_clear_entry(elem);
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);
/* 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 */
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);
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
*
graph->is_leaf_call = 0;
graph->is_recursive = 0;
graph->is_chain_call = 0;
+ graph->is_strict = 1;
graph->is_analyzed = 0;
}
STAT_LEAVE;
reg_pressure_entry_t *rp_ent;
block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash);
- rp_ent = obstack_alloc(&status->be_data, sizeof(*rp_ent));
- memset(rp_ent, 0, sizeof(*rp_ent));
+ rp_ent = OALLOCZ(&status->be_data, reg_pressure_entry_t);
rp_ent->class_name = class_name;
rp_ent->pressure = pressure;
fname[0] = '\0';
p = name;
} /* if */
- strncat(fname, "firmstat-", sizeof(fname));
- strncat(fname, phase, sizeof(fname));
- strncat(fname, "-", sizeof(fname));
- strncat(fname, p, sizeof(fname));
+ strncat(fname, "firmstat-", sizeof(fname)-1);
+ strncat(fname, phase, sizeof(fname)-1);
+ strncat(fname, "-", sizeof(fname)-1);
+ strncat(fname, p, sizeof(fname)-1);
stat_dump_init(fname);
stat_finish_pattern_history(fname);
- /* clear the global counter here */
+ /* clear the global counters here */
{
node_entry_t *entry;
opcode_clear_entry(entry);
} /* for */
/* clear all global counter */
- graph_clear_entry(global, 1);
+ graph_clear_entry(global, /*all=*/1);
}
}
STAT_LEAVE;
} /* stat_dump_snapshot */
+struct pass_t {
+ ir_prog_pass_t pass;
+ const char *fname;
+ const char *phase;
+};
+
+/**
+ * Wrapper to run stat_dump_snapshot() as a ir_prog wrapper.
+ */
+static int stat_dump_snapshot_wrapper(ir_prog *irp, void *context) {
+ struct pass_t *pass = context;
+
+ (void)irp;
+ stat_dump_snapshot(pass->fname, pass->phase);
+ return 0;
+} /* stat_dump_snapshot_wrapper */
+
+/**
+ * Ensure that no verifier is run from the wrapper.
+ */
+static int no_verify(ir_prog *prog, void *ctx)
+{
+ (void)prog;
+ (void)ctx;
+ return 0;
+}
+
+/**
+ * Ensure that no dumper is run from the wrapper.
+ */
+static void no_dump(ir_prog *prog, void *ctx, unsigned idx)
+{
+ (void)prog;
+ (void)ctx;
+ (void)idx;
+}
+
+/* create an ir_pog pass */
+ir_prog_pass_t *stat_dump_snapshot_pass(
+ const char *name, const char *fname, const char *phase) {
+ struct pass_t *pass = XMALLOCZ(struct pass_t);
+
+ def_prog_pass_constructor(
+ &pass->pass, name ? name : "stat_snapshot", stat_dump_snapshot_wrapper);
+ pass->fname = fname;
+ pass->phase = phase;
+
+ /* no dump/verify */
+ pass->pass.dump_irprog = no_dump;
+ pass->pass.verify_irprog = no_verify;
+
+ return &pass->pass;
+} /* stat_dump_snapshot_pass */
+
/** the hook entries for the Firm statistics module */
static hook_entry_t stat_hooks[hook_last];
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);