Handle multiple control dependencies in a more sophisticated (and correct) way
[libfirm] / ir / opt / return.c
index 4483fcd..3b5338a 100644 (file)
@@ -60,8 +60,13 @@ void normalize_one_return(ir_graph *irg)
   ir_node *block;
 
   /* look, if we have more than one return */
-  n       = get_Block_n_cfgpreds(endbl);
-  assert(n > 0);
+  n = get_Block_n_cfgpreds(endbl);
+  if (n <= 0) {
+    /* The end block has no predecessors, we have an endless
+       loop. In that case, no returns exists. */
+    return;
+  }
+
   returns = alloca((n + 7) >> 3);
   memset(returns, 0, (n + 7) >> 3);
 
@@ -111,8 +116,24 @@ void normalize_one_return(ir_graph *irg)
 
   /* now create the Phi nodes */
   for (j = i = 0; i < n_ret_vals; ++i, j += n_rets) {
+    int k;
+    ir_node *first;
     /* the return values are already shuffled */
-    in[i] = new_r_Phi(irg, block, n_rets, &retvals[j], get_irn_mode(retvals[j]));
+
+    /* Beware: normally the Phi constructor automatically replaces a Phi(a,...a) into a
+       but NOT, if a is Unknown. Here, we known that this case can be optimize also,
+       so do it here */
+    first = retvals[j + 0];
+    for (k = 1; k < n_rets; ++k) {
+      if (retvals[j + k] != first) {
+        first = NULL;
+        break;
+      }
+    }
+    if (first)
+      in[i] = first;
+    else
+      in[i] = new_r_Phi(irg, block, n_rets, &retvals[j], get_irn_mode(retvals[j]));
   }
 
   endbl_in[last_idx++] = new_r_Return(irg, block, in[0], n_ret_vals-1, &in[1]);