X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firprofile.c;h=dd6eb5afc1971b236f5e4e8ba9d0acf23510c4a7;hb=01c4c27c4b7824dd0020f6fd2218edbe9ab40548;hp=70e2340094348644e8bb81b7d05cede59fd2c95b;hpb=71eed76d21d0ec16f6a220879e3290a03d35c6fe;p=libfirm diff --git a/ir/ir/irprofile.c b/ir/ir/irprofile.c index 70e234009..dd6eb5afc 100644 --- a/ir/ir/irprofile.c +++ b/ir/ir/irprofile.c @@ -39,10 +39,9 @@ #include "irdump_t.h" #include "irnode_t.h" #include "ircons_t.h" -#include "execfreq.h" -#include "typerep.h" - +#include "execfreq_t.h" #include "irprofile.h" +#include "typerep.h" /* Instrument blocks walker. */ typedef struct block_id_walker_data_t { @@ -56,12 +55,6 @@ typedef struct block_assoc_t { unsigned int *counters; /**< block execution counts */ } block_assoc_t; -typedef struct intialize_execfreq_env_t { - ir_graph *irg; - ir_exec_freq *execfreqs; - double freq_factor; -} initialize_execfreq_env_t; - /* minimal execution frequency (an execfreq of 0 confuses algos) */ #define MIN_EXECFREQ 0.00001 @@ -80,7 +73,7 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg;) */ typedef struct execcount_t { unsigned long block; /**< block id */ - unsigned int count; /**< execution count */ + uint32_t count; /**< execution count */ } execcount_t; /** @@ -94,6 +87,22 @@ static int cmp_execcount(const void *a, const void *b, size_t size) return ea->block != eb->block; } +uint32_t ir_profile_get_block_execcount(const ir_node *block) +{ + execcount_t *ec, query; + + query.block = get_irn_node_nr(block); + ec = set_find(execcount_t, profile, &query, sizeof(query), query.block); + + if (ec != NULL) { + return ec->count; + } else { + DBG((dbg, LEVEL_3, + "Warning: Profile contains no data for %+F\n", block)); + return 0; + } +} + /** * Block walker, count number of blocks. */ @@ -463,14 +472,6 @@ static ir_entity *new_static_string_entity(ident *name, const char *string) return result; } -/** - * Instrument all ir_graphs in the current ir_program. Currently this only - * works for graphs in the backend. Additionally, the resulting program - * has to be linked with libfirmprof. - * - * @param filename the name of the profile file (usually module_name.prof) - * @returns the module initializer, may be NULL - */ ir_graph *ir_profile_instrument(const char *filename) { int n, n_blocks = 0; @@ -506,14 +507,8 @@ ir_graph *ir_profile_instrument(const char *filename) return gen_initializer_irg(ent_filename, bblock_counts, n_blocks); } -static unsigned int * -parse_profile(const char *filename, unsigned int num_blocks) +static unsigned int *parse_profile(const char *filename, unsigned int num_blocks) { - unsigned int *result = NULL; - char buf[8]; - size_t ret; - unsigned int i; - FILE *f = fopen(filename, "rb"); if (!f) { DBG((dbg, LEVEL_2, "Failed to open profile file (%s)\n", filename)); @@ -521,7 +516,9 @@ parse_profile(const char *filename, unsigned int num_blocks) } /* check header */ - ret = fread(buf, 8, 1, f); + uint32_t *result = NULL; + char buf[8]; + size_t ret = fread(buf, 8, 1, f); if (ret == 0 || strncmp(buf, "firmprof", 8) != 0) { DBG((dbg, LEVEL_2, "Broken fileheader in profile\n")); goto end; @@ -531,7 +528,7 @@ parse_profile(const char *filename, unsigned int num_blocks) /* The profiling output format is defined to be a sequence of integer * values stored little endian format. */ - for (i = 0; i < num_blocks; ++i) { + for (unsigned i = 0; i < num_blocks; ++i) { unsigned char bytes[4]; if ((ret = fread(bytes, 1, 4, f)) < 1) @@ -556,7 +553,6 @@ end: /** * Reads the corresponding profile info file if it exists. */ - static void block_associate_walker(ir_node *bb, void *env) { block_assoc_t *b = (block_assoc_t*) env; @@ -566,43 +562,17 @@ static void block_associate_walker(ir_node *bb, void *env) query.count = b->counters[(b->i)++]; DBG((dbg, LEVEL_4, "execcount(%+F, %u): %u\n", bb, query.block, query.count)); - set_insert(profile, &query, sizeof(query), query.block); + (void)set_insert(execcount_t, profile, &query, sizeof(query), query.block); } static void irp_associate_blocks(block_assoc_t *env) { - int n; - for (n = get_irp_n_irgs() - 1; n >= 0; --n) { + for (int n = get_irp_n_irgs() - 1; n >= 0; --n) { ir_graph *irg = get_irp_irg(n); irg_block_walk_graph(irg, block_associate_walker, NULL, env); } } -bool ir_profile_read(const char *filename) -{ - block_assoc_t env; - FIRM_DBG_REGISTER(dbg, "firm.ir.profile"); - - env.i = 0; - env.counters = parse_profile(filename, get_irp_n_blocks()); - if (!env.counters) - return false; - - if (profile) - ir_profile_free(); - profile = new_set(cmp_execcount, 16); - - irp_associate_blocks(&env); - xfree(env.counters); - - /* register the vcg hook */ - hook = dump_add_node_info_callback(dump_profile_node_info, NULL); - return true; -} - -/** - * Frees the profile info - */ void ir_profile_free(void) { if (profile) { @@ -616,43 +586,40 @@ void ir_profile_free(void) } } -/** - * Tells whether profile module has acquired data - */ -bool ir_profile_has_data(void) +bool ir_profile_read(const char *filename) { - return profile != NULL; -} + block_assoc_t env; + FIRM_DBG_REGISTER(dbg, "firm.ir.profile"); -/** - * Get block execution count as determined by profiling - */ -unsigned int ir_profile_get_block_execcount(const ir_node *block) -{ - execcount_t *ec, query; + unsigned n_blocks = get_irp_n_blocks(); + env.i = 0; + env.counters = parse_profile(filename, n_blocks); + if (!env.counters) + return false; - if (!ir_profile_has_data()) - return 1; + ir_profile_free(); + profile = new_set(cmp_execcount, 16); - query.block = get_irn_node_nr(block); - ec = (execcount_t*)set_find(profile, &query, sizeof(query), query.block); + irp_associate_blocks(&env); + xfree(env.counters); - if (ec != NULL) { - return ec->count; - } else { - DBG((dbg, LEVEL_3, - "Warning: Profile contains no data for %+F\n", block)); - return 1; - } + /* register the vcg hook */ + hook = dump_add_node_info_callback(dump_profile_node_info, NULL); + return 1; } +typedef struct initialize_execfreq_env_t { + double freq_factor; +} initialize_execfreq_env_t; + static void initialize_execfreq(ir_node *block, void *data) { - initialize_execfreq_env_t *env = (initialize_execfreq_env_t*)data; + const initialize_execfreq_env_t *env + = (const initialize_execfreq_env_t*) data; + ir_graph *irg = get_irn_irg(block); double freq; - if (block == get_irg_start_block(env->irg) - || block == get_irg_end_block(env->irg)) { + if (block == get_irg_start_block(irg) || block == get_irg_end_block(irg)) { freq = 1.0; } else { freq = ir_profile_get_block_execcount(block); @@ -661,29 +628,29 @@ static void initialize_execfreq(ir_node *block, void *data) freq = MIN_EXECFREQ; } - set_execfreq(env->execfreqs, block, freq); + set_block_execfreq(block, freq); } -ir_exec_freq *ir_create_execfreqs_from_profile(ir_graph *irg) +static void ir_set_execfreqs_from_profile(ir_graph *irg) { - ir_node *start_block; - initialize_execfreq_env_t env; - unsigned count; - - env.irg = irg; - env.execfreqs = create_execfreq(irg); - /* Find the first block containing instructions */ - start_block = get_irg_start_block(irg); - count = ir_profile_get_block_execcount(start_block); + ir_node *start_block = get_irg_start_block(irg); + unsigned count = ir_profile_get_block_execcount(start_block); if (count == 0) { /* the function was never executed, so fallback to estimated freqs */ - free_execfreq(env.execfreqs); - return compute_execfreq(irg, 10); + ir_estimate_execfreq(irg); + return; } + initialize_execfreq_env_t env; env.freq_factor = 1.0 / count; irg_block_walk_graph(irg, initialize_execfreq, NULL, &env); +} - return env.execfreqs; +void ir_create_execfreqs_from_profile(void) +{ + for (int n = get_irp_n_irgs() - 1; n >= 0; --n) { + ir_graph *irg = get_irp_irg(n); + ir_set_execfreqs_from_profile(irg); + } }