/*
- * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
- *
* This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
*/
/**
#include "irtools.h"
#include "irhooks.h"
#include "util.h"
+#include "fourcc.h"
/**
* names of the optimizations
{ (hook_opt_kind)FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
{ (hook_opt_kind)FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
{ (hook_opt_kind)FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
- { (hook_opt_kind)FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
{ (hook_opt_kind)FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
{ (hook_opt_kind)FS_OPT_MUX_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
{ (hook_opt_kind)FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
{ (hook_opt_kind)FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
{ (hook_opt_kind)FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
{ (hook_opt_kind)FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
- { (hook_opt_kind)FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
+ { (hook_opt_kind)FS_OPT_INVOLUTION, "algebraic simplification: OP(OP(x)) = x" },
{ (hook_opt_kind)FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
{ (hook_opt_kind)FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
{ (hook_opt_kind)FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
*/
static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
{
- node_entry_t *entry;
counter_t f_alive;
counter_t f_new_node;
counter_t f_Id;
cnt_clr(&f_normlized);
fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
- foreach_pset(set, node_entry_t*, entry) {
+ foreach_pset(set, node_entry_t, entry) {
fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
get_id_str(entry->op->name),
cnt_to_uint(&entry->cnt_alive),
cnt_add(&f_new_node, &entry->new_node);
cnt_add(&f_Id, &entry->into_Id);
cnt_add(&f_normlized, &entry->normalized);
- } /* foreach_pset */
+ }
fprintf(dmp->f, "-------------------------------------------\n");
fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
cnt_to_uint(&f_alive),
cnt_to_uint(&f_Id),
cnt_to_uint(&f_normlized)
);
-} /* simple_dump_opcode_hash */
+}
/**
* Return the name of an optimization.
assert(index < (int) ARRAY_SIZE(opt_names) && "index out of range");
assert((int) opt_names[index].kind == index && "opt_names broken");
return opt_names[index].name;
-} /* get_opt_name */
+}
/**
* dumps an optimization hash into human readable form
static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
{
if (pset_count(set) > 0) {
- opt_entry_t *entry;
const char *name = get_opt_name(index);
fprintf(dmp->f, "\n%s:\n", name);
fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
- foreach_pset(set, opt_entry_t*, entry) {
+ foreach_pset(set, opt_entry_t, entry) {
fprintf(dmp->f, "%-16s %8u\n",
get_id_str(entry->op->name), cnt_to_uint(&entry->count));
- } /* foreach_pset */
- } /* if */
-} /* simple_dump_opt_hash */
+ }
+ }
+}
/**
* 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)
{
- be_block_entry_t *b_entry = (be_block_entry_t*)pset_first(entry->be_block_hash);
- reg_pressure_entry_t *rp_entry;
-
/* return if no be statistic information available */
- if (! b_entry)
+ be_block_entry_t *const b_first = pset_first(be_block_entry_t, entry->be_block_hash);
+ if (!b_first)
return;
fprintf(dmp->f, "\nREG PRESSURE:\n");
fprintf(dmp->f, "%12s", "Block Nr");
/* print table head (register class names) */
- foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t*, rp_entry)
+ foreach_pset(b_first->reg_pressure, reg_pressure_entry_t, rp_entry)
fprintf(dmp->f, "%15s", rp_entry->class_name);
fprintf(dmp->f, "\n");
/* print the reg pressure for all blocks and register classes */
- for (/* b_entry is already initialized */ ;
- b_entry;
- b_entry = (be_block_entry_t*)pset_next(entry->be_block_hash)) {
+ foreach_pset(entry->block_hash, be_block_entry_t, b_entry) {
fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
- foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t*, rp_entry)
+ foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t, rp_entry)
fprintf(dmp->f, "%15d", rp_entry->pressure);
fprintf(dmp->f, "\n");
- } /* for */
-} /* simple_dump_be_block_reg_pressure */
+ }
+}
/** prints a distribution entry */
static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
{
dumper_t *dmp = (dumper_t*)env;
fprintf(dmp->f, "%12u", cnt_to_uint(&entry->cnt));
-} /* simple_dump_distrib_entry */
+}
/**
* 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)
{
if (pset_count(entry->be_block_hash) > 0) {
- be_block_entry_t *b_entry;
- int i;
+ int i;
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");
- foreach_pset(entry->be_block_hash, be_block_entry_t*, b_entry) {
+ foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
/* this ensures that all keys from 1 to 5 are in the table */
for (i = 1; i < 6; ++i)
stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
fprintf(dmp->f, "\n");
- } /* foreach_pset */
- } /* if */
-} /* simple_dump_be_block_sched_ready */
+ }
+ }
+}
/**
* Adds the counter for given entry to another distribution table.
distrib_tbl_t *sum_tbl = (distrib_tbl_t*)env;
stat_add_int_distrib_tbl(sum_tbl, (int)PTR_TO_INT(entry->object), &entry->cnt);
-} /* add_distrib_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;
- distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
- distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
- char buf[16];
- int i;
+ distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
+ distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
+ char buf[16];
+ int i;
fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
"size",
"# exchanges"
);
- foreach_pset(entry->perm_stat, perm_stat_entry_t*, ps_ent) {
+ foreach_pset(entry->perm_stat, perm_stat_entry_t, ps_ent) {
fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
ps_ent->size,
ps_ent->real_size,
/* sum up distribution table for cycles */
stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
- } /* foreach_pset */
+ }
/* print chain distribution for all perms of this class in this block */
fprintf(dmp->f, "chain distribution:\n");
snprintf(buf, sizeof(buf), "length %d", i);
fprintf(dmp->f, "%12s", buf);
stat_insert_int_distrib_tbl(sum_chains, i);
- } /* for */
+ }
fprintf(dmp->f, "\n");
stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
fprintf(dmp->f, "\n");
snprintf(buf, sizeof(buf), "length %d", i);
fprintf(dmp->f, "%12s", buf);
stat_insert_int_distrib_tbl(sum_cycles, i);
- } /* for */
+ }
fprintf(dmp->f, "\n");
stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
fprintf(dmp->f, "\n");
stat_delete_distrib_tbl(sum_chains);
stat_delete_distrib_tbl(sum_cycles);
-} /* simple_dump_be_block_permstat_class */
+}
/**
* dumps statistics about perms
static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
{
if (pset_count(entry->be_block_hash) > 0) {
- be_block_entry_t *b_entry;
-
fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
- foreach_pset(entry->be_block_hash, be_block_entry_t*, b_entry) {
- perm_class_entry_t *pc_ent;
-
+ foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
if (b_entry->perm_class_stat) {
- foreach_pset(b_entry->perm_class_stat, perm_class_entry_t*, pc_ent) {
+ foreach_pset(b_entry->perm_class_stat, perm_class_entry_t, pc_ent) {
fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
simple_dump_be_block_permstat_class(dmp, pc_ent);
- } /* foreach_pset */
- } /* if */
- } /* foreach_pset */
+ }
+ }
+ }
fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
- } /* if */
-} /* simple_dump_be_block_permstat */
+ }
+}
/**
* dumps the number of real_function_call optimization
if (! cnt_eq(cnt, 0)) {
fprintf(dmp->f, "\nReal Function Calls optimized:\n");
fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
- } /* if */
-} /* simple_dump_real_func_calls */
+ }
+}
/**
* dumps the number of tail_recursion optimization
if (num_tail_recursion > 0) {
fprintf(dmp->f, "\nTail recursion optimized:\n");
fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
- } /* if */
-} /* simple_dump_tail_recursion */
+ }
+}
/**
* dumps the edges count
return;
fprintf(dmp->f, "%-16s %8u\n", "Edges", cnt_to_uint(cnt));
-} /* simple_dump_edges */
+}
/**
* dumps the IRG
static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
{
int dump_opts = 1;
- block_entry_t *b_entry;
- extbb_entry_t *eb_entry;
if (! dmp->f)
return;
fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
else
fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
- } /* if */
+ }
fprintf(dmp->f, " %swalked %u over blocks %u:\n"
" was inlined : %u\n"
for (i = 0; i < IF_RESULT_LAST; ++i) {
fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
- } /* for */
+ }
} else {
fprintf(dmp->f, "\nGlobals counts:\n");
fprintf(dmp->f, "--------------\n");
dump_opts = 0;
- } /* if */
+ }
/* address ops */
fprintf(dmp->f,
simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
- for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
+ for (i = 0; i != ARRAY_SIZE(entry->opt_hash); ++i) {
simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
- } /* for */
+ }
/* dump block info */
fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
- foreach_pset(entry->block_hash, block_entry_t*, b_entry) {
+ foreach_pset(entry->block_hash, block_entry_t, b_entry) {
fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
b_entry->block_nr,
cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
);
- } /* foreach_pset */
+ }
/* dump block reg pressure */
simple_dump_be_block_reg_pressure(dmp, entry);
/* dump block permutation statistics */
simple_dump_be_block_permstat(dmp, entry);
-
- if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
- /* 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");
- foreach_pset(entry->extbb_hash, extbb_entry_t*, eb_entry) {
- fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
- eb_entry->block_nr,
- cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
- cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
- cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
- cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
- cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
- cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
- );
- } /* foreach_pset */
- } /* if */
}
-} /* simple_dump_graph */
+}
/**
* dumps the constant table
for (i = 0; i < ARRAY_SIZE(tbl->int_bits_count); ++i) {
fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
cnt_add(&sum, &tbl->int_bits_count[i]);
- } /* for */
+ }
fprintf(dmp->f, "-------------------------------\n");
fprintf(dmp->f, "\nFloating point constants classification\n");
for (i = 0; i < ARRAY_SIZE(tbl->floats); ++i) {
fprintf(dmp->f, "%-10s %12u\n", stat_fc_name((float_classify_t)i), cnt_to_uint(&tbl->floats[i]));
cnt_add(&sum, &tbl->floats[i]);
- } /* for */
+ }
fprintf(dmp->f, "--------------------------------------\n");
fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
fprintf(dmp->f, "-------------------------------\n");
fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
-} /* simple_dump_const_tbl */
+}
/**
* Dumps a line of the parameter table
fprintf(dmp->f, "%ld : %u\n", (long int)PTR_TO_INT(entry->object),
cnt_to_uint(&entry->cnt));
-} /* dump_tbl_line */
+}
/**
* dumps the parameter distribution table
fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
-} /* simple_dump_param_tbl */
+}
/**
* dumps the optimization counter table
fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
}
}
-} /* simple_dump_opt_cnt */
+}
/**
* initialize the simple dumper
dmp->f = fopen(fname, "w");
if (! dmp->f) {
perror(fname);
- } /* if */
-} /* simple_init */
+ }
+}
/**
* finishes the simple dumper
if (dmp->f)
fclose(dmp->f);
dmp->f = NULL;
-} /* simple_finish */
+}
/**
* the simple human readable dumper
*/
static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
{
- node_entry_t *entry;
int i;
for (i = 0; i < 4; ++i)
cnt_clr(&cnt[i]);
- foreach_pset(graph->opcode_hash, node_entry_t*, entry) {
+ foreach_pset(graph->opcode_hash, node_entry_t, entry) {
if (entry->op == op_Phi) {
/* normal Phi */
cnt_add(&cnt[1], &entry->cnt_alive);
} else {
/* all other nodes */
cnt_add(&cnt[0], &entry->cnt_alive);
- } /* if */
- } /* foreach_pset */
-} /* csv_count_nodes */
+ }
+ }
+}
/**
* dumps the IRG
ir_graph *const_irg = get_const_code_irg();
if (entry->irg == const_irg) {
- name = "<Const code Irg>";
return;
} else {
if (entry->ent)
name = get_entity_name(entry->ent);
else
name = "<UNKNOWN IRG>";
- } /* if */
+ }
csv_count_nodes(dmp, entry, cnt);
cnt_to_uint(&cnt[2]),
cnt_to_uint(&cnt[3])
);
- } /* if */
-} /* csv_dump_graph */
+ }
+}
/**
* dumps the IRG
(void) dmp;
(void) tbl;
/* FIXME: NYI */
-} /* csv_dump_const_tbl */
+}
/**
* dumps the parameter distribution table
(void) tbl;
(void) global;
/* FIXME: NYI */
-} /* csv_dump_param_tbl */
+}
/**
* dumps the optimization counter
(void) tbl;
(void) len;
/* FIXME: NYI */
-} /* csv_dump_opt_cnt */
+}
/**
* initialize the simple dumper
dmp->f = fopen(fname, "a");
if (! dmp->f)
perror(fname);
-} /* csv_init */
+}
/**
* finishes the simple dumper
if (dmp->f)
fclose(dmp->f);
dmp->f = NULL;
-} /* csv_finish */
+}
/**
* the simple human readable dumper