OSDN Git Service

2008-05-14 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / dce.c
index 7b2ffe9..91cc9aa 100644 (file)
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -99,6 +99,20 @@ deletable_insn_p (rtx insn, bool fast)
   rtx body, x;
   int i;
 
+  if (CALL_P (insn)
+      /* We cannot delete calls inside of the recursive dce because
+        this may cause basic blocks to be deleted and this messes up
+        the rest of the stack of optimization passes.  */
+      && (!df_in_progress)
+      /* We cannot delete pure or const sibling calls because it is
+        hard to see the result.  */
+      && (!SIBLING_CALL_P (insn))
+      /* We can delete dead const or pure calls as long as they do not
+         infinite loop.  */
+      && (RTL_CONST_OR_PURE_CALL_P (insn)
+         && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
+    return true;
+
   if (!NONJUMP_INSN_P (insn))
     return false;
 
@@ -296,6 +310,7 @@ delete_unmarked_insns (void)
 {
   basic_block bb;
   rtx insn, next;
+  bool must_clean = false;
 
   FOR_EACH_BB (bb)
     FOR_BB_INSNS_SAFE (bb, insn, next)
@@ -373,9 +388,19 @@ delete_unmarked_insns (void)
              remove_note (XEXP (note, 0), libcall_note);
            }
 
+         /* If a pure or const call is deleted, this may make the cfg
+            have unreachable blocks.  We rememeber this and call
+            delete_unreachable_blocks at the end.  */
+         if (CALL_P (insn))
+           must_clean = true;
+
          /* Now delete the insn.  */
          delete_insn_and_edges (insn);
        }
+
+  /* Deleted a pure or const call.  */
+  if (must_clean)
+    delete_unreachable_blocks ();
 }