OSDN Git Service

* gengtype.c (write_field_root): Avoid out-of-scope access of newv.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dce.c
index bf69bbf..d6fbe62 100644 (file)
@@ -299,17 +299,32 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
       return;
 
     case GIMPLE_CALL:
-      /* Most, but not all function calls are required.  Function calls that
-        produce no result and have no side effects (i.e. const pure
-        functions) are unnecessary.  */
-      if (gimple_has_side_effects (stmt))
-       {
-         mark_stmt_necessary (stmt, true);
+      {
+       tree callee = gimple_call_fndecl (stmt);
+       if (callee != NULL_TREE
+           && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+         switch (DECL_FUNCTION_CODE (callee))
+           {
+           case BUILT_IN_MALLOC:
+           case BUILT_IN_CALLOC:
+           case BUILT_IN_ALLOCA:
+           case BUILT_IN_ALLOCA_WITH_ALIGN:
+             return;
+
+           default:;
+           }
+       /* Most, but not all function calls are required.  Function calls that
+          produce no result and have no side effects (i.e. const pure
+          functions) are unnecessary.  */
+       if (gimple_has_side_effects (stmt))
+         {
+           mark_stmt_necessary (stmt, true);
+           return;
+         }
+       if (!gimple_call_lhs (stmt))
          return;
-       }
-      if (!gimple_call_lhs (stmt))
-        return;
-      break;
+       break;
+      }
 
     case GIMPLE_DEBUG:
       /* Debug temps without a value are not useful.  ??? If we could
@@ -336,6 +351,12 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
        mark_stmt_necessary (stmt, true);
       break;
 
+    case GIMPLE_ASSIGN:
+      if (TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
+         && TREE_CLOBBER_P (gimple_assign_rhs1 (stmt)))
+       return;
+      break;
+
     default:
       break;
     }
@@ -613,6 +634,26 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
        return false;
     }
 
+  /* We want to skip statments that do not constitute stores but have
+     a virtual definition.  */
+  if (is_gimple_call (def_stmt))
+    {
+      tree callee = gimple_call_fndecl (def_stmt);
+      if (callee != NULL_TREE
+         && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+       switch (DECL_FUNCTION_CODE (callee))
+         {
+         case BUILT_IN_MALLOC:
+         case BUILT_IN_CALLOC:
+         case BUILT_IN_ALLOCA:
+         case BUILT_IN_ALLOCA_WITH_ALIGN:
+         case BUILT_IN_FREE:
+           return false;
+
+         default:;
+         }
+    }
+
   mark_operand_necessary (vdef);
 
   return false;
@@ -793,6 +834,25 @@ propagate_necessity (struct edge_list *el)
          ssa_op_iter iter;
          tree use;
 
+         /* If this is a call to free which is directly fed by an
+            allocation function do not mark that necessary through
+            processing the argument.  */
+         if (gimple_call_builtin_p (stmt, BUILT_IN_FREE))
+           {
+             tree ptr = gimple_call_arg (stmt, 0);
+             gimple def_stmt;
+             tree def_callee;
+             /* If the pointer we free is defined by an allocation
+                function do not add the call to the worklist.  */
+             if (TREE_CODE (ptr) == SSA_NAME
+                 && is_gimple_call (def_stmt = SSA_NAME_DEF_STMT (ptr))
+                 && (def_callee = gimple_call_fndecl (def_stmt))
+                 && DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL
+                 && (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC
+                     || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC))
+               continue;
+           }
+
          FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
            mark_operand_necessary (use);
 
@@ -836,7 +896,10 @@ propagate_necessity (struct edge_list *el)
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_MALLOC
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_CALLOC
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_END
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
+                     || (DECL_FUNCTION_CODE (callee)
+                         == BUILT_IN_ALLOCA_WITH_ALIGN)
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
@@ -860,19 +923,17 @@ propagate_necessity (struct edge_list *el)
          else if (gimple_assign_single_p (stmt))
            {
              tree rhs;
-             bool rhs_aliased = false;
              /* If this is a load mark things necessary.  */
              rhs = gimple_assign_rhs1 (stmt);
              if (TREE_CODE (rhs) != SSA_NAME
-                 && !is_gimple_min_invariant (rhs))
+                 && !is_gimple_min_invariant (rhs)
+                 && TREE_CODE (rhs) != CONSTRUCTOR)
                {
                  if (!ref_may_be_aliased (rhs))
                    mark_aliased_reaching_defs_necessary (stmt, rhs);
                  else
-                   rhs_aliased = true;
+                   mark_all_reaching_defs_necessary (stmt);
                }
-             if (rhs_aliased)
-               mark_all_reaching_defs_necessary (stmt);
            }
          else if (gimple_code (stmt) == GIMPLE_RETURN)
            {
@@ -880,7 +941,8 @@ propagate_necessity (struct edge_list *el)
              /* A return statement may perform a load.  */
              if (rhs
                  && TREE_CODE (rhs) != SSA_NAME
-                 && !is_gimple_min_invariant (rhs))
+                 && !is_gimple_min_invariant (rhs)
+                 && TREE_CODE (rhs) != CONSTRUCTOR)
                {
                  if (!ref_may_be_aliased (rhs))
                    mark_aliased_reaching_defs_necessary (stmt, rhs);
@@ -898,6 +960,7 @@ propagate_necessity (struct edge_list *el)
                  tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
                  if (TREE_CODE (op) != SSA_NAME
                      && !is_gimple_min_invariant (op)
+                     && TREE_CODE (op) != CONSTRUCTOR
                      && !ref_may_be_aliased (op))
                    mark_aliased_reaching_defs_necessary (stmt, op);
                }
@@ -925,18 +988,36 @@ propagate_necessity (struct edge_list *el)
     }
 }
 
