OSDN Git Service

PR testsuite/25214
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfgcleanup.c
index f2454b0..836a14d 100644 (file)
@@ -81,11 +81,11 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
       switch (TREE_CODE (expr))
        {
        case COND_EXPR:
-         val = COND_EXPR_COND (expr);
+         val = fold (COND_EXPR_COND (expr));
          break;
 
        case SWITCH_EXPR:
-         val = SWITCH_COND (expr);
+         val = fold (SWITCH_COND (expr));
          if (TREE_CODE (val) != INTEGER_CST)
            return false;
          break;
@@ -523,28 +523,25 @@ cleanup_tree_cfg_1 (void)
 }
 
 
-/* Remove unreachable blocks and other miscellaneous clean up work.  */
+/* Remove unreachable blocks and other miscellaneous clean up work.
+   Return true if the flowgraph was modified, false otherwise.  */
 
 bool
 cleanup_tree_cfg (void)
 {
-  bool retval;
-  int i;
+  bool retval, changed;
 
   timevar_push (TV_TREE_CLEANUP_CFG);
 
-  for (retval = true, i = 0; i < 5 && retval; i++)
-    retval = cleanup_tree_cfg_1 ();
-
-#ifdef ENABLE_CHECKING
-  if (retval)
+  /* Iterate until there are no more cleanups left to do.  If any
+     iteration changed the flowgraph, set CHANGED to true.  */
+  changed = false;
+  do
     {
-      gcc_assert (!cleanup_control_flow ());
-      gcc_assert (!delete_unreachable_blocks ());
-      if (optimize > 0)
-       gcc_assert (!cleanup_forwarder_blocks ());
+      retval = cleanup_tree_cfg_1 ();
+      changed |= retval;
     }
-#endif
+  while (retval);
 
   compact_blocks ();
 
@@ -554,7 +551,7 @@ cleanup_tree_cfg (void)
 
   timevar_pop (TV_TREE_CLEANUP_CFG);
 
-  return retval;
+  return changed;
 }
 
 /* Cleanup cfg and repair loop structures.  */
@@ -746,6 +743,41 @@ merge_phi_nodes (void)
             nodes at BB.  */
          *current++ = bb;
        }
+      else
+       {
+         tree phi;
+         unsigned int dest_idx = single_succ_edge (bb)->dest_idx;
+
+         /* BB dominates DEST.  There may be many users of the PHI
+            nodes in BB.  However, there is still a trivial case we
+            can handle.  If the result of every PHI in BB is used
+            only by a PHI in DEST, then we can trivially merge the
+            PHI nodes from BB into DEST.  */
+         for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+           {
+             tree result = PHI_RESULT (phi);
+             int num_uses = num_imm_uses (result);
+             use_operand_p imm_use;
+             tree use_stmt;
+
+             /* If the PHI's result is never used, then we can just
+                ignore it.  */
+             if (num_uses == 0)
+               continue;
+
+             /* Get the single use of the result of this PHI node.  */
+             if (!single_imm_use (result, &imm_use, &use_stmt)
+                 || TREE_CODE (use_stmt) != PHI_NODE
+                 || bb_for_stmt (use_stmt) != dest
+                 || PHI_ARG_DEF (use_stmt, dest_idx) != result)
+               break;
+           }
+
+         /* If the loop above iterated thorugh all the PHI nodes
+            in BB, then we can merge the PHIs from BB into DEST.  */
+         if (!phi)
+           *current++ = bb;
+       }
     }
 
   /* Now let's drain WORKLIST.  */