X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Flower%2Flower_switch.c;h=4ff2737980ed18c831b469641b7f8b3b0550e970;hb=b3b65d5e83b23c0d6c748c6caa4863803c58cc87;hp=92844922f734a3f04b09bb5ac874a4c8e04f1750;hpb=af300963705d97b2f596e8cf2887813c25de6ad8;p=libfirm diff --git a/ir/lower/lower_switch.c b/ir/lower/lower_switch.c index 92844922f..4ff273798 100644 --- a/ir/lower/lower_switch.c +++ b/ir/lower/lower_switch.c @@ -44,6 +44,7 @@ typedef struct walk_env_t { unsigned spare_size; /**< the allowed spare size for table switches */ + unsigned small_switch; bool allow_out_of_bounds; bool changed; /**< indicates whether a change was performed */ ir_nodeset_t processed; @@ -206,7 +207,7 @@ static void create_out_of_bounds_check(cond_env_t *env, ir_node *cond) ir_node *block = get_nodes_block(cond); ir_mode *cmp_mode = get_irn_mode(sel); ir_node **default_preds = NEW_ARR_F(ir_node*, 0); - unsigned long default_pn = get_Cond_default_proj(cond); + long default_pn = get_Cond_default_proj(cond); long delta = 0; ir_node *max_const; ir_node *proj_true; @@ -237,7 +238,7 @@ static void create_out_of_bounds_check(cond_env_t *env, ir_node *cond) /* check for out-of-bounds */ max_const = new_r_Const_long(irg, cmp_mode, env->switch_max); - cmp = new_rd_Cmp(dbgi, block, sel, max_const, ir_relation_less); + cmp = new_rd_Cmp(dbgi, block, sel, max_const, ir_relation_less_equal); oob_cond = new_rd_Cond(dbgi, block, cmp); proj_true = new_r_Proj(oob_cond, mode_X, pn_Cond_true); proj_false = new_r_Proj(oob_cond, mode_X, pn_Cond_false); @@ -251,16 +252,10 @@ static void create_out_of_bounds_check(cond_env_t *env, ir_node *cond) /* adapt projs */ foreach_out_irn(cond, i, proj) { - unsigned long pn = get_Proj_proj(proj); - unsigned long new_pn = pn - delta; + long pn = get_Proj_proj(proj); + long new_pn = pn - delta; if (pn == default_pn) { - /* we might have to choose a new default_pn */ - if (pn < (unsigned long) env->switch_max) { - new_pn = env->switch_max + 1; - set_Cond_default_proj(cond, new_pn); - } else { - new_pn = default_pn; - } + set_Cond_default_proj(cond, new_pn); ARR_APP1(ir_node*, default_preds, proj); } @@ -271,18 +266,18 @@ static void create_out_of_bounds_check(cond_env_t *env, ir_node *cond) /* adapt default block */ n_default_preds = ARR_LEN(default_preds); if (n_default_preds > 1) { - size_t i; + size_t p; /* create new intermediate blocks so we don't have critical edges */ - for (i = 0; i < n_default_preds; ++i) { - ir_node *proj = default_preds[i]; - ir_node *block; - ir_node *in[1]; + for (p = 0; p < n_default_preds; ++p) { + ir_node *pred = default_preds[p]; + ir_node *split_block; + ir_node *block_in[1]; - in[0] = proj; - block = new_r_Block(irg, 1, in); + block_in[0] = pred; + split_block = new_r_Block(irg, 1, block_in); - default_preds[i] = new_r_Jmp(block); + default_preds[p] = new_r_Jmp(split_block); } } set_irn_in(env->default_block, n_default_preds, default_preds); @@ -311,6 +306,7 @@ static void find_cond_nodes(ir_node *block, void *ctx) dbg_info *dbgi; cond_env_t cond_env; unsigned long spare; + bool lower_switch = false; /* because we split critical blocks only blocks with 1 predecessors may * contain Proj->Cond nodes */ @@ -349,7 +345,10 @@ static void find_cond_nodes(ir_node *block, void *ctx) spare = (unsigned long) cond_env.switch_max - (unsigned long) cond_env.switch_min - (unsigned long) cond_env.num_cases + 1; - if (spare < env->spare_size) { + lower_switch |= spare >= env->spare_size; + lower_switch |= cond_env.num_cases <= env->small_switch; + + if (!lower_switch) { /* we won't decompose the switch. But we might have to add * out-of-bounds checking */ if (!env->allow_out_of_bounds) { @@ -405,11 +404,13 @@ static void find_cond_nodes(ir_node *block, void *ctx) DEL_ARR_F(cond_env.defusers); } -void lower_switch(ir_graph *irg, unsigned spare_size, int allow_out_of_bounds) +void lower_switch(ir_graph *irg, unsigned small_switch, unsigned spare_size, + int allow_out_of_bounds) { walk_env_t env; env.changed = false; env.spare_size = spare_size; + env.small_switch = small_switch; env.allow_out_of_bounds = allow_out_of_bounds; ir_nodeset_init(&env.processed); @@ -421,9 +422,7 @@ void lower_switch(ir_graph *irg, unsigned spare_size, int allow_out_of_bounds) if (env.changed) { /* control flow changed */ - set_irg_outs_inconsistent(irg); set_irg_doms_inconsistent(irg); set_irg_extblk_inconsistent(irg); - set_irg_loopinfo_inconsistent(irg); } }