Prevent SSA construction from running into endless loops.
authorSebastian Buchwald <Sebastian.Buchwald@kit.edu>
Fri, 15 Apr 2011 14:12:37 +0000 (16:12 +0200)
committerSebastian Buchwald <Sebastian.Buchwald@kit.edu>
Fri, 15 Apr 2011 14:38:47 +0000 (16:38 +0200)
If there is an unreachable loop (i.e. there is no loop entry edge)
then there may is a cycle of blocks with only one predecessor.
Since the algorithm handle this case by returning the value of the predecessor,
this causes an endless recursion.
The fix uses the visited flag to detect such cycles.

ir/ir/ircons.c

index 9a166e6..6ac3a88 100644 (file)
@@ -245,6 +245,8 @@ static ir_node *set_phi_arguments(ir_node *phi, int pos)
                if (is_Bad(cfgpred)) {
                        value = new_r_Bad(irg);
                } else {
+                       inc_irg_visited(irg);
+
                        value = get_r_value_internal(cfgpred, pos, mode);
                }
                in[i] = value;
@@ -277,10 +279,19 @@ static ir_node *set_phi_arguments(ir_node *phi, int pos)
  */
 static ir_node *get_r_value_internal(ir_node *block, int pos, ir_mode *mode)
 {
-       ir_node *res = block->attr.block.graph_arr[pos];
+       ir_node  *res = block->attr.block.graph_arr[pos];
+       ir_graph *irg = get_irn_irg(block);
        if (res != NULL)
                return res;
 
+       /* We ran into a cycle. This may happen in unreachable loops. */
+       if (irn_visited(block)) {
+               /* Since the loop is unreachable, return a Bad. */
+               return new_r_Bad(irg);
+       }
+
+       mark_irn_visited(block);
+
        /* in a matured block we can immediately determine the phi arguments */
        if (get_Block_matured(block)) {
                int arity = get_irn_arity(block);
@@ -567,6 +578,7 @@ ir_node *get_r_value(ir_graph *irg, int pos, ir_mode *mode)
 {
        assert(get_irg_phase_state(irg) == phase_building);
        assert(pos >= 0);
+       inc_irg_visited(irg);
 
        return get_r_value_internal(irg->current_block, pos + 1, mode);
 }
@@ -665,6 +677,7 @@ int find_value(ir_node *value)
 ir_node *get_r_store(ir_graph *irg)
 {
        assert(get_irg_phase_state(irg) == phase_building);
+       inc_irg_visited(irg);
        return get_r_value_internal(irg->current_block, 0, mode_M);
 }