X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbessaconstr.c;h=257ea7238aaf1a010d6fb85f52d15610bf5fad99;hb=333bc9c7aba2e2dbb8a3f108e73d6fd1c95dcc9f;hp=ae2d19495a90fe1f99fe5518c656c527cebc58b5;hpb=39f3a8dbd0f00f90b7b12a849d1bf7b9c1329479;p=libfirm diff --git a/ir/be/bessaconstr.c b/ir/be/bessaconstr.c index ae2d19495..257ea7238 100644 --- a/ir/be/bessaconstr.c +++ b/ir/be/bessaconstr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -29,11 +29,11 @@ * to their closest copy while introducing phis as necessary. * * Algorithm: Mark all blocks in the iterated dominance frontiers of the value - * and it's copies. Link the copies ordered by dominance to the blocks. The - * we search for each use all all definitions in the current block, if none is + * and it's copies. Link the copies ordered by dominance to the blocks. Then + * we search for each use all definitions in the current block, if none is * found, then we search one in the immediate dominator. If we are in a block - * of the dominance frontier, create a phi and search do the same search for - * the phi arguments. + * of the dominance frontier, create a phi and do the same search for all + * phi arguments. * * A copy in this context means, that you want to introduce several new * abstract values (in Firm: nodes) for which you know, that they @@ -53,8 +53,9 @@ #include "bessaconstr.h" #include "bemodule.h" #include "besched_t.h" -#include "bera.h" +#include "beintlive_t.h" #include "beirg_t.h" +#include "be_t.h" #include "debug.h" #include "error.h" @@ -67,35 +68,58 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) +/** + * Checks that low <= what < hi. + */ +static INLINE int is_inside(unsigned what, unsigned low, unsigned hi) +{ + return what - low < hi; +} + /** * Calculates the iterated dominance frontier of a set of blocks. Marks the * blocks as visited. Sets the link fields of the blocks in the dominance * frontier to the block itself. */ static -void mark_iterated_dominance_frontiers(const be_dom_front_info_t *domfronts, - waitq *worklist) +void mark_iterated_dominance_frontiers(const be_ssa_construction_env_t *env) { + stat_ev_cnt_decl(blocks); DBG((dbg, LEVEL_3, "Dominance Frontier:")); - while(!pdeq_empty(worklist)) { + stat_ev_tim_push(); + while (!waitq_empty(env->worklist)) { int i; - ir_node *block = waitq_get(worklist); - ir_node **domfront = be_get_dominance_frontier(domfronts, block); + ir_node *block = waitq_get(env->worklist); + ir_node **domfront = be_get_dominance_frontier(env->domfronts, block); int domfront_len = ARR_LEN(domfront); for (i = 0; i < domfront_len; ++i) { ir_node *y = domfront[i]; - if(Block_block_visited(y)) + if (Block_block_visited(y)) + continue; + + /* + * It makes no sense to add phi-functions to blocks + * that are not dominated by any definition; + * all uses are dominated, hence the paths reaching the uses + * have to stay in the dominance subtrees of the given definitions. + */ + + if (!is_inside(get_Block_dom_tree_pre_num(y), env->min_dom, env->max_dom)) continue; - if(!irn_visited(y)) { + if (!irn_visited(y)) { set_irn_link(y, NULL); - waitq_put(worklist, y); + waitq_put(env->worklist, y); } + DBG((dbg, LEVEL_3, " %+F", y)); mark_Block_block_visited(y); + stat_ev_cnt_inc(blocks); } } + stat_ev_tim_pop("bessaconstr_idf_time"); + stat_ev_cnt_done(blocks, "bessaconstr_idf_blocks"); DBG((dbg, LEVEL_3, "\n")); } @@ -144,9 +168,8 @@ static ir_node *get_def_at_idom(be_ssa_construction_env_t *env, ir_node *block) { ir_node *dom = get_Block_idom(block); - ir_node *def = search_def_end_of_block(env, dom); - - return def; + assert(dom != NULL); + return search_def_end_of_block(env, dom); } static @@ -161,7 +184,6 @@ ir_node *search_def_end_of_block(be_ssa_construction_env_t *env, ir_node *block) ir_node *def = get_def_at_idom(env, block); mark_irn_visited(block); set_irn_link(block, def); - return def; } } @@ -203,11 +225,20 @@ ir_node *search_def(be_ssa_construction_env_t *env, ir_node *at) return create_phi(env, block, node); } - DBG((dbg, LEVEL_3, "\t...continue at idom (after checking block)\n")); return get_def_at_idom(env, block); } +static +void update_domzone(be_ssa_construction_env_t *env, const ir_node *bl) +{ + int start = get_Block_dom_tree_pre_num(bl); + int end = get_Block_dom_max_subtree_pre_num(bl) + 1; + + env->min_dom = MIN(env->min_dom, start); + env->max_dom = MAX(env->max_dom, end); +} + /** * Adds a definition into the link field of the block. The definitions are * sorted by dominance. A non-visited block means no definition has been @@ -245,16 +276,26 @@ void introduce_def_at_block(ir_node *block, ir_node *def) void be_ssa_construction_init(be_ssa_construction_env_t *env, be_irg_t *birg) { ir_graph *irg = be_get_birg_irg(birg); - memset(env, 0, sizeof(env[0])); + ir_node *sb = get_irg_start_block(irg); + int n_blocks = get_Block_dom_max_subtree_pre_num(sb); + stat_ev_ctx_push_fobj("bessaconstr", irg); + stat_ev_tim_push(); + + (void) n_blocks; + stat_ev_dbl("bessaconstr_n_blocks", n_blocks); + + memset(env, 0, sizeof(env[0])); be_assure_dom_front(birg); env->irg = irg; env->domfronts = be_get_birg_dom_front(birg); env->new_phis = NEW_ARR_F(ir_node*, 0); env->worklist = new_waitq(); + env->min_dom = INT_MAX; + env->max_dom = 0; - set_using_visited(irg); + set_using_irn_visited(irg); set_using_block_visited(irg); set_using_irn_link(irg); @@ -262,18 +303,22 @@ void be_ssa_construction_init(be_ssa_construction_env_t *env, be_irg_t *birg) * and blocks that already have the relevant value at the end calculated */ inc_irg_visited(irg); /* We use the block visited flag to indicate blocks in the dominance - * froniter of some values (and this potentially needing phis) */ + * frontier of some values (and this potentially needing phis) */ inc_irg_block_visited(irg); } void be_ssa_construction_destroy(be_ssa_construction_env_t *env) { + stat_ev_int("bessaconstr_phis", ARR_LEN(env->new_phis)); del_waitq(env->worklist); DEL_ARR_F(env->new_phis); - clear_using_visited(env->irg); + clear_using_irn_visited(env->irg); clear_using_block_visited(env->irg); clear_using_irn_link(env->irg); + + stat_ev_tim_pop("bessaconstr_total_time"); + stat_ev_ctx_pop("bessaconstr"); } void be_ssa_construction_add_copy(be_ssa_construction_env_t *env, @@ -295,6 +340,7 @@ void be_ssa_construction_add_copy(be_ssa_construction_env_t *env, waitq_put(env->worklist, block); } introduce_def_at_block(block, copy); + update_domzone(env, block); } void be_ssa_construction_add_copies(be_ssa_construction_env_t *env, @@ -317,6 +363,7 @@ void be_ssa_construction_add_copies(be_ssa_construction_env_t *env, waitq_put(env->worklist, block); } introduce_def_at_block(block, copy); + update_domzone(env, block); } } @@ -331,186 +378,84 @@ ir_node **be_ssa_construction_get_new_phis(be_ssa_construction_env_t *env) return env->new_phis; } -void be_ssa_construction_fix_users(be_ssa_construction_env_t *env, - ir_node *value) +void be_ssa_construction_fix_users_array(be_ssa_construction_env_t *env, + ir_node **nodes, size_t nodes_len) { + stat_ev_cnt_decl(uses); const ir_edge_t *edge, *next; + size_t i; + + BE_TIMER_PUSH(t_ssa_constr); if(!env->iterated_domfront_calculated) { - mark_iterated_dominance_frontiers(env->domfronts, env->worklist); + mark_iterated_dominance_frontiers(env); env->iterated_domfront_calculated = 1; } - /* - * Search the valid def for each use and set it. - */ - foreach_out_edge_safe(value, edge, next) { - ir_node *use = get_edge_src_irn(edge); - ir_node *at = use; - int pos = get_edge_src_pos(edge); - ir_node *def; - - if(env->ignore_uses != NULL && - ir_nodeset_contains(env->ignore_uses, use)) - continue; - - if(is_Phi(use)) { - ir_node *block = get_nodes_block(use); - ir_node *predblock = get_Block_cfgpred_block(block, pos); - at = sched_last(predblock); - } + stat_ev_int("bessaconstr_domzone", env->max_dom - env->min_dom); + stat_ev_tim_push(); + for(i = 0; i < nodes_len; ++i) { + ir_node *value = nodes[i]; + + /* + * Search the valid def for each use and set it. + */ + foreach_out_edge_safe(value, edge, next) { + ir_node *use = get_edge_src_irn(edge); + ir_node *at = use; + int pos = get_edge_src_pos(edge); + ir_node *def; + + if(env->ignore_uses != NULL && + ir_nodeset_contains(env->ignore_uses, use)) + continue; + if(is_Anchor(use)) + continue; - def = search_def(env, at); + if(is_Phi(use)) { + ir_node *block = get_nodes_block(use); + ir_node *predblock = get_Block_cfgpred_block(block, pos); + at = sched_last(predblock); + } - if(def == NULL) { - panic("no definition found for %+F at position %d\n", use, pos); - } + def = search_def(env, at); + + if(def == NULL) { + panic("no definition found for %+F at position %d\n", use, pos); + } - DBG((dbg, LEVEL_2, "\t%+F(%d) -> %+F\n", use, pos, def)); - set_irn_n(use, pos, def); + DBG((dbg, LEVEL_2, "\t%+F(%d) -> %+F\n", use, pos, def)); + set_irn_n(use, pos, def); + stat_ev_cnt_inc(uses); + } } + BE_TIMER_POP(t_ssa_constr); + + stat_ev_tim_pop("bessaconstr_fix_time"); + stat_ev_cnt_done(uses, "bessaconstr_uses"); } -void be_ssa_construction_fix_users_array(be_ssa_construction_env_t *env, - ir_node **nodes, size_t nodes_len) +void be_ssa_construction_fix_users(be_ssa_construction_env_t *env, ir_node *value) { - size_t i; - - for(i = 0; i < nodes_len; ++i) { - ir_node *node = nodes[i]; - be_ssa_construction_fix_users(env, node); - } + be_ssa_construction_fix_users_array(env, &value, 1); } + void be_ssa_construction_update_liveness_phis(be_ssa_construction_env_t *env, be_lv_t *lv) { int i, n; + BE_TIMER_PUSH(t_ssa_constr); + n = ARR_LEN(env->new_phis); for(i = 0; i < n; ++i) { ir_node *phi = env->new_phis[i]; be_liveness_introduce(lv, phi); } -} - -#if 0 -ir_node **be_ssa_construction(const be_dom_front_info_t *domfronts, be_lv_t *lv, - ir_node *value, int copies_len, ir_node **copies, - const ir_nodeset_t *ignore_uses, int need_new_phis) -{ - ir_graph *irg = get_irn_irg(value); - const ir_edge_t *edge, *next; - int i; - ir_node *block; - waitq *worklist; - be_ssa_construction_env_t env; - - /* We need to collect the phi functions to compute their liveness. */ - if(lv != NULL || need_new_phis) { - env.new_phis = NEW_ARR_F(ir_node*, 0); - } else { - env.new_phis = NULL; - } - env.mode = get_irn_mode(value); - - set_using_visited(irg); - set_using_block_visited(irg); - set_using_irn_link(irg); - /* we use the visited flag to indicate blocks in the dominance frontier - * and blocks that already have the relevant value at the end calculated */ - inc_irg_visited(irg); - /* We use the block visited flag to indicate blocks in the dominance - * froniter of some values (and this potentially needing phis) */ - inc_irg_block_visited(irg); - - DBG((dbg, LEVEL_1, "Introducing following copies for: %+F\n", value)); - /* compute iterated dominance frontiers and create lists in the block link - * fields that sort usages by dominance. Blocks in the dominance frontier - * are marked by links back to the block. */ - worklist = new_waitq(); - - block = get_nodes_block(value); - /* we sometimes replace virtual values by real ones, in this case we do - not want to insert them into the def list (they're not scheduled - and can't be used anyway) */ - if(sched_is_scheduled(value)) { - introduce_def_at_block(block, value); - } - waitq_put(worklist, block); - - for(i = 0; i < copies_len; ++i) { - ir_node *copy = copies[i]; - block = get_nodes_block(copy); - - if(!irn_visited(block)) { - waitq_put(worklist, block); - } - introduce_def_at_block(block, copy); - DBG((dbg, LEVEL_1, "\t%+F in %+F\n", copy, block)); - } - - mark_iterated_dominance_frontiers(domfronts, worklist); - del_waitq(worklist); - - DBG((dbg, LEVEL_2, "New Definitions:\n")); - /* - * Search the valid def for each use and set it. - */ - foreach_out_edge_safe(value, edge, next) { - ir_node *use = get_edge_src_irn(edge); - ir_node *at = use; - int pos = get_edge_src_pos(edge); - - if(ignore_uses != NULL && ir_nodeset_contains(ignore_uses, use)) - continue; - - if(is_Phi(use)) { - ir_node *block = get_nodes_block(use); - ir_node *predblock = get_Block_cfgpred_block(block, pos); - at = sched_last(predblock); - } - - ir_node *def = search_def(&env, at); - - if(def == NULL) { - panic("no definition found for %+F at position %d\n", use, pos); - } - - DBG((dbg, LEVEL_2, "\t%+F(%d) -> %+F\n", use, pos, def)); - set_irn_n(use, pos, def); - } - - /* Recompute the liveness of the original nodes, the copies and the - * inserted phis. */ - if(lv != NULL) { - int n; - - be_liveness_update(lv, value); - for(i = 0; i < copies_len; ++i) { - ir_node *copy = copies[i]; - be_liveness_update(lv, copy); - } - - n = ARR_LEN(env.new_phis); - for(i = 0; i < n; ++i) { - ir_node *phi = env.new_phis[i]; - be_liveness_introduce(lv, phi); - } - } - - clear_using_visited(irg); - clear_using_block_visited(irg); - clear_using_irn_link(irg); - - if(!need_new_phis && env.new_phis != NULL) { - DEL_ARR_F(env.new_phis); - return NULL; - } - return env.new_phis; + BE_TIMER_POP(t_ssa_constr); } -#endif void be_init_ssaconstr(void) {