OSDN Git Service

Merge from gomp-3_1-branch branch:
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dce.c
index edec49d..bf69bbf 100644 (file)
@@ -1,5 +1,5 @@
 /* Dead code elimination pass for the GNU compiler.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Ben Elliston <bje@redhat.com>
    and Andrew MacLeod <amacleod@redhat.com>
@@ -271,8 +271,6 @@ mark_operand_necessary (tree op)
 static void
 mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
 {
-  tree lhs = NULL_TREE;
-
   /* With non-call exceptions, we have to assume that all statements could
      throw.  If a statement may throw, it is inherently necessary.  */
   if (cfun->can_throw_non_call_exceptions && stmt_could_throw_p (stmt))
@@ -311,12 +309,6 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
        }
       if (!gimple_call_lhs (stmt))
         return;
-      lhs = gimple_call_lhs (stmt);
-      /* Fall through */
-
-    case GIMPLE_ASSIGN:
-      if (!lhs)
-        lhs = gimple_assign_lhs (stmt);
       break;
 
     case GIMPLE_DEBUG:
@@ -324,7 +316,8 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
         easily locate the debug temp bind stmt for a use thereof,
         would could refrain from marking all debug temps here, and
         mark them only if they're used.  */
-      if (gimple_debug_bind_has_value_p (stmt)
+      if (!gimple_debug_bind_p (stmt)
+         || gimple_debug_bind_has_value_p (stmt)
          || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
        mark_stmt_necessary (stmt, false);
       return;
@@ -433,6 +426,7 @@ find_obviously_necessary_stmts (struct edge_list *el)
   gimple_stmt_iterator gsi;
   edge e;
   gimple phi, stmt;
+  int flags;
 
   FOR_EACH_BB (bb)
     {
@@ -454,9 +448,8 @@ find_obviously_necessary_stmts (struct edge_list *el)
 
   /* Pure and const functions are finite and thus have no infinite loops in
      them.  */
-  if ((TREE_READONLY (current_function_decl)
-       || DECL_PURE_P (current_function_decl))
-      && !DECL_LOOPING_CONST_OR_PURE_P (current_function_decl))
+  flags = flags_from_decl_or_type (current_function_decl);
+  if ((flags & (ECF_CONST|ECF_PURE)) && !(flags & ECF_LOOPING_CONST_OR_PURE))
     return;
 
   /* Prevent the empty possibly infinite loops from being removed.  */
@@ -497,6 +490,7 @@ find_obviously_necessary_stmts (struct edge_list *el)
 static bool
 ref_may_be_aliased (tree ref)
 {
+  gcc_assert (TREE_CODE (ref) != WITH_SIZE_EXPR);
   while (handled_component_p (ref))
     ref = TREE_OPERAND (ref, 0);
   if (TREE_CODE (ref) == MEM_REF
@@ -529,7 +523,14 @@ mark_aliased_reaching_defs_necessary_1 (ao_ref *ref, tree vdef, void *data)
 
   /* If the stmt lhs kills ref, then we can stop walking.  */
   if (gimple_has_lhs (def_stmt)
-      && TREE_CODE (gimple_get_lhs (def_stmt)) != SSA_NAME)
+      && TREE_CODE (gimple_get_lhs (def_stmt)) != SSA_NAME
+      /* The assignment is not necessarily carried out if it can throw
+         and we can catch it in the current function where we could inspect
+        the previous value.
+         ???  We only need to care about the RHS throwing.  For aggregate
+        assignments or similar calls and non-call exceptions the LHS
+        might throw as well.  */
+      && !stmt_can_throw_internal (def_stmt))
     {
       tree base, lhs = gimple_get_lhs (def_stmt);
       HOST_WIDE_INT size, offset, max_size;
@@ -831,8 +832,14 @@ propagate_necessity (struct edge_list *el)
              if (callee != NULL_TREE
                  && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
                  && (DECL_FUNCTION_CODE (callee) == BUILT_IN_MEMSET
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_MEMSET_CHK
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_MALLOC
-                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE))
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_CALLOC
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE
+                     || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
                continue;
 
              /* Calls implicitly load from memory, their arguments
@@ -844,6 +851,8 @@ propagate_necessity (struct edge_list *el)
                  if (TREE_CODE (arg) == SSA_NAME
                      || is_gimple_min_invariant (arg))
                    continue;
+                 if (TREE_CODE (arg) == WITH_SIZE_EXPR)
+                   arg = TREE_OPERAND (arg, 0);
                  if (!ref_may_be_aliased (arg))
                    mark_aliased_reaching_defs_necessary (stmt, arg);
                }
@@ -869,7 +878,8 @@ propagate_necessity (struct edge_list *el)
            {
              tree rhs = gimple_return_retval (stmt);
              /* A return statement may perform a load.  */
-             if (TREE_CODE (rhs) != SSA_NAME
+             if (rhs
+                 && TREE_CODE (rhs) != SSA_NAME
                  && !is_gimple_min_invariant (rhs))
                {
                  if (!ref_may_be_aliased (rhs))
@@ -1408,6 +1418,8 @@ perform_tree_ssa_dce (bool aggressive)
   struct edge_list *el = NULL;
   bool something_changed = 0;
 
+  calculate_dominance_info (CDI_DOMINATORS);
+
   /* Preheaders are needed for SCEV to work.
      Simple lateches and recorded exits improve chances that loop will
      proved to be finite in testcases such as in loop-15.c and loop-24.c  */
@@ -1522,7 +1534,7 @@ struct gimple_opt_pass pass_dce =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa     /* todo_flags_finish */
+  TODO_verify_ssa                      /* todo_flags_finish */
  }
 };
 
@@ -1541,7 +1553,7 @@ struct gimple_opt_pass pass_dce_loop =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa     /* todo_flags_finish */
+  TODO_verify_ssa                      /* todo_flags_finish */
  }
 };
 
@@ -1560,7 +1572,7 @@ struct gimple_opt_pass pass_cd_dce =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa
+  TODO_verify_ssa
   | TODO_verify_flow                   /* todo_flags_finish */
  }
 };