#include "irprintf.h"
#include "irdom.h"
#include "set.h"
+#include "statev.h"
#include "dfs_t.h"
+static const char *edge_names[] = {
+ "anc",
+ "fwd",
+ "cross",
+ "back"
+};
+
static int cmp_edge(const void *a, const void *b, size_t sz)
{
const dfs_edge_t *p = a;
static void classify_edges(dfs_t *dfs)
{
+ stat_ev_cnt_decl(anc);
+ stat_ev_cnt_decl(back);
+ stat_ev_cnt_decl(fwd);
+ stat_ev_cnt_decl(cross);
dfs_edge_t *edge;
foreach_set (dfs->edges, edge) {
dfs_node_t *src = edge->s;
dfs_node_t *tgt = edge->t;
- if (tgt->ancestor == src)
+ if (tgt->ancestor == src) {
+ stat_ev_cnt_inc(anc);
edge->kind = DFS_EDGE_ANC;
- else if (_dfs_int_is_ancestor(tgt, src))
+ }
+ else if (_dfs_int_is_ancestor(tgt, src)) {
+ stat_ev_cnt_inc(back);
edge->kind = DFS_EDGE_BACK;
- else if (_dfs_int_is_ancestor(src, tgt))
+ }
+ else if (_dfs_int_is_ancestor(src, tgt)) {
+ stat_ev_cnt_inc(fwd);
edge->kind = DFS_EDGE_FWD;
- else
+ }
+ else {
+ stat_ev_cnt_inc(cross);
edge->kind = DFS_EDGE_CROSS;
+ }
}
+
+ stat_ev_cnt_done(anc, "dfs_edge_anc");
+ stat_ev_cnt_done(back, "dfs_edge_back");
+ stat_ev_cnt_done(fwd, "dfs_edge_fwd");
+ stat_ev_cnt_done(cross, "dfs_edge_cross");
}
dfs_edge_kind_t dfs_get_edge_kind(const dfs_t *dfs, const void *a, const void *b)
res->post_order[node->post_num] = node;
}
+ stat_ev_dbl("dfs_n_blocks", res->pre_num);
+
return res;
}
}
}
}
+
+ for (i = 0, n = dfs_get_n_nodes(lv->dfs); i < n; ++i) {
+ const ir_node *bl = dfs_get_post_num_node(lv->dfs, i);
+ bl_info_t *bi = get_block_info(lv, bl);
+ bitset_set(bi->be_tgt_reach, bi->id);
+ }
}
lv_chk_t *lv_chk_new(ir_graph *irg, const dfs_t *dfs)
struct obstack *obst;
int i;
+ stat_ev_tim_push();
phase_init(&res->ph, "liveness check", irg, PHASE_DEFAULT_GROWTH, init_block_data, NULL);
obst = phase_obst(&res->ph);
FIRM_DBG_REGISTER(res->dbg, "ir.ana.lvchk");
- // res->dfs = dfs_new(&absgraph_irg_cfg_succ, irg);
res->dfs = dfs;
res->n_blocks = dfs_get_n_nodes(res->dfs);
res->back_edge_src = bitset_obstack_alloc(obst, res->n_blocks);
DBG((res->dbg, LEVEL_1, "back edge src: %B\n", res->back_edge_src));
DBG((res->dbg, LEVEL_1, "back edge tgt: %B\n", res->back_edge_tgt));
+ stat_ev_tim_pop("lv_chk_cons_time");
return res;
}
if (!is_liveness_node(var))
return 0;
- stat_ev("lv_chk");
+ stat_ev_ctx_push_fmt("lv_chk", "%u", get_irn_idx(var));
+ stat_ev_tim_push();
/* If there is no dominance relation, go out, too */
def_bl = get_nodes_block(var);
* silently exploited below.
*/
else {
- bitset_t *tmp = bitset_alloca(lv->n_blocks);
- bitset_t *uses = bitset_alloca(lv->n_blocks);
bl_info_t *def = get_block_info(lv, def_bl);
bl_info_t *bli = get_block_info(lv, bl);
+ bitset_t *uses = bitset_alloca(lv->n_blocks);
+ bitset_t *Tq;
- int i, min_dom, max_dom;
+ unsigned i, min_dom, max_dom;
const ir_edge_t *edge;
/* if the block has no DFS info, it cannot be reached.
if (!bli)
goto end;
+ (void) def;
DBG((lv->dbg, LEVEL_2, "lv check %+F (def in %+F #%d) in different block %+F #%d\n",
var, def_bl, def->id, bl, bli->id));
/* prepare a set with all reachable back edge targets.
* this will determine our "looking points" from where
- * we will search/find the calculated uses.
- *
- * Since there might be no reachable back edge targets
- * we add the current block also since reachability of
- * uses are then checked from there. */
- bitset_copy(tmp, bli->be_tgt_reach);
- bitset_set (tmp, bli->id);
+ * we will search/find the calculated uses. */
+ Tq = bli->be_tgt_reach;
/* now, visit all viewing points in the temporary bitset lying
* in the dominance range of the variable. Note that for reducible
* flow-graphs the first iteration is sufficient and the loop
* will be left. */
- DBG((lv->dbg, LEVEL_2, "\tbe tgt reach: %B, dom span: [%d, %d]\n", tmp, min_dom, max_dom));
- for (i = bitset_next_set(tmp, min_dom); i >= 0 && i <= max_dom; i = bitset_next_set(tmp, i + 1)) {
+ DBG((lv->dbg, LEVEL_2, "\tbe tgt reach: %B, dom span: [%d, %d]\n", Tq, min_dom, max_dom));
+ i = bitset_next_set(Tq, min_dom);
+ while(i <= max_dom) {
bl_info_t *ti = lv->map[i];
int use_in_current_block = bitset_is_set(uses, ti->id);
goto end;
}
- bitset_andnot(tmp, ti->red_reachable);
-
/*
* if we deleted a use do to the commentary above, we have to
* re-add it since it might be visible from further view points
*/
if (use_in_current_block)
bitset_set(uses, ti->id);
+
+ i = bitset_next_set(Tq, get_Block_dom_max_subtree_pre_num(ti->block) + 1);
}
}
end:
+ stat_ev_tim_pop("lv_chk_query_time");
stat_ev_cnt_done(uses, "lv_chk_uses");
stat_ev_cnt_done(iter, "lv_chk_iter");
+ stat_ev_ctx_pop("lv_chk");
return res;
}
FIRM_DBG_REGISTER(env.dbg, "firm.be.sched.ilp");
- stat_ev_ctx_push("phase", "ilpsched");
+ stat_ev_ctx_push("ilpsched");
// firm_dbg_set_mask(env.dbg, 1);
/* notify backend */
be_ilp_sched_finish_irg_ilp_schedule(sel, birg->irg, env.irg_env);
- stat_ev_ctx_pop();
+ stat_ev_ctx_pop("ilpsched");
}
/**
#include "irphase_t.h"
#include "iredges_t.h"
+#include "statev.h"
+
#include "beirg_t.h"
#include "besched_t.h"
+#include "belive_t.h"
/**
* Check dominance of two nodes in the same block.
{
int a2b = _value_dominates(a, b);
int b2a = _value_dominates(b, a);
+ int res = 0;
+
+ stat_ev_ctx_push("beintlive");
+
+ /*
+ * Adjust a and b so, that a dominates b if
+ * a dominates b or vice versa.
+ */
+ if(b2a) {
+ const ir_node *t = a;
+ a = b;
+ b = t;
+ a2b = 1;
+ }
/* If there is no dominance relation, they do not interfere. */
- if((a2b | b2a) > 0) {
+ if(a2b) {
const ir_edge_t *edge;
- ir_node *bb;
+ ir_node *bb = get_nodes_block(b);
- /*
- * Adjust a and b so, that a dominates b if
- * a dominates b or vice versa.
- */
- if(b2a) {
- const ir_node *t = a;
- a = b;
- b = t;
- }
-
- bb = get_nodes_block(b);
+ stat_ev_dbl("beintlive_ignore", arch_irn_is(lv->birg->main_env->arch_env, a, ignore));
/*
* If a is live end in b's block it is
* live at b's definition (a dominates b)
*/
- if(be_is_live_end(lv, bb, a))
- return 1;
+ if(be_is_live_end(lv, bb, a)) {
+ res = 1;
+ goto end;
+ }
/*
* Look at all usages of a.
*/
foreach_out_edge(a, edge) {
const ir_node *user = get_edge_src_irn(edge);
- if(get_nodes_block(user) == bb && !is_Phi(user) && _value_strictly_dominates(b, user))
- return 1;
+ if(get_nodes_block(user) == bb && !is_Phi(user) && _value_strictly_dominates(b, user)) {
+ res = 1;
+ goto end;
+ }
}
}
- return 0;
+end:
+ stat_ev_ctx_pop("beintlive");
+ return res;
}
#include "dfs_t.h"
#include "absgraph.h"
+#include "statev.h"
#include "beutil.h"
#include "belive_t.h"
struct _be_lv_info_node_t *be_lv_get(const struct _be_lv_t *li, const ir_node *bl, const ir_node *irn)
{
- struct _be_lv_info_t *irn_live = phase_get_irn_data(&li->ph, bl);
+ struct _be_lv_info_t *irn_live;
+ struct _be_lv_info_node_t *res = NULL;
+ stat_ev_tim_push();
+ irn_live = phase_get_irn_data(&li->ph, bl);
if(irn_live) {
unsigned idx = get_irn_idx(irn);
int pos = _be_liveness_bsearch(irn_live, idx);
/* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
- struct _be_lv_info_node_t *res = &irn_live[pos + 1].u.node;
+ struct _be_lv_info_node_t *rec = &irn_live[pos + 1].u.node;
/* Check, if the irn is in deed in the array. */
- if(res->idx == idx)
- return res;
+ if(rec->idx == idx)
+ res = rec;
}
+ stat_ev_tim_pop("be_lv_get");
- return NULL;
+ return res;
}
static struct _be_lv_info_node_t *be_lv_get_or_set(struct _be_lv_t *li, ir_node *bl, ir_node *irn)
ir_node **nodes;
int i, n;
+ stat_ev_tim_push();
obstack_init(&obst);
irg_walk_graph(lv->irg, collect_nodes, NULL, &obst);
n = obstack_object_size(&obst) / sizeof(nodes[0]);
obstack_free(&obst, NULL);
register_hook(hook_node_info, &lv->hook_info);
+ stat_ev_tim_pop("be_lv_sets_cons");
}
void be_liveness_assure_sets(be_lv_t *lv)
obstack_ptr_grow(&obst, NULL);
nodes = obstack_finish(&obst);
- for (i = 0; blocks[i]; ++i) {
- ir_node *bl = blocks[i];
+ stat_ev_ctx_push("be_lv_chk_compare");
+ for (j = 0; nodes[j]; ++j) {
+ ir_node *irn = nodes[j];
+ for (i = 0; blocks[i]; ++i) {
+ ir_node *bl = blocks[i];
- for (j = 0; nodes[j]; ++j) {
- ir_node *irn = nodes[j];
if (!is_Block(irn)) {
int lvr_in = be_is_live_in (lv, bl, irn);
int lvr_out = be_is_live_out(lv, bl, irn);
}
}
}
-
+ stat_ev_ctx_pop("be_lv_chk_compare");
obstack_free(&obst, NULL);
}
#include "irphase_t.h"
#include "irhooks.h"
#include "dfs.h"
+#include "statev.h"
#include "pset.h"
#include "bitset.h"
static INLINE int _be_is_live_xxx(const struct _be_lv_t *li, const ir_node *block, const ir_node *irn, unsigned flags)
{
+ int res;
+
if (li->nodes) {
struct _be_lv_info_node_t *info = be_lv_get(li, block, irn);
- return info ? (info->flags & flags) != 0 : 0;
+ res = info ? (info->flags & flags) != 0 : 0;
}
#ifdef USE_LIVE_CHK
else
- return (lv_chk_bl_xxx(li->lvc, block, irn) & flags) != 0;
-#else
- assert(li->nodes && "node sets must be computed");
- return 0;
+ res = (lv_chk_bl_xxx(li->lvc, block, irn) & flags) != 0;
#endif /* USE_LIVE_CHK */
+
+ return res;
}
#define be_lv_foreach(lv, bl, flags, i) \
LC_OPT_ENT_ENUM_PTR ("sched", "select a scheduler", &sched_var),
#ifdef FIRM_STATISTICS
LC_OPT_ENT_BOOL ("statev", "dump statistic events", &be_options.statev),
- LC_OPT_ENT_STR ("printev", "print (some) statistic events", &be_options.printev, sizeof(be_options.printev)),
+ LC_OPT_ENT_STR ("filtev", "filter for stat events (regex if support is active", &be_options.printev, sizeof(be_options.printev)),
#endif
#ifdef WITH_ILP
}
/* generate code */
- stat_ev_ctx_push("bemain_phase", "prepare");
+ stat_ev_ctx_push_str("bemain_phase", "prepare");
BE_TIMER_PUSH(t_codegen);
arch_code_generator_prepare_graph(birg->cg);
BE_TIMER_POP(t_codegen);
- stat_ev_ctx_pop();
+ stat_ev_ctx_pop("bemain_phase");
/* reset the phi handler. */
be_phi_handler_reset(env.phi_handler);
/* be_live_chk_compare(birg); */
/* let backend prepare scheduling */
- stat_ev_ctx_push("bemain_phase", "before_sched");
+ stat_ev_ctx_push_str("bemain_phase", "before_sched");
BE_TIMER_PUSH(t_codegen);
arch_code_generator_before_sched(birg->cg);
BE_TIMER_POP(t_codegen);
- stat_ev_ctx_pop();
+ stat_ev_ctx_pop("bemain_phase");
/* schedule the irg */
BE_TIMER_PUSH(t_sched);
#endif /* FIRM_STATISTICS */
free_ir_graph(irg);
#endif /* if 0 */
- stat_ev_ctx_pop();
+ stat_ev_ctx_pop("bemain_irg");
}
be_profile_free();
be_done_env(&env);
}
#ifdef FIRM_STATISTICS
- if (be_options.statev || be_options.printev[0] != '\0') {
+ if (be_options.statev) {
const char *dot = strrchr(cup_name, '.');
const char *pos = dot ? dot : cup_name + strlen(cup_name);
char *buf = alloca(pos - cup_name + 1);
strncpy(buf, cup_name, pos - cup_name);
buf[pos - cup_name] = '\0';
- stat_ev_begin(buf);
-
- if(be_options.printev[0] != '\0') {
- stat_ev_print(be_options.printev);
- }
+ be_options.statev = 1;
+ stat_ev_begin(buf, be_options.printev);
}
#endif
FIRM_DBG_REGISTER(dbg, "ir.be.ssadestr");
be_liveness_invalidate(lv);
- be_liveness_assure_sets(lv);
/* create a map for fast lookup of perms: block --> perm */
irg_walk_graph(irg, clear_link, collect_phis_walker, chordal_env);