OSDN Git Service

* tree-ssa-threadupdate.c (rediscover_loops_after_threading):
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dse.c
index 4277a3a..17ed129 100644 (file)
@@ -83,8 +83,15 @@ struct dse_block_local_data
   bitmap stores;
 };
 
+/* Basic blocks of the potentially dead store and the following
+   store, for memory_address_same.  */
+struct address_walk_data
+{
+  basic_block store1_bb, store2_bb;
+};
+
 static bool gate_dse (void);
-static void tree_ssa_dse (void);
+static unsigned int tree_ssa_dse (void);
 static void dse_initialize_block_local_data (struct dom_walk_data *,
                                             basic_block,
                                             bool);
@@ -145,6 +152,64 @@ dse_initialize_block_local_data (struct dom_walk_data *walk_data,
     }
 }
 
+/* Helper function for memory_address_same via walk_tree.  Returns
+   non-NULL if it finds an SSA_NAME which is part of the address,
+   such that the definition of the SSA_NAME post-dominates the store
+   we want to delete but not the store that we believe makes it
+   redundant.  This indicates that the address may change between
+   the two stores.  */
+
+static tree
+memory_ssa_name_same (tree *expr_p, int *walk_subtrees ATTRIBUTE_UNUSED,
+                     void *data)
+{
+  struct address_walk_data *walk_data = data;
+  tree expr = *expr_p;
+  tree def_stmt;
+  basic_block def_bb;
+
+  if (TREE_CODE (expr) != SSA_NAME)
+    return NULL_TREE;
+
+  /* If we've found a default definition, then there's no problem.  Both
+     stores will post-dominate it.  And def_bb will be NULL.  */
+  if (expr == default_def (SSA_NAME_VAR (expr)))
+    return NULL_TREE;
+
+  def_stmt = SSA_NAME_DEF_STMT (expr);
+  def_bb = bb_for_stmt (def_stmt);
+
+  /* DEF_STMT must dominate both stores.  So if it is in the same
+     basic block as one, it does not post-dominate that store.  */
+  if (walk_data->store1_bb != def_bb
+      && dominated_by_p (CDI_POST_DOMINATORS, walk_data->store1_bb, def_bb))
+    {
+      if (walk_data->store2_bb == def_bb
+         || !dominated_by_p (CDI_POST_DOMINATORS, walk_data->store2_bb,
+                             def_bb))
+       /* Return non-NULL to stop the walk.  */
+       return def_stmt;
+    }
+
+  return NULL_TREE;
+}
+
+/* Return TRUE if the destination memory address in STORE1 and STORE2
+   might be modified after STORE1, before control reaches STORE2.  */
+
+static bool
+memory_address_same (tree store1, tree store2)
+{
+  struct address_walk_data walk_data;
+
+  walk_data.store1_bb = bb_for_stmt (store1);
+  walk_data.store2_bb = bb_for_stmt (store2);
+
+  return (walk_tree (&TREE_OPERAND (store1, 0), memory_ssa_name_same,
+                    &walk_data, NULL)
+         == NULL);
+}
+
 /* Attempt to eliminate dead stores in the statement referenced by BSI.
 
    A dead store is a store into a memory location which will later be
@@ -244,6 +309,15 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
             && TREE_CODE (use_stmt) == PHI_NODE
             && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt)))
        {
+         /* A PHI node can both define and use the same SSA_NAME if
+            the PHI is at the top of a loop and the PHI_RESULT is
+            a loop invariant and copies have not been fully propagated.
+
+            The safe thing to do is exit assuming no optimization is
+            possible.  */
+         if (SSA_NAME_DEF_STMT (PHI_RESULT (use_stmt)) == use_stmt)
+           return;
+
          /* Skip past this PHI and loop again in case we had a PHI
             chain.  */
          if (single_imm_use (PHI_RESULT (use_stmt), &use_p, &use_stmt))
@@ -251,20 +325,18 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
        }
 
       /* If we have precisely one immediate use at this point, then we may
-        have found redundant store.  */
+        have found redundant store.  Make sure that the stores are to
+        the same memory location.  This includes checking that any
+        SSA-form variables in the address will have the same values.  */
       if (use_p != NULL_USE_OPERAND_P
          && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
          && operand_equal_p (TREE_OPERAND (stmt, 0),
-                             TREE_OPERAND (use_stmt, 0), 0))
+                             TREE_OPERAND (use_stmt, 0), 0)
+         && memory_address_same (stmt, use_stmt))
        {
-         tree def;
-         ssa_op_iter iter;
-
          /* Make sure we propagate the ABNORMAL bit setting.  */
          if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (first_use_p)))
            SSA_NAME_OCCURS_IN_ABNORMAL_PHI (usevar) = 1;
-         /* Then we need to fix the operand of the consuming stmt.  */
-         SET_USE (first_use_p, usevar);
 
          if (dump_file && (dump_flags & TDF_DETAILS))
             {
@@ -272,15 +344,14 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
               print_generic_expr (dump_file, bsi_stmt (bsi), dump_flags);
               fprintf (dump_file, "'\n");
             }
-
+         /* Then we need to fix the operand of the consuming stmt.  */
+         FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND (var1, var2, stmt, op_iter)
+           {
+             single_imm_use (DEF_FROM_PTR (var1), &use_p, &temp);
+             SET_USE (use_p, USE_FROM_PTR (var2));
+           }
          /* Remove the dead store.  */
-         bsi_remove (&bsi);
-
-         /* The virtual defs for the dead statement will need to be
-            updated.  Since these names are going to disappear,
-            FUD chains for uses downstream need to be updated.  */
-         FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_VIRTUAL_DEFS)
-           mark_sym_for_renaming (SSA_NAME_VAR (def));
+         bsi_remove (&bsi, true);
 
          /* And release any SSA_NAMEs set in this statement back to the
             SSA_NAME manager.  */
@@ -327,7 +398,7 @@ dse_finalize_block (struct dom_walk_data *walk_data,
       }
 }
 
-static void
+static unsigned int
 tree_ssa_dse (void)
 {
   struct dom_walk_data walk_data;
@@ -384,6 +455,7 @@ tree_ssa_dse (void)
 
   /* For now, just wipe the post-dominator information.  */
   free_dominance_info (CDI_POST_DOMINATORS);
+  return 0;
 }
 
 static bool
@@ -408,7 +480,6 @@ struct tree_opt_pass pass_dse = {
   0,                           /* todo_flags_start */
   TODO_dump_func
     | TODO_ggc_collect
-    | TODO_update_ssa
     | TODO_verify_ssa,         /* todo_flags_finish */
   0                            /* letter */
 };