ia32_Minus64Bit needs no contraint copies.
[libfirm] / ir / opt / jumpthreading.c
index 0f519a9..39de745 100644 (file)
@@ -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);
@@ -86,7 +86,7 @@ static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode,
        /* In case of a bad input to a block we need to return the bad value */
        if (is_Bad(block)) {
                ir_graph *irg = get_irn_irg(block);
-               return new_r_Bad(irg);
+               return new_r_Bad(irg, mode);
        }
 
        /* the other defs can't be marked for cases where a user of the original
@@ -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);
@@ -275,6 +285,13 @@ static void copy_and_fix(const jumpthreading_env_t *env, ir_node *block,
                ir_node *copy;
                ir_mode *mode;
 
+               if (is_End(node)) {
+                       /* edge is a Keep edge. If the end block is unreachable via normal control flow,
+                        * we must maintain end's reachability with Keeps.
+                        */
+                       keep_alive(copy_block);
+                       continue;
+               }
                /* ignore control flow */
                mode = get_irn_mode(node);
                if (mode == mode_X || is_Cond(node))
@@ -624,9 +641,10 @@ static void thread_jumps(ir_node* block, void* data)
        int      selector_evaluated;
        const ir_edge_t *edge, *next;
        ir_graph *irg;
-       ir_node *bad;
+       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;
 
@@ -686,7 +704,7 @@ static void thread_jumps(ir_node* block, void* data)
 
        if (selector_evaluated == 0) {
                ir_graph *irg = get_irn_irg(block);
-               bad = new_r_Bad(irg);
+               ir_node  *bad = new_r_Bad(irg, mode_X);
                exchange(projx, bad);
                *changed = 1;
                return;
@@ -709,21 +727,27 @@ 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 */
-       bad      = new_r_Bad(irg);
+       badX     = new_r_Bad(irg, mode_X);
        cnst_pos = env.cnst_pos;
 
        /* shorten Phis */
        foreach_out_edge_safe(env.cnst_pred, edge, next) {
                ir_node *node = get_edge_src_irn(edge);
 
-               if (is_Phi(node))
+               if (is_Phi(node)) {
+                       ir_node *bad = new_r_Bad(irg, get_irn_mode(node));
                        set_Phi_pred(node, cnst_pos, bad);
+               }
        }
 
-       set_Block_cfgpred(env.cnst_pred, cnst_pos, bad);
+       set_Block_cfgpred(env.cnst_pred, cnst_pos, badX);
 
        /* the graph is changed now */
        *changed = 1;
@@ -757,10 +781,8 @@ void opt_jumpthreading(ir_graph* irg)
 
        if (changed) {
                /* control flow changed, some blocks may become dead */
-               set_irg_outs_inconsistent(irg);
                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);
        }
 }