OSDN Git Service

2010-07-13 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfgcleanup.c
index db7fb00..f798b2f 100644 (file)
@@ -23,18 +23,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "flags.h"
 #include "function.h"
-#include "expr.h"
 #include "ggc.h"
 #include "langhooks.h"
-#include "diagnostic.h"
 #include "tree-flow.h"
 #include "timevar.h"
 #include "tree-dump.h"
@@ -540,6 +537,68 @@ remove_forwarder_block (basic_block bb)
   return true;
 }
 
+/* STMT is a call that has been discovered noreturn.  Fixup the CFG
+   and remove LHS.  Return true if something changed.  */
+
+bool
+fixup_noreturn_call (gimple stmt)
+{
+  basic_block bb = gimple_bb (stmt);
+  bool changed = false;
+
+  if (gimple_call_builtin_p (stmt, BUILT_IN_RETURN))
+    return false;
+
+  /* First split basic block if stmt is not last.  */
+  if (stmt != gsi_stmt (gsi_last_bb (bb)))
+    split_block (bb, stmt);
+
+  changed |= remove_fallthru_edge (bb->succs);
+
+  /* If there is LHS, remove it.  */
+  if (gimple_call_lhs (stmt))
+    {
+      tree op = gimple_call_lhs (stmt);
+      gimple_call_set_lhs (stmt, NULL_TREE);
+
+      /* We need to remove SSA name to avoid checking errors.
+        All uses are dominated by the noreturn and thus will
+        be removed afterwards.
+        We proactively remove affected non-PHI statements to avoid
+        fixup_cfg from trying to update them and crashing.  */
+      if (TREE_CODE (op) == SSA_NAME)
+       {
+         use_operand_p use_p;
+          imm_use_iterator iter;
+         gimple use_stmt;
+         bitmap_iterator bi;
+         unsigned int bb_index;
+
+         bitmap blocks = BITMAP_ALLOC (NULL);
+
+          FOR_EACH_IMM_USE_STMT (use_stmt, iter, op)
+           {
+             if (gimple_code (use_stmt) != GIMPLE_PHI)
+               bitmap_set_bit (blocks, gimple_bb (use_stmt)->index);
+             else
+               FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+                 SET_USE (use_p, error_mark_node);
+           }
+         EXECUTE_IF_SET_IN_BITMAP (blocks, 0, bb_index, bi)
+           delete_basic_block (BASIC_BLOCK (bb_index));
+         BITMAP_FREE (blocks);
+         release_ssa_name (op);
+       }
+      update_stmt (stmt);
+      changed = true;
+    }
+  /* Similarly remove VDEF if there is any.  */
+  else if (gimple_vdef (stmt))
+    update_stmt (stmt);
+  return changed;
+}
+
+
 /* Split basic blocks on calls in the middle of a basic block that are now
    known not to return, and remove the unreachable code.  */
 
@@ -562,13 +621,10 @@ split_bbs_on_noreturn_calls (void)
            || bb->index < NUM_FIXED_BLOCKS
            || bb->index >= n_basic_blocks
            || BASIC_BLOCK (bb->index) != bb
-           || last_stmt (bb) == stmt
            || !gimple_call_noreturn_p (stmt))
          continue;
 
-       changed = true;
-       split_block (bb, stmt);
-       remove_fallthru_edge (bb->succs);
+       changed |= fixup_noreturn_call (stmt);
       }
 
   return changed;