Better fix for wrong tarval computation of -(infinity).
[libfirm] / ir / lower / lower_switch.c
index e44bd5f..56adc79 100644 (file)
@@ -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;
@@ -251,11 +252,11 @@ 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) {
+                       if (pn < env->switch_max) {
                                new_pn = env->switch_max + 1;
                                set_Cond_default_proj(cond, new_pn);
                        } else {
@@ -311,6 +312,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 +351,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 +410,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);
 
@@ -423,6 +430,5 @@ void lower_switch(ir_graph *irg, unsigned spare_size, int allow_out_of_bounds)
                /* control flow changed */
                set_irg_doms_inconsistent(irg);
                set_irg_extblk_inconsistent(irg);
-               set_irg_loopinfo_inconsistent(irg);
        }
 }