OSDN Git Service

PR debug/50317
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-live.c
index 65b3855..31eac11 100644 (file)
@@ -1,5 +1,5 @@
 /* Liveness for SSA trees.
-   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Andrew MacLeod <amacleod@redhat.com>
 
@@ -374,7 +374,8 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data)
      eliminated as unused.  */
   if (TREE_CODE (t) == VAR_DECL)
     {
-      if (data != NULL && bitmap_clear_bit ((bitmap) data, DECL_UID (t)))
+      if (data != NULL && bitmap_clear_bit ((bitmap) data, DECL_UID (t))
+         && DECL_CONTEXT (t) == current_function_decl)
        mark_all_vars_used (&DECL_INITIAL (t), data);
       set_is_used (t);
     }
@@ -688,6 +689,7 @@ remove_unused_locals (void)
   referenced_var_iterator rvi;
   bitmap global_unused_vars = NULL;
   unsigned srcidx, dstidx, num;
+  bool have_local_clobbers = false;
 
   /* Removing declarations from lexical blocks when not optimizing is
      not only a waste of time, it actually causes differences in stack
@@ -720,6 +722,12 @@ remove_unused_locals (void)
          if (is_gimple_debug (stmt))
            continue;
 
+         if (gimple_clobber_p (stmt))
+           {
+             have_local_clobbers = true;
+             continue;
+           }
+
          if (b)
            TREE_USED (b) = true;
 
@@ -753,6 +761,41 @@ remove_unused_locals (void)
          TREE_USED (e->goto_block) = true;
     }
 
+  /* We do a two-pass approach about the out-of-scope clobbers.  We want
+     to remove them if they are the only references to a local variable,
+     but we want to retain them when there's any other.  So the first pass
+     ignores them, and the second pass (if there were any) tries to remove
+     them.  */
+  if (have_local_clobbers)
+    FOR_EACH_BB (bb)
+      {
+       gimple_stmt_iterator gsi;
+
+       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
+         {
+           gimple stmt = gsi_stmt (gsi);
+           tree b = gimple_block (stmt);
+
+           if (gimple_clobber_p (stmt))
+             {
+               tree lhs = gimple_assign_lhs (stmt);
+               lhs = get_base_address (lhs);
+               if (TREE_CODE (lhs) == SSA_NAME)
+                 lhs = SSA_NAME_VAR (lhs);
+               if (DECL_P (lhs) && (!var_ann (lhs) || !is_used_p (lhs)))
+                 {
+                   unlink_stmt_vdef (stmt);
+                   gsi_remove (&gsi, true);
+                   release_defs (stmt);
+                   continue;
+                 }
+               if (b)
+                 TREE_USED (b) = true;
+             }
+           gsi_next (&gsi);
+         }
+      }
+
   cfun->has_local_explicit_reg_vars = false;
 
   /* Remove unmarked local vars from local_decls.  */
@@ -794,7 +837,8 @@ remove_unused_locals (void)
        if (TREE_CODE (var) == VAR_DECL
            && is_global_var (var)
            && var_ann (var) != NULL
-           && is_used_p (var))
+           && is_used_p (var)
+           && DECL_CONTEXT (var) == current_function_decl)
          mark_all_vars_used (&DECL_INITIAL (var), global_unused_vars);
 
       num = VEC_length (tree, cfun->local_decls);