OSDN Git Service

2008-01-15 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dse.c
index d7453dd..3e0f04b 100644 (file)
@@ -210,62 +210,62 @@ memory_address_same (tree store1, tree store2)
          == NULL);
 }
 
-/* Return the use stmt for the lhs of STMT following the virtual
-   def-use chains.  Returns the MODIFY_EXPR stmt which lhs is equal to
-   the lhs of STMT or NULL_TREE if no such stmt can be found.  */
-static tree 
-get_use_of_stmt_lhs (tree stmt,
-                    use_operand_p * first_use_p,
-                    use_operand_p * use_p, tree * use_stmt)
+/* Return true if there is a stmt that kills the lhs of STMT and is in the
+   virtual def-use chain of STMT without a use inbetween the kill and STMT.
+   Returns false if no such stmt is found.
+   *FIRST_USE_P is set to the first use of the single virtual def of
+   STMT.  *USE_P is set to the vop killed by *USE_STMT.  */
+
+static bool
+get_kill_of_stmt_lhs (tree stmt,
+                     use_operand_p * first_use_p,
+                     use_operand_p * use_p, tree * use_stmt)
 {
-  tree usevar, lhs;
-  def_operand_p def_p;
+  tree lhs;
 
-  if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
-    return NULL_TREE;
+  gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
 
   lhs = GIMPLE_STMT_OPERAND (stmt, 0);
 
-  /* The stmt must have a single VDEF.  */
-  def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_VDEF);
-  if (def_p == NULL_DEF_OPERAND_P)
-    return NULL_TREE;
-
-  if (!has_single_use (DEF_FROM_PTR (def_p)))
-    return NULL_TREE;
-  /* Get the immediate use of the def.  */
-  single_imm_use (DEF_FROM_PTR (def_p), use_p, use_stmt);
-  gcc_assert (*use_p != NULL_USE_OPERAND_P);
-  first_use_p = use_p;
-
-  /* If the use is not simple, give up.  */
-  if (TREE_CODE (*use_stmt) != GIMPLE_MODIFY_STMT
-      || get_call_expr_in (*use_stmt))
-    return NULL_TREE;
-
+  /* We now walk the chain of single uses of the single VDEFs.
+     We succeeded finding a kill if the lhs of the use stmt is
+     equal to the original lhs.  We can keep walking to the next
+     use if there are no possible uses of the original lhs in
+     the stmt.  */
   do
     {
-      /* Look at the use stmt and see if it's LHS matches
-         stmt's lhs SSA_NAME.  */
-      def_p = SINGLE_SSA_DEF_OPERAND (*use_stmt, SSA_OP_VDEF);
+      tree use_lhs, use_rhs;
+      def_operand_p def_p;
+
+      /* The stmt must have a single VDEF.  */
+      def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_VDEF);
       if (def_p == NULL_DEF_OPERAND_P)
-       return NULL_TREE;
+       return false;
+
+      /* Get the single immediate use of the def.  */
+      if (!single_imm_use (DEF_FROM_PTR (def_p), first_use_p, &stmt))
+       return false;
+      first_use_p = use_p;
 
-      usevar = GIMPLE_STMT_OPERAND (*use_stmt, 0);
-      if (operand_equal_p (usevar, lhs, 0))
-       return *use_stmt;
+      /* If there are possible hidden uses, give up.  */
+      if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
+       return false;
+      use_rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+      if (TREE_CODE (use_rhs) == CALL_EXPR
+         || (!is_gimple_min_invariant (use_rhs)
+             && TREE_CODE (use_rhs) != SSA_NAME))
+       return false;
 
-      if (!has_single_use (DEF_FROM_PTR (def_p)))
-       return NULL_TREE;
-      single_imm_use (DEF_FROM_PTR (def_p), use_p, use_stmt);
-      gcc_assert (*use_p != NULL_USE_OPERAND_P);
-      if (TREE_CODE (*use_stmt) != GIMPLE_MODIFY_STMT
-         || get_call_expr_in (*use_stmt))
-       return NULL_TREE;
+      /* If the use stmts lhs matches the original lhs we have
+        found the kill, otherwise continue walking.  */
+      use_lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+      if (operand_equal_p (use_lhs, lhs, 0))
+       {
+         *use_stmt = stmt;
+         return true;
+       }
     }
   while (1);
-
-  return NULL_TREE;
 }
 
 /* A helper of dse_optimize_stmt.
@@ -448,8 +448,7 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
              the stores are not to the same memory location then walk the
              virtual def-use chain to get the stmt which stores to that same
              memory location.  */
-          if (get_use_of_stmt_lhs (stmt, &first_use_p, &use_p, &use_stmt) ==
-              NULL_TREE)
+          if (!get_kill_of_stmt_lhs (stmt, &first_use_p, &use_p, &use_stmt))
             {
               record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
               return;
@@ -471,6 +470,26 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
          vuse_vec_p vv;
          tree stmt_lhs;
 
+         if (LOADED_SYMS (use_stmt))
+           {
+             tree use_base
+               = get_base_address (GIMPLE_STMT_OPERAND (use_stmt, 0));
+             /* If use_stmt is or might be a nop assignment, e.g. for
+                struct { ... } S a, b, *p; ...
+                b = a; b = b;
+                or
+                b = a; b = *p; where p might be &b, then USE_STMT
+                acts as a use as well as definition, so store in STMT
+                is not dead.  */
+             if (TREE_CODE (use_base) == VAR_DECL
+                 && bitmap_bit_p (LOADED_SYMS (use_stmt),
+                                  DECL_UID (use_base)))
+               {
+                 record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
+                 return;
+               }
+           }
+
          if (dump_file && (dump_flags & TDF_DETAILS))
             {
               fprintf (dump_file, "  Deleted dead store '");
@@ -654,7 +673,7 @@ execute_simple_dse (void)
        bitmap_ior_into (variables_loaded,
                         LOADED_SYMS (bsi_stmt (bsi)));
 
-  /* Look for statements writting into the write only variables.
+  /* Look for statements writing into the write only variables.
      And try to remove them.  */
 
   FOR_EACH_BB (bb)