OSDN Git Service

2011-03-24 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dse.c
index 37a5481..26a438d 100644 (file)
@@ -1,5 +1,5 @@
 /* Dead store elimination
-   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -24,11 +24,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "ggc.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tm_p.h"
 #include "basic-block.h"
 #include "timevar.h"
-#include "diagnostic.h"
+#include "gimple-pretty-print.h"
 #include "tree-flow.h"
 #include "tree-pass.h"
 #include "tree-dump.h"
@@ -84,6 +83,10 @@ struct dse_block_local_data
   bitmap stores;
 };
 
+/* Bitmap of blocks that have had EH statements cleaned.  We should
+   remove their dead edges eventually.  */
+static bitmap need_eh_cleanup;
+
 static bool gate_dse (void);
 static unsigned int tree_ssa_dse (void);
 static void dse_initialize_block_local_data (struct dom_walk_data *,
@@ -161,7 +164,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
   temp = stmt;
   do
     {
-      gimple prev, use_stmt;
+      gimple use_stmt;
       imm_use_iterator ui;
       bool fail = false;
       tree defvar;
@@ -175,28 +178,33 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt)
        defvar = PHI_RESULT (temp);
       else
        defvar = gimple_vdef (temp);
-      prev = temp;
       temp = NULL;
       FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
        {
          cnt++;
 
+         /* If we ever reach our DSE candidate stmt again fail.  We
+            cannot handle dead stores in loops.  */
+         if (use_stmt == stmt)
+           {
+             fail = true;
+             BREAK_FROM_IMM_USE_STMT (ui);
+           }
          /* In simple cases we can look through PHI nodes, but we
             have to be careful with loops and with memory references
             containing operands that are also operands of PHI nodes.
             See gcc.c-torture/execute/20051110-*.c.  */
-         if (gimple_code (use_stmt) == GIMPLE_PHI)
+         else if (gimple_code (use_stmt) == GIMPLE_PHI)
            {
              if (temp
-                 /* We can look through PHIs to post-dominated regions
-                    without worrying if the use not also dominates prev
-                    (in which case it would be a loop PHI with the use
-                    in a latch block).  */
-                 || gimple_bb (prev) == gimple_bb (use_stmt)
-                 || !dominated_by_p (CDI_POST_DOMINATORS,
-                                     gimple_bb (prev), gimple_bb (use_stmt))
+                 /* Make sure we are not in a loop latch block.  */
+                 || gimple_bb (stmt) == gimple_bb (use_stmt)
                  || dominated_by_p (CDI_DOMINATORS,
-                                    gimple_bb (prev), gimple_bb (use_stmt)))
+                                    gimple_bb (stmt), gimple_bb (use_stmt))
+                 /* We can look through PHIs to regions post-dominating
+                    the DSE candidate stmt.  */
+                 || !dominated_by_p (CDI_POST_DOMINATORS,
+                                     gimple_bb (stmt), gimple_bb (use_stmt)))
                {
                  fail = true;
                  BREAK_FROM_IMM_USE_STMT (ui);
@@ -297,8 +305,9 @@ dse_optimize_stmt (struct dse_global_data *dse_gd,
         virtual uses from stmt and the stmt which stores to that same
         memory location, then we may have found redundant store.  */
       if (bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
-         && operand_equal_p (gimple_assign_lhs (stmt),
-                             gimple_assign_lhs (use_stmt), 0))
+         && (operand_equal_p (gimple_assign_lhs (stmt),
+                              gimple_assign_lhs (use_stmt), 0)
+             || stmt_kills_ref_p (use_stmt, gimple_assign_lhs (stmt))))
        {
          /* If use_stmt is or might be a nop assignment, e.g. for
             struct { ... } S a, b, *p; ...
@@ -330,6 +339,8 @@ dse_optimize_stmt (struct dse_global_data *dse_gd,
          /* Then we need to fix the operand of the consuming stmt.  */
          unlink_stmt_vdef (stmt);
 
+         bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
+
          /* Remove the dead store.  */
          gsi_remove (&gsi, true);
 
@@ -396,6 +407,8 @@ tree_ssa_dse (void)
   struct dom_walk_data walk_data;
   struct dse_global_data dse_gd;
 
+  need_eh_cleanup = BITMAP_ALLOC (NULL);
+
   renumber_gimple_stmt_uids ();
 
   /* We might consider making this a property of each pass so that it
@@ -430,6 +443,16 @@ tree_ssa_dse (void)
   /* Release the main bitmap.  */
   BITMAP_FREE (dse_gd.stores);
 
+  /* Removal of stores may make some EH edges dead.  Purge such edges from
+     the CFG as needed.  */
+  if (!bitmap_empty_p (need_eh_cleanup))
+    {
+      gimple_purge_all_dead_eh_edges (need_eh_cleanup);
+      cleanup_tree_cfg ();
+    }
+
+  BITMAP_FREE (need_eh_cleanup);
+    
   /* For now, just wipe the post-dominator information.  */
   free_dominance_info (CDI_POST_DOMINATORS);
   return 0;