-/* Replace all uses of result of PHI by underlying variable and mark it
+/* Replace all uses of NAME by underlying variable and mark it
    for renaming.  */
 
 void
-mark_virtual_phi_result_for_renaming (gimple phi)
+mark_virtual_operand_for_renaming (tree name)
 {
   bool used = false;
   imm_use_iterator iter;
   use_operand_p use_p;
   gimple stmt;
-  tree result_ssa, result_var;
+  tree name_var;
 
+  name_var = SSA_NAME_VAR (name);
+  FOR_EACH_IMM_USE_STMT (stmt, iter, name)
+    {
+      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+        SET_USE (use_p, name_var);
+      update_stmt (stmt);
+      used = true;
+    }
+  if (used)
+    mark_sym_for_renaming (name_var);
+}
+
+/* Replace all uses of result of PHI by underlying variable and mark it
+   for renaming.  */
+
+void
+mark_virtual_phi_result_for_renaming (gimple phi)
+{
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "Marking result for renaming : ");
@@ -944,19 +1025,10 @@ mark_virtual_phi_result_for_renaming (gimple phi)
       fprintf (dump_file, "\n");
     }
 
-  result_ssa = gimple_phi_result (phi);
-  result_var = SSA_NAME_VAR (result_ssa);
-  FOR_EACH_IMM_USE_STMT (stmt, iter, result_ssa)
-    {
-      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-        SET_USE (use_p, result_var);
-      update_stmt (stmt);
-      used = true;
-    }
-  if (used)
-    mark_sym_for_renaming (result_var);
+  mark_virtual_operand_for_renaming (gimple_phi_result (phi));
 }
 
+
 /* Remove dead PHI nodes from block BB.  */
 
 static bool
@@ -1205,6 +1277,29 @@ eliminate_unnecessary_stmts (void)
 
          stats.total++;
 
+         /* We can mark a call to free as not necessary if the
+            defining statement of its argument is an allocation
+            function and that is not necessary itself.  */
+         if (gimple_call_builtin_p (stmt, BUILT_IN_FREE))
+           {
+             tree ptr = gimple_call_arg (stmt, 0);
+             tree callee2;
+             gimple def_stmt;
+             if (TREE_CODE (ptr) != SSA_NAME)
+               continue;
+             def_stmt = SSA_NAME_DEF_STMT (ptr);
+             if (!is_gimple_call (def_stmt)
+                 || gimple_plf (def_stmt, STMT_NECESSARY))
+               continue;
+             callee2 = gimple_call_fndecl (def_stmt);
+             if (callee2 == NULL_TREE
+                 || DECL_BUILT_IN_CLASS (callee2) != BUILT_IN_NORMAL
+                 || (DECL_FUNCTION_CODE (callee2) != BUILT_IN_MALLOC
+                     && DECL_FUNCTION_CODE (callee2) != BUILT_IN_CALLOC))
+               continue;
+             gimple_set_plf (stmt, STMT_NECESSARY, false);
+           }
+
          /* If GSI is not necessary then remove it.  */
          if (!gimple_plf (stmt, STMT_NECESSARY))
            {