X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fcondeval.c;h=276c79b66649cc9d3a7f193044d106de5958ed91;hb=7dfcddaf2dfe8322182d100532b16c48e438752d;hp=d9ed8d557ac79572bd582170ab0be4a6deac9e8c;hpb=c0a9c2c836abe00ffac72cdd1980e367ead77351;p=libfirm diff --git a/ir/opt/condeval.c b/ir/opt/condeval.c index d9ed8d557..276c79b66 100644 --- a/ir/opt/condeval.c +++ b/ir/opt/condeval.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. * @@ -86,11 +86,14 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode) return value; } + irg = get_irn_irg(block); + assert(block != get_irg_start_block(irg)); + // blocks with only 1 pred need no phi n_cfgpreds = get_Block_n_cfgpreds(block); if(n_cfgpreds == 1) { ir_node *pred_block = get_Block_cfgpred_block(block, 0); - ir_node *value = search_def_and_create_phis(pred_block, mode); + ir_node *value = search_def_and_create_phis(pred_block, mode); set_irn_link(block, value); mark_irn_visited(block); @@ -102,7 +105,6 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode) for(i = 0; i < n_cfgpreds; ++i) in[i] = new_Unknown(mode); - irg = get_irn_irg(block); phi = new_r_Phi(irg, block, n_cfgpreds, in, mode); set_irn_link(block, phi); mark_irn_visited(block); @@ -132,7 +134,7 @@ static void construct_ssa(ir_node * const *blocks, ir_node * const *vals, int n_ const ir_edge_t *next; ir_node *value; - assert(n_vals > 0); + assert(n_vals == 2); irg = get_irn_irg(vals[0]); inc_irg_visited(irg); @@ -151,9 +153,6 @@ static void construct_ssa(ir_node * const *blocks, ir_node * const *vals, int n_ // Only fix the users of the first, i.e. the original node value = vals[0]; - // this can happen when fixing phi preds, we mustn't fix the users - if(get_nodes_block(value) != blocks[0]) return; - foreach_out_edge_safe(value, edge, next) { ir_node *user = get_edge_src_irn(edge); int j = get_edge_src_pos(edge); @@ -164,6 +163,9 @@ static void construct_ssa(ir_node * const *blocks, ir_node * const *vals, int n_ if(get_irn_op(user) == op_End) continue; + if (user_block == blocks[1]) + continue; + DB((dbg, LEVEL_3, ">>> Fixing user %+F (pred %d == %+F)\n", user, j, get_irn_n(user, j))); if(is_Phi(user)) { @@ -205,6 +207,47 @@ typedef struct condeval_env_t { kill that edge later) */ } condeval_env_t; +static ir_node *copy_and_fix_node(const condeval_env_t *env, ir_node *block, + ir_node *copy_block, int j, ir_node *node) { + int i, arity; + ir_node *copy; + + /* we can evaluate Phis right now, all other nodes get copied */ + if (is_Phi(node)) { + copy = get_Phi_pred(node, j); + /* we might have to evaluate a phi-cascades */ + if(get_irn_visited(copy) >= env->visited_nr) { + copy = get_irn_link(copy); + } + } else { + copy = exact_copy(node); + set_nodes_block(copy, copy_block); + + assert(get_irn_mode(copy) != mode_X); + + arity = get_irn_arity(copy); + for(i = 0; i < arity; ++i) { + ir_node *pred = get_irn_n(copy, i); + ir_node *new_pred; + + if(get_nodes_block(pred) != block) + continue; + + if(get_irn_visited(pred) >= env->visited_nr) { + new_pred = get_irn_link(pred); + } else { + new_pred = copy_and_fix_node(env, block, copy_block, j, pred); + } + set_irn_n(copy, i, new_pred); + } + } + + set_irn_link(node, copy); + set_irn_visited(node, env->visited_nr); + + return copy; +} + static void copy_and_fix(const condeval_env_t *env, ir_node *block, ir_node *copy_block, int j) { const ir_edge_t *edge; @@ -213,15 +256,22 @@ static void copy_and_fix(const condeval_env_t *env, ir_node *block, foreach_out_edge(block, edge) { ir_node *node = get_edge_src_irn(edge); ir_node *copy; - ir_mode *mode = get_irn_mode(node); + ir_mode *mode; + + if (is_Block(node)) { + /* Block->Block edge, should be the MacroBlock edge */ + assert(get_Block_MacroBlock(node) == block && "Block->Block edge found"); + continue; + } /* ignore control flow */ + mode = get_irn_mode(node); if (mode == mode_X || is_Cond(node)) continue; #ifdef AVOID_PHIB /* we may not copy mode_b nodes, because this could produce phi with * mode_bs which can't be handled in all backends. Instead we duplicate - * the node and move it to it's users */ + * the node and move it to its users */ if (mode == mode_b) { const ir_edge_t *edge, *next; ir_node *pred; @@ -250,16 +300,7 @@ static void copy_and_fix(const condeval_env_t *env, ir_node *block, } #endif - /* we can evaluate Phis right now, all other nodes get copied */ - if (is_Phi(node)) { - copy = get_Phi_pred(node, j); - } else { - copy = exact_copy(node); - set_nodes_block(copy, copy_block); - } - - set_irn_link(node, copy); - set_irn_visited(node, env->visited_nr); + copy = copy_and_fix_node(env, block, copy_block, j, node); /* we might hit values in blocks that have already been processed by a * recursive find_phi_with_const call */ @@ -276,8 +317,15 @@ static void copy_and_fix(const condeval_env_t *env, ir_node *block, ir_node *vals[2]; ir_node *blocks[2]; ir_node *node = get_edge_src_irn(edge); - ir_mode *mode = get_irn_mode(node); + ir_mode *mode; + + if (is_Block(node)) { + /* Block->Block edge, should be the MacroBlock edge */ + assert(get_Block_MacroBlock(node) == block && "Block->Block edge found"); + continue; + } + mode = get_irn_mode(node); if (mode == mode_X || is_Cond(node)) continue; #ifdef AVOID_PHIB @@ -295,12 +343,16 @@ static void copy_and_fix(const condeval_env_t *env, ir_node *block, } } +/** + * returns wether the cmp evaluates to true or false, or can't be evaluated! + * 1: true, 0: false, -1: can't evaluate + */ static int eval_cmp(pn_Cmp pnc, tarval *tv1, tarval *tv2) { pn_Cmp cmp_result = tarval_cmp(tv1, tv2); // does the compare evaluate to true? if(cmp_result == pn_Cmp_False) - return 0; + return -1; if((cmp_result & pnc) != cmp_result) return 0; @@ -319,7 +371,7 @@ static ir_node *find_const(condeval_env_t *env, ir_node *jump, ir_node *value) tarval *tv_const = get_Const_tarval(env->cnst); tarval *tv = get_Const_tarval(value); - if(!eval_cmp(env->pnc, tv, tv_const)) { + if(eval_cmp(env->pnc, tv, tv_const) <= 0) { return NULL; } @@ -535,6 +587,8 @@ static void cond_eval(ir_node* block, void* data) tarval *tv_right = get_Const_tarval(right); selector_evaluated = eval_cmp(pnc, tv_left, tv_right); + if(selector_evaluated < 0) + return; } } } else if(is_Const(selector)) { @@ -611,7 +665,7 @@ void opt_cond_eval(ir_graph* irg) edges_assure(irg); set_using_irn_link(irg); - set_using_visited(irg); + set_using_irn_visited(irg); changed = 0; do { @@ -628,6 +682,6 @@ void opt_cond_eval(ir_graph* irg) set_irg_loopinfo_inconsistent(irg); } - clear_using_visited(irg); + clear_using_irn_visited(irg); clear_using_irn_link(irg); }