From: Christian Würdig Date: Mon, 10 Apr 2006 15:22:31 +0000 (+0000) Subject: added permutations statistics X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=099169663d1d5389be0546c9644c74eb0e78d9c1;p=libfirm added permutations statistics [r7612] --- diff --git a/ir/stat/firmstat.c b/ir/stat/firmstat.c index a7a4d66e0..c3ede63cc 100644 --- a/ir/stat/firmstat.c +++ b/ir/stat/firmstat.c @@ -141,7 +141,7 @@ static int be_block_cmp(const void *elt, const void *key) } /** - * compare two elements of the block/extbb hash + * compare two elements of reg pressure hash */ static int reg_pressure_cmp(const void *elt, const void *key) { @@ -151,6 +151,28 @@ static int reg_pressure_cmp(const void *elt, const void *key) return e1->id_name != e2->id_name; } +/** + * compare two elements of the perm_stat hash + */ +static int perm_stat_cmp(const void *elt, const void *key) +{ + const perm_stat_entry_t *e1 = elt; + const perm_stat_entry_t *e2 = key; + + return e1->perm != e2->perm; +} + +/** + * compare two elements of the perm_class hash + */ +static int perm_class_cmp(const void *elt, const void *key) +{ + const perm_class_entry_t *e1 = elt; + const perm_class_entry_t *e2 = key; + + return e1->id_name != e2->id_name; +} + /** * compare two elements of the ir_op hash */ @@ -273,8 +295,14 @@ static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap) key.irg = irg; elem = pset_find(hmap, &key, HASH_PTR(irg)); - if (elem) + + if (elem) { + /* create hash map backend block information */ + if (! elem->be_block_hash) + elem->be_block_hash = new_pset(be_block_cmp, 5); + return elem; + } /* allocate a new one */ elem = obstack_alloc(&status->cnts, sizeof(*elem)); @@ -289,9 +317,6 @@ static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap) elem->address_mark = new_set(address_mark_cmp, 5); elem->irg = irg; - /* create hash map backend block information */ - elem->be_block_hash = new_pset(be_block_cmp, 5); - /* these hash tables are created on demand */ elem->block_hash = NULL; elem->extbb_hash = NULL; @@ -389,8 +414,12 @@ static void be_block_clear_entry(be_block_entry_t *elem) if (elem->sched_ready) stat_delete_distrib_tbl(elem->sched_ready); - elem->reg_pressure = new_pset(reg_pressure_cmp, 5); - elem->sched_ready = stat_new_int_distrib_tbl(); + if (elem->perm_class_stat) + del_pset(elem->perm_class_stat); + + elem->reg_pressure = new_pset(reg_pressure_cmp, 5); + elem->sched_ready = stat_new_int_distrib_tbl(); + elem->perm_class_stat = new_pset(perm_class_cmp, 5); } /** @@ -421,6 +450,85 @@ static be_block_entry_t *be_block_get_entry(struct obstack *obst, long block_nr, return pset_insert(hmap, elem, block_nr); } +/** + * clears all sets in perm_class_entry_t + */ +static void perm_class_clear_entry(perm_class_entry_t *elem) { + if (elem->perm_stat) + del_pset(elem->perm_stat); + + elem->perm_stat = new_pset(perm_stat_cmp, 5); +} + +/** + * Returns the associated perm_class entry for a register class. + * + * @param cls_id the register class ident + * @param hmap a hash map containing class_name -> perm_class_entry_t + */ +static perm_class_entry_t *perm_class_get_entry(struct obstack *obst, ident *cls_id, hmap_perm_class_entry_t *hmap) +{ + perm_class_entry_t key; + perm_class_entry_t *elem; + + key.id_name = cls_id; + + elem = pset_find(hmap, &key, HASH_PTR(cls_id)); + if (elem) + return elem; + + elem = obstack_alloc(obst, sizeof(*elem)); + memset(elem, 0, sizeof(*elem)); + + /* clear new counter */ + perm_class_clear_entry(elem); + + elem->id_name = cls_id; + + return pset_insert(hmap, elem, HASH_PTR(cls_id)); +} + +/** + * clears all sets in perm_stat_entry_t + */ +static void perm_stat_clear_entry(perm_stat_entry_t *elem) { + if (elem->chains) + stat_delete_distrib_tbl(elem->chains); + + if (elem->cycles) + stat_delete_distrib_tbl(elem->cycles); + + elem->chains = stat_new_int_distrib_tbl(); + elem->cycles = stat_new_int_distrib_tbl(); +} + +/** + * Returns the associated perm_stat entry for a perm. + * + * @param perm the perm node + * @param hmap a hash map containing perm -> perm_stat_entry_t + */ +static perm_stat_entry_t *perm_stat_get_entry(struct obstack *obst, ir_node *perm, hmap_perm_stat_entry_t *hmap) +{ + perm_stat_entry_t key; + perm_stat_entry_t *elem; + + key.perm = perm; + + elem = pset_find(hmap, &key, HASH_PTR(perm)); + if (elem) + return elem; + + elem = obstack_alloc(obst, sizeof(*elem)); + memset(elem, 0, sizeof(*elem)); + + /* clear new counter */ + perm_stat_clear_entry(elem); + + elem->perm = perm; + + return pset_insert(hmap, elem, HASH_PTR(perm)); +} /** * Returns the ir_op for an IR-node, @@ -1570,10 +1678,6 @@ static void stat_be_block_regpressure(void *ctx, ir_node *block, ir_graph *irg, be_block_entry_t *block_ent; reg_pressure_entry_t *rp_ent; - /* create new be_block hash */ - if (! graph->be_block_hash) - graph->be_block_hash = new_pset(be_block_cmp, 5); - 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)); @@ -1601,24 +1705,93 @@ static void stat_be_block_sched_ready(void *ctx, ir_node *block, ir_graph *irg, STAT_ENTER; { - graph_entry_t *graph = graph_get_entry(irg, status->irg_hash); - be_block_entry_t *block_ent; - counter_t cnt_1; + graph_entry_t *graph = graph_get_entry(irg, status->irg_hash); + be_block_entry_t *block_ent; + const counter_t *cnt_1 = cnt_get_1(); + + block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash); + + /* add 1 to the counter of corresponding number of ready nodes */ + stat_add_int_distrib_tbl(block_ent->sched_ready, num_ready, cnt_1); + } + STAT_LEAVE; +} + +/** + * Update the permutation statistic of a block + * + * @param ctx the hook context + * @param class_name the ident name of the register class + * @param perm the perm node + * @param block the block containing the perm + * @param size the size of the perm + * @param real_size number of pairs with different registers + */ +void stat_be_block_stat_perm(void *ctx, ident *class_name, int n_regs, ir_node *perm, ir_node *block, + int size, int real_size) +{ + if (! status->stat_options) + return; - /* create new be_block hash */ - if (! graph->be_block_hash) - graph->be_block_hash = new_pset(be_block_cmp, 5); + STAT_ENTER; + { + graph_entry_t *graph = graph_get_entry(get_irn_irg(block), status->irg_hash); + be_block_entry_t *block_ent; + perm_class_entry_t *pc_ent; + perm_stat_entry_t *ps_ent; block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash); + pc_ent = perm_class_get_entry(&status->be_data, class_name, block_ent->perm_class_stat); + ps_ent = perm_stat_get_entry(&status->be_data, perm, pc_ent->perm_stat); + + pc_ent->n_regs = n_regs; - /* add 1 to the counter of orresponding number of ready nodes */ - cnt_clr(&cnt_1); - cnt_inc(&cnt_1); - stat_add_int_distrib_tbl(block_ent->sched_ready, num_ready, &cnt_1); + /* update information */ + ps_ent->size = size; + ps_ent->real_size = real_size; } STAT_LEAVE; } +/** + * Update the permutation statistic of a single perm + * + * @param ctx the hook context + * @param class_name the ident name of the register class + * @param perm the perm node + * @param block the block containing the perm + * @param is_chain 1 if chain, 0 if cycle + * @param n_ops the number of ops representing this cycle/chain after lowering + */ +void stat_be_block_stat_permcycle(void *ctx, ident *class_name, ir_node *perm, ir_node *block, + int is_chain, int size, int n_ops) +{ + if (! status->stat_options) + return; + + STAT_ENTER; + { + graph_entry_t *graph = graph_get_entry(get_irn_irg(block), status->irg_hash); + const counter_t *cnt_1 = cnt_get_1(); + be_block_entry_t *block_ent; + perm_class_entry_t *pc_ent; + perm_stat_entry_t *ps_ent; + + block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash); + pc_ent = perm_class_get_entry(&status->be_data, class_name, block_ent->perm_class_stat); + ps_ent = perm_stat_get_entry(&status->be_data, perm, pc_ent->perm_stat); + + if (is_chain) { + ps_ent->n_copies += n_ops; + stat_add_int_distrib_tbl(ps_ent->chains, size, cnt_1); + } + else { + ps_ent->n_exchg += n_ops; + stat_add_int_distrib_tbl(ps_ent->cycles, size, cnt_1); + } + } + STAT_LEAVE; +} /* Dumps a statistics snapshot */ void stat_dump_snapshot(const char *name, const char *phase) @@ -1785,6 +1958,8 @@ void firm_init_stat(unsigned enable_options) HOOK(hook_arch_dep_replace_division_by_const, stat_arch_dep_replace_division_by_const); HOOK(hook_be_block_regpressure, stat_be_block_regpressure); HOOK(hook_be_block_sched_ready, stat_be_block_sched_ready); + HOOK(hook_be_block_stat_perm, stat_be_block_stat_perm); + HOOK(hook_be_block_stat_permcycle, stat_be_block_stat_permcycle); obstack_init(&status->cnts); obstack_init(&status->be_data); diff --git a/ir/stat/firmstat_t.h b/ir/stat/firmstat_t.h index ef8e271de..5ba3a9ae7 100644 --- a/ir/stat/firmstat_t.h +++ b/ir/stat/firmstat_t.h @@ -42,6 +42,8 @@ typedef pset hmap_opt_entry_t; typedef pset hmap_block_entry_t; typedef pset hmap_be_block_entry_t; typedef pset hmap_reg_pressure_entry_t; +typedef pset hmap_perm_stat_entry_t; +typedef pset hmap_perm_class_entry_t; typedef pset hmap_ir_op; typedef pset hmap_distrib_entry_t; @@ -148,14 +150,37 @@ typedef struct _reg_pressure_entry_t { int pressure; /**< the register pressure for this class */ } reg_pressure_entry_t; +/** + * An entry for permutation statistics. + */ +typedef struct _perm_stat_entry_t { + ir_node *perm; /**< the perm node */ + int size; /**< complete size */ + int real_size; /**< number of pairs with different registers */ + int n_copies; /**< number of copies created for lowering */ + int n_exchg; /**< number of exchanges created for lowering */ + distrib_tbl_t *cycles; /**< distribution of cycle lengths */ + distrib_tbl_t *chains; /**< distribution of chain lengths */ +} perm_stat_entry_t; + +/** + * An entry for permutation statistics per class. + */ +typedef struct _perm_class_entry_t { + ident *id_name; /**< name of the register class */ + int n_regs; /**< number of register in this class */ + HASH_MAP(perm_stat_entry_t) *perm_stat; /**< statistics about all perm nodes of this class */ +} perm_class_entry_t; + /** * An entry for a block or extended block in a ir-graph */ typedef struct _be_block_entry_t { - long block_nr; /**< block nr */ - distrib_tbl_t *sched_ready; /**< distribution of ready nodes per block */ + long block_nr; /**< block nr */ + distrib_tbl_t *sched_ready; /**< distribution of ready nodes per block */ /**< the highest register pressures for this block for each register class */ HASH_MAP(reg_pressure_entry_t) *reg_pressure; + HASH_MAP(perm_class_entry_t) *perm_class_stat; /**< statistics about perm nodes for each register class */ } be_block_entry_t; /** diff --git a/ir/stat/stat_dmp.c b/ir/stat/stat_dmp.c index d0608c886..88a40c91d 100644 --- a/ir/stat/stat_dmp.c +++ b/ir/stat/stat_dmp.c @@ -151,11 +151,12 @@ static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index) /** * dumps the register pressure for each block and for each register class */ -static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry) { +static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry) +{ be_block_entry_t *b_entry = pset_first(entry->be_block_hash); reg_pressure_entry_t *rp_entry; - /* return if no reg pressure information available */ + /* return if no be statistic information available */ if (! b_entry) return; @@ -189,7 +190,8 @@ static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entr } /** prints a distribution entry */ -void dump_block_sched_ready_distrib(const distrib_entry_t *entry, void *env) { +void dump_block_sched_ready_distrib(const distrib_entry_t *entry, void *env) +{ FILE *dmp_f = env; fprintf(dmp_f, "%12d", entry->cnt.cnt[0]); } @@ -197,17 +199,16 @@ void dump_block_sched_ready_distrib(const distrib_entry_t *entry, void *env) { /** * dumps the distribution of the amount of ready nodes for each block */ -static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry) { +static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry) +{ be_block_entry_t *b_entry = pset_first(entry->be_block_hash); - counter_t cnt_0; + const counter_t *cnt_0 = cnt_get_0(); int i; - /* return if no reg pressure information available */ + /* return if no be statistic information available */ if (! b_entry) return; - cnt_clr(&cnt_0); - fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n"); fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE"); @@ -216,9 +217,9 @@ static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry b_entry; b_entry = pset_next(entry->be_block_hash)) { - /* this ensures that all keys from 1 to 5 are in the table*/ + /* this ensures that all keys from 1 to 5 are in the table */ for (i = 1; i < 6; i++) - stat_add_int_distrib_tbl(b_entry->sched_ready, i, &cnt_0); + stat_add_int_distrib_tbl(b_entry->sched_ready, i, cnt_0); fprintf(dmp->f, "BLK %6ld", b_entry->block_nr); stat_iterate_distrib_tbl(b_entry->sched_ready, dump_block_sched_ready_distrib, dmp->f); @@ -227,6 +228,57 @@ static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry } } +/** + * dumps permutation statistics for one and block and one class + */ +static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry) +{ + perm_stat_entry_t *ps_ent; + + fprintf(dmp->f, "%12s %12s\n", "size", "real size"); + for (ps_ent = pset_first(entry->perm_stat); + ps_ent; + ps_ent = pset_next(entry->perm_stat)) + { + fprintf(dmp->f, "%12d %12d\n", ps_ent->size, ps_ent->real_size); + } +} + +/** + * dumps statistics about perms + */ +static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry) +{ + be_block_entry_t *b_entry = pset_first(entry->be_block_hash); + + /* return if no be statistic information available */ + if (! b_entry) + return; + + fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n"); + for (/* b_entry is already initialized */ ; + b_entry; + b_entry = pset_next(entry->be_block_hash)) + { + perm_class_entry_t *pc_ent; + + fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr); + + if (! b_entry->perm_class_stat) + continue; + + for (pc_ent = pset_first(b_entry->perm_class_stat); + pc_ent; + pc_ent = pset_next(b_entry->perm_class_stat)) + { + fprintf(dmp->f, "register class %s:\n", get_id_str(pc_ent->id_name)); + simple_dump_be_block_permstat_class(dmp, pc_ent); + } + } + + fprintf(dmp->f, "PERMUTATION STATISTICS END\n"); +} + /** * dumps the number of real_function_call optimization */ @@ -362,6 +414,9 @@ static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry) /* dump block ready nodes distribution */ simple_dump_be_block_sched_ready(dmp, entry); + /* dump block permutation statistics */ + simple_dump_be_block_permstat(dmp, entry); + if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB) { /* dump extended block info */ fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");