/**
* names of the optimizations
*/
-static const char *opt_names[] = {
- "straightening optimization",
- "if simplification",
- "constant evaluation",
- "algebraic simplification",
- "Phi optmization",
- "Write-After-Write optimization",
- "Write-After-Read optimization",
- "Read-After-Write optimization",
- "Read-After-Read optimization",
- "Read-a-Const optimization",
- "Tuple optimization",
- "ID optimization",
- "Common subexpression elimination",
- "Strength reduction",
- "Architecture dependant optimization",
- "Reassociation optimization",
- "Polymorphic call optimization",
- "an if conversion was tried",
- "Lowered",
+static const struct {
+ hook_opt_kind kind;
+ const char *name;
+} opt_names[] = {
+ { HOOK_OPT_DEAD_BLOCK, "dead block elimination" },
+ { HOOK_OPT_STG, "straightening optimization" },
+ { HOOK_OPT_IFSIM, "if simplification" },
+ { HOOK_OPT_CONST_EVAL, "constant evaluation" },
+ { HOOK_OPT_ALGSIM, "algebraic simplification" },
+ { HOOK_OPT_PHI, "Phi optmization" },
+ { HOOK_OPT_SYNC, "Sync optmization" },
+ { HOOK_OPT_WAW, "Write-After-Write optimization" },
+ { HOOK_OPT_WAR, "Write-After-Read optimization" },
+ { HOOK_OPT_RAW, "Read-After-Write optimization" },
+ { HOOK_OPT_RAR, "Read-After-Read optimization" },
+ { HOOK_OPT_RC, "Read-a-Const optimization" },
+ { HOOK_OPT_TUPLE, "Tuple optimization" },
+ { HOOK_OPT_ID, "ID optimization" },
+ { HOOK_OPT_CSE, "Common subexpression elimination" },
+ { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
+ { HOOK_OPT_ARCH_DEP, "Architecture dependant optimization" },
+ { HOOK_OPT_REASSOC, "Reassociation optimization" },
+ { HOOK_OPT_POLY_CALL, "Polymorphic call optimization" },
+ { HOOK_OPT_IF_CONV, "an if conversion was tried" },
+ { HOOK_OPT_FUNC_CALL, "Real function call optimization" },
+ { HOOK_OPT_CONFIRM, "Confirm-based optimization: replacement" },
+ { HOOK_OPT_CONFIRM_C, "Confirm-based optimization: replaced by const" },
+ { HOOK_OPT_CONFIRM_E, "Confirm-based optimization: evaluated" },
+ { HOOK_OPT_EXC_REM, "a exception edge was removed due to a Confirmation prove" },
+ { HOOK_LOWERED, "Lowered" },
+ { HOOK_BACKEND, "Backend transformation" },
+ { FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
+ { FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
+ { FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
+ { FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
+ { FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
+ { FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
+ { FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
+ { FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
+ { FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
+ { FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
+ { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = a" },
+ { FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
+ { FS_OPT_EOR_TO_NOT_BOOL,"algebraic simplification: bool ^ 1 = !bool" },
+ { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x" },
+ { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
+ { FS_OPT_OR_SHFT_TO_ROT, "algebraic simplification: (x << c) | (x >> (bits - c)) == Rot(x, c)" },
+ { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
+ { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
+ { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
+ { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
+ { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
+ { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
+ { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(a, b, c) = b OR Mux(a,b, c) = c" },
+ { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
+ { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
+ { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > b, a, b) = Abs(a,b)" },
+ { FS_OPT_MUX_TO_SHR, "algebraic simplification: Mux(a > b, a, b) = a >> b" },
+ { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
+ { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
+ { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
+ { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
+ { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
+ { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
+ { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
+ { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
+ { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
+ { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
+ { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
};
static const char *if_conv_names[IF_RESULT_LAST] = {
{
opt_entry_t *entry = pset_first(set);
+ assert(index < ARR_SIZE(opt_names) && "index out of range");
+ assert(opt_names[index].kind == index && "opt_names broken");
if (entry) {
- fprintf(dmp->f, "\n%s:\n", opt_names[index]);
+ fprintf(dmp->f, "\n%s:\n", opt_names[index].name);
fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
for (; entry; entry = pset_next(set)) {
}
}
+/**
+ * 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 = pset_first(entry->be_block_hash);
+ reg_pressure_entry_t *rp_entry;
+
+ /* return if no reg pressure information available */
+ if (! b_entry)
+ return;
+
+ /* print table head (register classes) */
+ fprintf(dmp->f, "\nREG PRESSURE:\n");
+ fprintf(dmp->f, "%12s", "Block Nr");
+ for (rp_entry = pset_first(b_entry->reg_pressure);
+ rp_entry;
+ rp_entry = pset_next(b_entry->reg_pressure))
+ {
+ fprintf(dmp->f, "%15s", get_id_str(rp_entry->id_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 = pset_next(entry->be_block_hash))
+ {
+ fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
+ for (rp_entry = pset_first(b_entry->reg_pressure);
+ rp_entry;
+ rp_entry = pset_next(b_entry->reg_pressure))
+ {
+ fprintf(dmp->f, "%15d", rp_entry->pressure);
+ }
+ fprintf(dmp->f, "\n");
+ }
+}
+
/**
* dumps the number of real_function_call optimization
*/
static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
{
+ if (! dmp->f)
+ return;
+
if (! cnt_eq(cnt, 0)) {
fprintf(dmp->f, "\nReal Function Calls optimized:\n");
fprintf(dmp->f, "%-16s %8u\n",
*/
static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
{
+ if (! dmp->f)
+ return;
+
if (num_tail_recursion > 0) {
fprintf(dmp->f, "\nTail recursion optimized:\n");
fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
*/
static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
{
+ if (! dmp->f)
+ return;
+
fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
}
{
int i, dump_opts = 1;
block_entry_t *b_entry;
+ extbb_entry_t *eb_entry;
+
+ if (! dmp->f)
+ return;
if (entry->irg) {
ir_graph *const_irg = get_const_code_irg();
}
fprintf(dmp->f, " %swalked %u over blocks %u:\n"
- " was inlined : %u\n"
- " got inlined : %u\n"
- " strength red : %u\n"
- " leaf function : %s\n"
- " calls only leaf functions : %s\n"
- " recursive : %s\n"
- " chain call : %s\n"
+ " was inlined : %u\n"
+ " got inlined : %u\n"
+ " strength red : %u\n"
+ " leaf function : %s\n"
+ " calls only leaf functions : %s\n"
+ " recursive : %s\n"
+ " chain call : %s\n"
" calls : %u\n"
" indirect calls : %u\n",
entry->is_deleted ? "DELETED " : "",
entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
entry->cnt_was_inlined.cnt[0],
entry->cnt_got_inlined.cnt[0],
- entry->cnt_strength_red.cnt[0],
- entry->is_leaf ? "YES" : "NO",
- entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
- entry->is_recursive ? "YES" : "NO",
- entry->is_chain_call ? "YES" : "NO",
+ entry->cnt_strength_red.cnt[0],
+ entry->is_leaf ? "YES" : "NO",
+ entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
+ entry->is_recursive ? "YES" : "NO",
+ entry->is_chain_call ? "YES" : "NO",
entry->cnt_all_calls.cnt[0],
entry->cnt_indirect_calls.cnt[0]
- );
+ );
for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
fprintf(dmp->f, " %s : %u\n", if_conv_names[i], entry->cnt_if_conv[i].cnt[0]);
for (b_entry = pset_first(entry->block_hash);
b_entry;
b_entry = pset_next(entry->block_hash)) {
- fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %12u %4.8f\n",
+ fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f\n",
b_entry->block_nr,
b_entry->cnt_nodes.cnt[0],
b_entry->cnt_edges.cnt[0],
b_entry->cnt_in_edges.cnt[0],
b_entry->cnt_out_edges.cnt[0],
- b_entry->cnt_phi_data.cnt[0],
+ b_entry->cnt_phi_data.cnt[0],
(double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
);
}
+
+ /* dump block reg pressure */
+ simple_dump_be_block_reg_pressure(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");
+ for (eb_entry = pset_first(entry->extbb_hash);
+ eb_entry;
+ eb_entry = pset_next(entry->extbb_hash)) {
+ fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
+ eb_entry->block_nr,
+ eb_entry->cnt_nodes.cnt[0],
+ eb_entry->cnt_edges.cnt[0],
+ eb_entry->cnt_in_edges.cnt[0],
+ eb_entry->cnt_out_edges.cnt[0],
+ eb_entry->cnt_phi_data.cnt[0],
+ (double)eb_entry->cnt_edges.cnt[0] / (double)eb_entry->cnt_nodes.cnt[0]
+ );
+ }
+ }
}
}
static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
{
int i;
+ counter_t sum;
+
+ if (! dmp->f)
+ return;
+
+ cnt_clr(&sum);
fprintf(dmp->f, "\nConstant Information:\n");
fprintf(dmp->f, "---------------------\n");
fprintf(dmp->f, "\nBit usage for integer constants\n");
fprintf(dmp->f, "-------------------------------\n");
- for (i = 0; i < ARR_SIZE(tbl->bits_count); ++i)
- fprintf(dmp->f, "%3d %12u\n", i + 1, tbl->bits_count[i].cnt[0]);
+ for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
+ fprintf(dmp->f, "%5d %12u\n", i + 1, tbl->int_bits_count[i].cnt[0]);
+ cnt_add(&sum, &tbl->int_bits_count[i]);
+ }
+ fprintf(dmp->f, "-------------------------------\n");
+
+ fprintf(dmp->f, "\nFloating point constants classification\n");
+ fprintf(dmp->f, "--------------------------------------\n");
+ for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
+ fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), tbl->floats[i].cnt[0]);
+ cnt_add(&sum, &tbl->floats[i]);
+ }
+ fprintf(dmp->f, "--------------------------------------\n");
+
+ fprintf(dmp->f, "other %12u\n", tbl->others.cnt[0]);
+ cnt_add(&sum, &tbl->others);
fprintf(dmp->f, "-------------------------------\n");
+
+ fprintf(dmp->f, "sum %12u\n", sum.cnt[0]);
}
/**
snprintf(fname, sizeof(fname), "%s.txt", name);
dmp->f = fopen(fname, "w");
+ if (! dmp->f) {
+ perror(fname);
+ }
}
/**
*/
static void simple_finish(dumper_t *dmp)
{
- fclose(dmp->f);
+ if (dmp->f)
+ fclose(dmp->f);
dmp->f = NULL;
}
static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
{
const char *name;
-
counter_t cnt[4];
+ if (! dmp->f)
+ return;
+
if (entry->irg && !entry->is_deleted) {
ir_graph *const_irg = get_const_code_irg();
snprintf(fname, sizeof(fname), "%s.csv", name);
dmp->f = fopen(fname, "a");
+ if (! dmp->f) {
+ perror(fname);
+ }
}
/**
*/
static void csv_finish(dumper_t *dmp)
{
- fclose(dmp->f);
+ if (dmp->f)
+ fclose(dmp->f);
dmp->f = NULL;
}