X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fjumpthreading.c;h=3a18401acd34b8a46606916126cff470a3ac16e1;hb=8c9921a1fc166552f6e416434fd8394a4fc210a3;hp=34aff8a39e3510fc716f30f2de2390390bb70e54;hpb=ae9fd2c229cc7f4c724ce9ccc9263c16d77670fe;p=libfirm diff --git a/ir/opt/jumpthreading.c b/ir/opt/jumpthreading.c index 34aff8a39..3a18401ac 100644 --- a/ir/opt/jumpthreading.c +++ b/ir/opt/jumpthreading.c @@ -22,7 +22,6 @@ * @brief Path-Sensitive Jump Threading * @date 10. Sep. 2006 * @author Christoph Mallon, Matthias Braun - * @version $Id$ */ #include "config.h" @@ -46,10 +45,11 @@ #include "iropt_dbg.h" #include "irpass.h" #include "vrp.h" +#include "opt_manage.h" #undef AVOID_PHIB -DEBUG_ONLY(static firm_dbg_module_t *dbg); +DEBUG_ONLY(static firm_dbg_module_t *dbg;) /** * Add the new predecessor x to node node, which is either a Block or a Phi @@ -60,7 +60,7 @@ static void add_pred(ir_node* node, ir_node* x) int n; int i; - assert(is_Block(node) || is_Phi(node)); + assert(is_Block(node)); n = get_irn_arity(node); NEW_ARR_A(ir_node*, ins, n + 1); @@ -194,6 +194,16 @@ static void construct_ssa(ir_node *orig_block, ir_node *orig_val, } } +/** + * jumpthreading produces critical edges, e.g. B-C: + * A A + * \ / \ | + * B => B | + * / \ / \| + * C C + * + * By splitting this critical edge more threadings might be possible. + */ static void split_critical_edge(ir_node *block, int pos) { ir_graph *irg = get_irn_irg(block); @@ -284,7 +294,7 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block, } /* ignore control flow */ mode = get_irn_mode(node); - if (mode == mode_X || is_Cond(node)) + if (mode == mode_X || is_Cond(node) || is_Switch(node)) continue; #ifdef AVOID_PHIB /* we may not copy mode_b nodes, because this could produce Phi with @@ -337,7 +347,7 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block, ir_mode *mode; mode = get_irn_mode(node); - if (mode == mode_X || is_Cond(node)) + if (mode == mode_X || is_Cond(node) || is_Switch(node)) continue; #ifdef AVOID_PHIB if (mode == mode_b) @@ -634,6 +644,7 @@ static void thread_jumps(ir_node* block, void* data) ir_node *badX; int cnst_pos; + /* we do not deal with Phis, so restrict this to exactly one cfgpred */ if (get_Block_n_cfgpreds(block) != 1) return; @@ -643,15 +654,12 @@ static void thread_jumps(ir_node* block, void* data) assert(get_irn_mode(projx) == mode_X); cond = get_Proj_pred(projx); - if (!is_Cond(cond)) - return; - - selector = get_Cond_selector(cond); /* TODO handle switch Conds */ - if (get_irn_mode(selector) != mode_b) + if (!is_Cond(cond)) return; /* handle cases that can be immediately evaluated */ + selector = get_Cond_selector(cond); selector_evaluated = -1; if (is_Cmp(selector)) { ir_node *left = get_Cmp_left(selector); @@ -716,6 +724,10 @@ static void thread_jumps(ir_node* block, void* data) if (copy_block == NULL) return; + /* We might thread the condition block of an infinite loop, + * such that there is no path to End anymore. */ + keep_alive(block); + /* we have to remove the edge towards the pred as the pred now * jumps into the true_block. We also have to shorten Phis * in our block because of this */ @@ -738,21 +750,15 @@ static void thread_jumps(ir_node* block, void* data) *changed = 1; } -void opt_jumpthreading(ir_graph* irg) +static ir_graph_state_t do_jumpthread(ir_graph* irg) { int changed, rerun; + ir_graph_state_t res = 0; FIRM_DBG_REGISTER(dbg, "firm.opt.jumpthreading"); DB((dbg, LEVEL_1, "===> Performing jumpthreading on %+F\n", irg)); - remove_critical_cf_edges(irg); - - /* ugly: jump threading might get confused by garbage nodes - * of mode_X in copy_and_fix_node(), so remove all garbage edges. */ - edges_deactivate(irg); - - edges_assure(irg); ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_IRN_VISITED); changed = 0; @@ -764,13 +770,22 @@ void opt_jumpthreading(ir_graph* irg) ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_IRN_VISITED); - if (changed) { - /* control flow changed, some blocks may become dead */ - set_irg_doms_inconsistent(irg); - set_irg_extblk_inconsistent(irg); - set_irg_loopinfo_inconsistent(irg); - set_irg_entity_usage_state(irg, ir_entity_usage_not_computed); + if (!changed) { + res |= IR_GRAPH_STATE_CONSISTENT_DOMINANCE | IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE; } + + return res; +} + +static optdesc_t opt_jumpthread = { + "jumpthreading", + IR_GRAPH_STATE_NO_UNREACHABLE_CODE | IR_GRAPH_STATE_CONSISTENT_OUT_EDGES | IR_GRAPH_STATE_NO_CRITICAL_EDGES, + do_jumpthread, +}; + +void opt_jumpthreading(ir_graph* irg) +{ + perform_irg_optimization(irg, &opt_jumpthread); } /* Creates an ir_graph pass for opt_jumpthreading. */