From 1d652478a6e5ab6aa83f806a40d2251b2a1f1ec6 Mon Sep 17 00:00:00 2001 From: Adam Szalkowski Date: Mon, 4 Sep 2006 12:36:22 +0000 Subject: [PATCH] changed api and inserted into bemain --- ir/be/bemain.c | 2 + ir/be/beprofile.c | 138 ++++++++++++++++++++++++++++++++++++++-------- ir/be/beprofile.h | 20 ++++++- 3 files changed, 134 insertions(+), 26 deletions(-) diff --git a/ir/be/bemain.c b/ir/be/bemain.c index 23dc3bb40..c02916441 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -420,6 +420,7 @@ static void be_main_loop(FILE *file_handle) ir_graph *prof_init_irg = be_profile_instrument(); pset_insert_ptr(env.arch_env->constructor_entities, get_irg_entity(prof_init_irg)); } + be_profile_read("test.c"); //FIXME /* For all graphs */ for (i = 0, n = get_irp_n_irgs(); i < n; ++i) { @@ -660,6 +661,7 @@ static void be_main_loop(FILE *file_handle) free_ir_graph(irg); } + be_profile_free(); be_done_env(&env); #undef BE_TIMER_POP diff --git a/ir/be/beprofile.c b/ir/be/beprofile.c index 03bb66982..9e0e30fed 100644 --- a/ir/be/beprofile.c +++ b/ir/be/beprofile.c @@ -52,17 +52,31 @@ #include #endif /* WITH_LIBCORE */ -typedef struct _block_id_walker_data { +#include "beprofile.h" + +typedef struct _block_id_walker_data_t { tarval **array; unsigned int id; ir_node *symconst; -} block_id_walker_data; +} block_id_walker_data_t; + +typedef struct _execcount_t { + unsigned int block; + unsigned int count; +} execcount_t; + +static int +cmp_execcount(const void * a, const void * b, size_t size) +{ + return ((execcount_t*)a)->block != ((execcount_t*)b)->block; +} static void block_counter(ir_node * bb, void * data) { unsigned int *count = data; *count = *count + 1; + } static unsigned int @@ -74,6 +88,9 @@ count_blocks(ir_graph * irg) return count; } +/* keep the execcounts here because they are only read once per compiler run */ +static set * profile = NULL; + /** * Instrument a block with code needed for profiling */ @@ -104,29 +121,31 @@ instrument_block(ir_node * bb, ir_node * address, unsigned int id) * Generates a new irg which calls the initializer */ static ir_graph * -gen_initializer_irg(entity * bblock_id, entity * bblock_counts, int n_blocks) +gen_initializer_irg(entity * ent_filename, entity * bblock_id, entity * bblock_counts, int n_blocks) { ir_node *start_block; - ir_node *ins[3]; + ir_node *ins[4]; ident *name = new_id_from_str("__firmprof_initializer"); entity *ent = new_entity(get_glob_type(), name, new_type_method(name, 0, 0)); ir_node *ret, *call, *symconst; symconst_symbol sym; ident *init_name = new_id_from_str("__init_firmprof"); - ir_type *init_type = new_type_method(init_name, 3, 0); - ir_type *uint, *uintptr; + ir_type *init_type = new_type_method(init_name, 4, 0); + ir_type *uint, *uintptr, *string; entity *init_ent; ir_graph *irg; ir_node *bb; uint = new_type_primitive(new_id_from_str("__uint"), mode_Iu); uintptr = new_type_pointer(new_id_from_str("__uintptr"), uint, mode_P); + string = new_type_pointer(new_id_from_str("__charptr"), new_type_primitive(new_id_from_str("__char"), mode_Bs), mode_P); - set_method_param_type(init_type, 0, uintptr); + set_method_param_type(init_type, 0, string); set_method_param_type(init_type, 1, uintptr); - set_method_param_type(init_type, 2, uint); + set_method_param_type(init_type, 2, uintptr); + set_method_param_type(init_type, 3, uint); init_ent = new_entity(get_glob_type(), init_name, init_type); irg = new_ir_graph(ent, 0); @@ -139,11 +158,13 @@ gen_initializer_irg(entity * bblock_id, entity * bblock_counts, int n_blocks) sym.entity_p = init_ent; symconst = new_r_SymConst(irg, start_block, sym, symconst_addr_ent); - sym.entity_p = bblock_id; + sym.entity_p = ent_filename; ins[0] = new_r_SymConst(irg, start_block, sym, symconst_addr_ent); - sym.entity_p = bblock_counts; + sym.entity_p = bblock_id; ins[1] = new_r_SymConst(irg, start_block, sym, symconst_addr_ent); - ins[2] = new_r_Const_long(irg, start_block, mode_Iu, n_blocks); + sym.entity_p = bblock_counts; + ins[2] = new_r_SymConst(irg, start_block, sym, symconst_addr_ent); + ins[3] = new_r_Const_long(irg, start_block, mode_Iu, n_blocks); call = new_r_Call( irg, bb, //ir_node * block, @@ -174,7 +195,7 @@ gen_initializer_irg(entity * bblock_id, entity * bblock_counts, int n_blocks) static void block_id_walker(ir_node * bb, void * data) { - block_id_walker_data *wd = data; + block_id_walker_data_t *wd = data; wd->array[wd->id] = new_tarval_from_long(get_irn_node_nr(bb), mode_Iu); instrument_block(bb, wd->symconst, wd->id); @@ -184,26 +205,33 @@ block_id_walker(ir_node * bb, void * data) ir_graph * be_profile_instrument(void) { - ir_graph *const_irg = get_const_code_irg(); - ir_node *const_block = get_irg_start_block(const_irg); + ir_graph *const_irg = get_const_code_irg(); + ir_node *const_block = get_irg_start_block(const_irg); int n, i; unsigned int n_blocks = 0; - entity *bblock_id, *bblock_counts, *bblock_count; - ir_type *array_type, *integer_type; - tarval **tarval_array; + entity *bblock_id, *bblock_counts, *bblock_count, *ent_filename; + ir_type *array_type, *integer_type, *string_type, *character_type; + tarval **tarval_array, **tarval_string; + char *filename = "test.c"; //FIXME + int filename_len = strlen(filename)+1; - block_id_walker_data wd; + block_id_walker_data_t wd; symconst_symbol sym; integer_type = new_type_primitive(new_id_from_str("__uint"), mode_Iu); array_type = new_type_array(new_id_from_str("__block_info_array"), 1, integer_type); set_array_bounds_int(array_type, 0, 0, n_blocks); + character_type = new_type_primitive(new_id_from_str("__char"), mode_Bs); + string_type = new_type_array(new_id_from_str("__function_name"), 1, character_type); + set_array_bounds_int(string_type, 0, 0, filename_len); bblock_id = new_entity(get_glob_type(), new_id_from_str("__BLOCK_IDS"), array_type); set_entity_variability(bblock_id, variability_initialized); bblock_counts = new_entity(get_glob_type(), new_id_from_str("__BLOCK_COUNTS"), array_type); set_entity_variability(bblock_counts, variability_initialized); bblock_count = new_entity(get_glob_type(), new_id_from_str("__N_BLOCKS"), integer_type); set_entity_variability(bblock_count, variability_initialized); + ent_filename = new_entity(get_glob_type(), new_id_from_str("__FUNCTION_NAME"), string_type); + set_entity_variability(ent_filename, variability_initialized); for (n = get_irp_n_irgs()-1; n>=0; --n) { ir_graph *irg = get_irp_irg(n); @@ -212,7 +240,7 @@ be_profile_instrument(void) } /* initialize count array */ - tarval_array = alloca(sizeof(tarval_array[0]) * n_blocks); + tarval_array = alloca(sizeof(*tarval_array) * n_blocks); for(i = 0; i < n_blocks; ++i) { tarval_array[i] = get_tarval_null(mode_Iu); } @@ -221,8 +249,13 @@ be_profile_instrument(void) /* initialize the block count entity */ set_atomic_ent_value(bblock_count, new_r_Const_long(const_irg, const_block, mode_Iu, n_blocks)); - /* generate a symbolic constant pointing to the count array */ - sym.entity_p = bblock_count; + /* initialize function name string constant */ + tarval_string = alloca(sizeof(*tarval_string) * (filename_len)); + for(i = 0; i < filename_len; ++i) { + tarval_string[i] = new_tarval_from_long(filename[i], mode_Bs); + } + set_array_entity_values(ent_filename, tarval_string, filename_len); + /* initialize block id array and instrument blocks */ wd.array = tarval_array; @@ -230,18 +263,77 @@ be_profile_instrument(void) for (n = get_irp_n_irgs()-1; n>=0; --n) { ir_graph *irg = get_irp_irg(n); + /* generate a symbolic constant pointing to the count array */ + sym.entity_p = bblock_count; wd.symconst = new_r_SymConst(irg, get_irg_start_block(irg), sym, symconst_addr_ent); irg_block_walk_graph(irg, block_id_walker, NULL, &wd); } set_array_entity_values(bblock_id, tarval_array, n_blocks); - return gen_initializer_irg(bblock_id, bblock_counts, n_blocks); + return gen_initializer_irg(ent_filename, bblock_id, bblock_counts, n_blocks); } +/** + * Reads the corresponding profile info file if it exists and returns a + * profile info struct + */ void -be_profile_read(void) +be_profile_read(char * filename) { + FILE *f; + char buf[8]; + size_t ret; + + f = fopen(filename, "r"); + + /* check magic */ + ret = fread(buf, 8, 1, f); + if(ret == 0 || strncmp(buf, "firmprof", 8) != 0) { + return; + } + if(profile) be_profile_free(); + profile = new_set(cmp_execcount, 16); + + do { + execcount_t query; + ret = fread(&query, sizeof(unsigned int), 2, f); + + if(ret != 2) break; + + set_insert(profile, &query, sizeof(query), query.block); + } while(1); +} + +/** + * Frees the profile info + */ +void +be_profile_free(void) +{ + if(profile) + del_set(profile); +} + +/** + * Get block execution count as determined be profiling + */ +unsigned int +be_profile_get_block_execcount(const ir_node * block) +{ + execcount_t *ec, query; + + if(!profile) + return 1; + + query.block = get_irn_node_nr(block); + ec = set_find(profile, &query, sizeof(query), get_irn_node_nr(block)); + + if(ec) { + return ec->count; + } else { + return 1; + } } diff --git a/ir/be/beprofile.h b/ir/be/beprofile.h index f72014d6b..6cc173984 100644 --- a/ir/be/beprofile.h +++ b/ir/be/beprofile.h @@ -14,11 +14,25 @@ #define _BEPROFILE_H_ /** - * Instruments irgs with profile code. + * Instruments irgs with profile code * @return The irg doing the profile initialization. */ -ir_graph *be_profile_instrument(void); +ir_graph * be_profile_instrument(void); -void be_profile_read(void); +/** + * Reads the corresponding profile info file if it exists and returns a + * profile info struct + */ +void be_profile_read(char * filename); + +/** + * Frees the profile info + */ +void be_profile_free(); + +/** + * Get block execution count as determined be profiling + */ +unsigned int be_profile_get_block_execcount(const ir_node * block); #endif /* _BEPROFILE_H_ */ -- 2.20.1