OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-live.c
index a78dd9c..80ab425 100644 (file)
@@ -1,5 +1,6 @@
 /* Liveness for SSA trees.
-   Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
    Contributed by Andrew MacLeod <amacleod@redhat.com>
 
 This file is part of GCC.
@@ -23,14 +24,16 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
 #include "bitmap.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "tree-ssa-live.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "debug.h"
 #include "flags.h"
+#include "gimple.h"
 
 #ifdef ENABLE_CHECKING
 static void  verify_live_on_entry (tree_live_info_p);
@@ -46,7 +49,7 @@ static void  verify_live_on_entry (tree_live_info_p);
    At the end of out-of-ssa, each partition becomes a "real" variable and is
    rewritten as a compiler variable.
 
-   The var_map datat structure is used to manage these partitions.  It allows
+   The var_map data structure is used to manage these partitions.  It allows
    partitions to be combined, and determines which partition belongs to what
    ssa_name or variable, and vice versa.  */
 
@@ -59,7 +62,7 @@ var_map_base_init (var_map map)
   int x, num_part, num;
   tree var;
   var_ann_t ann;
-  
+
   num = 0;
   num_part = num_var_partitions (map);
 
@@ -135,9 +138,6 @@ init_var_map (int size)
 
   map = (var_map) xmalloc (sizeof (struct _var_map));
   map->var_partition = partition_new (size);
-  map->partition_to_var 
-             = (tree *)xmalloc (size * sizeof (tree));
-  memset (map->partition_to_var, 0, size * sizeof (tree));
 
   map->partition_to_view = NULL;
   map->view_to_partition = NULL;
@@ -156,59 +156,31 @@ void
 delete_var_map (var_map map)
 {
   var_map_base_fini (map);
-  free (map->partition_to_var);
   partition_delete (map->var_partition);
-  if (map->partition_to_view)
-    free (map->partition_to_view);
-  if (map->view_to_partition)
-    free (map->view_to_partition);
+  free (map->partition_to_view);
+  free (map->view_to_partition);
   free (map);
 }
 
 
-/* This function will combine the partitions in MAP for VAR1 and VAR2.  It 
-   Returns the partition which represents the new partition.  If the two 
+/* This function will combine the partitions in MAP for VAR1 and VAR2.  It
+   Returns the partition which represents the new partition.  If the two
    partitions cannot be combined, NO_PARTITION is returned.  */
 
 int
 var_union (var_map map, tree var1, tree var2)
 {
   int p1, p2, p3;
-  tree root_var = NULL_TREE;
-  tree other_var = NULL_TREE;
 
-  /* This is independent of partition_to_view. If partition_to_view is 
+  gcc_assert (TREE_CODE (var1) == SSA_NAME);
+  gcc_assert (TREE_CODE (var2) == SSA_NAME);
+
+  /* This is independent of partition_to_view. If partition_to_view is
      on, then whichever one of these partitions is absorbed will never have a
      dereference into the partition_to_view array any more.  */
 
-  if (TREE_CODE (var1) == SSA_NAME)
-    p1 = partition_find (map->var_partition, SSA_NAME_VERSION (var1));
-  else
-    {
-      p1 = var_to_partition (map, var1);
-      if (map->view_to_partition)
-        p1 = map->view_to_partition[p1];
-      root_var = var1;
-    }
-  
-  if (TREE_CODE (var2) == SSA_NAME)
-    p2 = partition_find (map->var_partition, SSA_NAME_VERSION (var2));
-  else
-    {
-      p2 = var_to_partition (map, var2);
-      if (map->view_to_partition)
-        p2 = map->view_to_partition[p2];
-
-      /* If there is no root_var set, or it's not a user variable, set the
-        root_var to this one.  */
-      if (!root_var || (DECL_P (root_var) && DECL_IGNORED_P (root_var)))
-        {
-         other_var = root_var;
-         root_var = var2;
-       }
-      else 
-       other_var = var2;
-    }
+  p1 = partition_find (map->var_partition, SSA_NAME_VERSION (var1));
+  p2 = partition_find (map->var_partition, SSA_NAME_VERSION (var2));
 
   gcc_assert (p1 != NO_PARTITION);
   gcc_assert (p2 != NO_PARTITION);
@@ -221,20 +193,15 @@ var_union (var_map map, tree var1, tree var2)
   if (map->partition_to_view)
     p3 = map->partition_to_view[p3];
 
-  if (root_var)
-    change_partition_var (map, root_var, p3);
-  if (other_var)
-    change_partition_var (map, other_var, p3);
-
   return p3;
 }
 
-/* Compress the partition numbers in MAP such that they fall in the range 
+
+/* Compress the partition numbers in MAP such that they fall in the range
    0..(num_partitions-1) instead of wherever they turned out during
    the partitioning exercise.  This removes any references to unused
    partitions, thereby allowing bitmaps and other vectors to be much
-   denser.  
+   denser.
 
    This is implemented such that compaction doesn't affect partitioning.
    Ie., once partitions are created and possibly merged, running one
@@ -248,8 +215,8 @@ var_union (var_map map, tree var1, tree var2)
    definitions for assignment to program variables.  */
 
 
-/* Set MAP back to the initial state of having no partition view.  Return a 
-   bitmap which has a bit set for each partition number which is in use in the 
+/* Set MAP back to the initial state of having no partition view.  Return a
+   bitmap which has a bit set for each partition number which is in use in the
    varmap.  */
 
 static bitmap
@@ -277,7 +244,9 @@ partition_view_init (var_map map)
   for (x = 0; x < map->partition_size; x++)
     {
       tmp = partition_find (map->var_partition, x);
-      if (map->partition_to_var[tmp] != NULL_TREE && !bitmap_bit_p (used, tmp))
+      if (ssa_name (tmp) != NULL_TREE && is_gimple_reg (ssa_name (tmp))
+         && (!has_zero_uses (ssa_name (tmp))
+             || !SSA_NAME_IS_DEFAULT_DEF (ssa_name (tmp))))
        bitmap_set_bit (used, tmp);
     }
 
@@ -287,16 +256,15 @@ partition_view_init (var_map map)
 
 
 /* This routine will finalize the view data for MAP based on the partitions
-   set in SELECTED.  This is either the same bitmap returned from 
+   set in SELECTED.  This is either the same bitmap returned from
    partition_view_init, or a trimmed down version if some of those partitions
    were not desired in this view.  SELECTED is freed before returning.  */
 
-static void 
+static void
 partition_view_fini (var_map map, bitmap selected)
 {
   bitmap_iterator bi;
   unsigned count, i, x, limit;
-  tree var;
 
   gcc_assert (selected);
 
@@ -316,11 +284,6 @@ partition_view_fini (var_map map, bitmap selected)
        {
          map->partition_to_view[x] = i;
          map->view_to_partition[i] = x;
-         var = map->partition_to_var[x];
-         /* If any one of the members of a partition is not an SSA_NAME, make
-            sure it is the representative.  */
-         if (TREE_CODE (var) != SSA_NAME)
-           change_partition_var (map, var, i);
          i++;
        }
       gcc_assert (i == count);
@@ -331,7 +294,7 @@ partition_view_fini (var_map map, bitmap selected)
 }
 
 
-/* Create a partition view which includes all the used partitions in MAP.  If 
+/* Create a partition view which includes all the used partitions in MAP.  If
    WANT_BASES is true, create the base variable map as well.  */
 
 extern void
@@ -349,8 +312,8 @@ partition_view_normal (var_map map, bool want_bases)
 }
 
 
-/* Create a partition view in MAP which includes just partitions which occur in 
-   the bitmap ONLY. If WANT_BASES is true, create the base variable map 
+/* Create a partition view in MAP which includes just partitions which occur in
+   the bitmap ONLY. If WANT_BASES is true, create the base variable map
    as well.  */
 
 extern void
@@ -378,32 +341,12 @@ partition_view_bitmap (var_map map, bitmap only, bool want_bases)
 }
 
 
-/* This function is used to change the representative variable in MAP for VAR's 
-   partition to a regular non-ssa variable.  This allows partitions to be 
-   mapped back to real variables.  */
-  
-void 
-change_partition_var (var_map map, tree var, int part)
-{
-  var_ann_t ann;
-
-  gcc_assert (TREE_CODE (var) != SSA_NAME);
-
-  ann = var_ann (var);
-  ann->out_of_ssa_tag = 1;
-  VAR_ANN_PARTITION (ann) = part;
-  if (map->view_to_partition)
-    map->partition_to_var[map->view_to_partition[part]] = var;
-}
-
-
-static inline void mark_all_vars_used (tree *);
+static inline void mark_all_vars_used (tree *, void *data);
 
 /* Helper function for mark_all_vars_used, called via walk_tree.  */
 
 static tree
-mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
-                     void *data ATTRIBUTE_UNUSED)
+mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data)
 {
   tree t = *tp;
   enum tree_code_class c = TREE_CODE_CLASS (TREE_CODE (t));
@@ -411,18 +354,18 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
 
   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
-  if ((IS_EXPR_CODE_CLASS (c)
-       || IS_GIMPLE_STMT_CODE_CLASS (c))
+
+  if (IS_EXPR_CODE_CLASS (c)
       && (b = TREE_BLOCK (t)) != NULL)
     TREE_USED (b) = true;
 
-  /* Ignore TREE_ORIGINAL for TARGET_MEM_REFS, as well as other
-     fields that do not contain vars.  */
+  /* Ignore TMR_OFFSET and TMR_STEP for TARGET_MEM_REFS, as those
+     fields do not contain vars.  */
   if (TREE_CODE (t) == TARGET_MEM_REF)
     {
-      mark_all_vars_used (&TMR_SYMBOL (t));
-      mark_all_vars_used (&TMR_BASE (t));
-      mark_all_vars_used (&TMR_INDEX (t));
+      mark_all_vars_used (&TMR_BASE (t), data);
+      mark_all_vars_used (&TMR_INDEX (t), data);
+      mark_all_vars_used (&TMR_INDEX2 (t), data);
       *walk_subtrees = 0;
       return NULL;
     }
@@ -430,7 +373,20 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
   /* Only need to mark VAR_DECLS; parameters and return results are not
      eliminated as unused.  */
   if (TREE_CODE (t) == VAR_DECL)
-    set_is_used (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);
+    }
+  /* remove_unused_scope_block_p requires information about labels
+     which are not DECL_IGNORED_P to tell if they might be used in the IL.  */
+  if (TREE_CODE (t) == LABEL_DECL)
+    /* Although the TREE_USED values that the frontend uses would be
+       acceptable (albeit slightly over-conservative) for our purposes,
+       init_vars_expansion clears TREE_USED for LABEL_DECLs too, so we
+       must re-compute it here.  */
+    TREE_USED (t) = 1;
 
   if (IS_TYPE_OR_DECL_P (t))
     *walk_subtrees = 0;
@@ -453,7 +409,7 @@ mark_scope_block_unused (tree scope)
 }
 
 /* Look if the block is dead (by possibly eliminating its dead subblocks)
-   and return true if so.  
+   and return true if so.
    Block is declared dead if:
      1) No statements are associated with it.
      2) Declares no live variables
@@ -470,33 +426,82 @@ remove_unused_scope_block_p (tree scope)
 {
   tree *t, *next;
   bool unused = !TREE_USED (scope);
-  var_ann_t ann;
   int nsubblocks = 0;
 
   for (t = &BLOCK_VARS (scope); *t; t = next)
     {
-      next = &TREE_CHAIN (*t);
+      next = &DECL_CHAIN (*t);
 
       /* Debug info of nested function refers to the block of the
-        function.  */
+        function.  We might stil call it even if all statements
+        of function it was nested into was elliminated.
+
+        TODO: We can actually look into cgraph to see if function
+        will be output to file.  */
       if (TREE_CODE (*t) == FUNCTION_DECL)
        unused = false;
 
+      /* If a decl has a value expr, we need to instantiate it
+        regardless of debug info generation, to avoid codegen
+        differences in memory overlap tests.  update_equiv_regs() may
+        indirectly call validate_equiv_mem() to test whether a
+        SET_DEST overlaps with others, and if the value expr changes
+        by virtual register instantiation, we may get end up with
+        different results.  */
+      else if (TREE_CODE (*t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*t))
+       unused = false;
+
+      /* Remove everything we don't generate debug info for.  */
+      else if (DECL_IGNORED_P (*t))
+       {
+         *t = DECL_CHAIN (*t);
+         next = t;
+       }
+
       /* When we are outputting debug info, we usually want to output
         info about optimized-out variables in the scope blocks.
         Exception are the scope blocks not containing any instructions
         at all so user can't get into the scopes at first place.  */
-      else if ((ann = var_ann (*t)) != NULL
-               && ann->used)
+      else if (var_ann (*t) != NULL && is_used_p (*t))
+       unused = false;
+      else if (TREE_CODE (*t) == LABEL_DECL && TREE_USED (*t))
+       /* For labels that are still used in the IL, the decision to
+          preserve them must not depend DEBUG_INFO_LEVEL, otherwise we
+          risk having different ordering in debug vs.  non-debug builds
+          during inlining or versioning.
+          A label appearing here (we have already checked DECL_IGNORED_P)
+          should not be used in the IL unless it has been explicitly used
+          before, so we use TREE_USED as an approximation.  */
+       /* In principle, we should do the same here as for the debug case
+          below, however, when debugging, there might be additional nested
+          levels that keep an upper level with a label live, so we have to
+          force this block to be considered used, too.  */
        unused = false;
 
       /* When we are not doing full debug info, we however can keep around
         only the used variables for cfgexpand's memory packing saving quite
-        a lot of memory.  */
-      else if (debug_info_level != DINFO_LEVEL_NORMAL
-              && debug_info_level != DINFO_LEVEL_VERBOSE)
+        a lot of memory.
+
+        For sake of -g3, we keep around those vars but we don't count this as
+        use of block, so innermost block with no used vars and no instructions
+        can be considered dead.  We only want to keep around blocks user can
+        breakpoint into and ask about value of optimized out variables.
+
+        Similarly we need to keep around types at least until all
+        variables of all nested blocks are gone.  We track no
+        information on whether given type is used or not, so we have
+        to keep them even when not emitting debug information,
+        otherwise we may end up remapping variables and their (local)
+        types in different orders depending on whether debug
+        information is being generated.  */
+
+      else if (TREE_CODE (*t) == TYPE_DECL
+              || debug_info_level == DINFO_LEVEL_NORMAL
+              || debug_info_level == DINFO_LEVEL_VERBOSE)
+       ;
+      else
        {
-         *t = TREE_CHAIN (*t);
+         *t = DECL_CHAIN (*t);
          next = t;
        }
     }
@@ -508,126 +513,364 @@ remove_unused_scope_block_p (tree scope)
          {
            tree next = BLOCK_CHAIN (*t);
            tree supercontext = BLOCK_SUPERCONTEXT (*t);
+
            *t = BLOCK_SUBBLOCKS (*t);
-           gcc_assert (!BLOCK_CHAIN (*t));
+           while (BLOCK_CHAIN (*t))
+             {
+               BLOCK_SUPERCONTEXT (*t) = supercontext;
+               t = &BLOCK_CHAIN (*t);
+             }
            BLOCK_CHAIN (*t) = next;
            BLOCK_SUPERCONTEXT (*t) = supercontext;
            t = &BLOCK_CHAIN (*t);
            nsubblocks ++;
          }
        else
-          *t = BLOCK_CHAIN (*t);
+         *t = BLOCK_CHAIN (*t);
       }
     else
       {
         t = &BLOCK_CHAIN (*t);
        nsubblocks ++;
       }
+
+
+   if (!unused)
+     ;
    /* Outer scope is always used.  */
-   if (!BLOCK_SUPERCONTEXT (scope)
-       || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL)
+   else if (!BLOCK_SUPERCONTEXT (scope)
+            || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL)
      unused = false;
-   /* If there are more than one live subblocks, it is used.  */
-   else if (nsubblocks > 1)
+   /* Innermost blocks with no live variables nor statements can be always
+      eliminated.  */
+   else if (!nsubblocks)
+     ;
+   /* For terse debug info we can eliminate info on unused variables.  */
+   else if (debug_info_level == DINFO_LEVEL_NONE
+           || debug_info_level == DINFO_LEVEL_TERSE)
+     {
+       /* Even for -g0/-g1 don't prune outer scopes from artificial
+         functions, otherwise diagnostics using tree_nonartificial_location
+         will not be emitted properly.  */
+       if (inlined_function_outer_scope_p (scope))
+        {
+          tree ao = scope;
+
+          while (ao
+                 && TREE_CODE (ao) == BLOCK
+                 && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
+            ao = BLOCK_ABSTRACT_ORIGIN (ao);
+          if (ao
+              && TREE_CODE (ao) == FUNCTION_DECL
+              && DECL_DECLARED_INLINE_P (ao)
+              && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
+            unused = false;
+        }
+     }
+   else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope))
      unused = false;
-   /* When there is only one subblock, see if it is just wrapper we can
-      ignore.  Wrappers are not declaring any variables and not changing
-      abstract origin.  */
-   else if (nsubblocks == 1
-           && (BLOCK_VARS (scope)
-               || ((debug_info_level == DINFO_LEVEL_NORMAL
-                    || debug_info_level == DINFO_LEVEL_VERBOSE)
-                   && ((BLOCK_ABSTRACT_ORIGIN (scope)
-                       != BLOCK_ABSTRACT_ORIGIN (BLOCK_SUPERCONTEXT (scope)))))))
+   /* See if this block is important for representation of inlined function.
+      Inlined functions are always represented by block with
+      block_ultimate_origin being set to FUNCTION_DECL and DECL_SOURCE_LOCATION
+      set...  */
+   else if (inlined_function_outer_scope_p (scope))
      unused = false;
+   else
+   /* Verfify that only blocks with source location set
+      are entry points to the inlined functions.  */
+     gcc_assert (BLOCK_SOURCE_LOCATION (scope) == UNKNOWN_LOCATION);
+
+   TREE_USED (scope) = !unused;
    return unused;
 }
 
-/* Mark all VAR_DECLS under *EXPR_P as used, so that they won't be 
+/* Mark all VAR_DECLS under *EXPR_P as used, so that they won't be
    eliminated during the tree->rtl conversion process.  */
 
 static inline void
-mark_all_vars_used (tree *expr_p)
+mark_all_vars_used (tree *expr_p, void *data)
 {
-  walk_tree (expr_p, mark_all_vars_used_1, NULL, NULL);
+  walk_tree (expr_p, mark_all_vars_used_1, data, NULL);
 }
 
 
+/* Dump scope blocks starting at SCOPE to FILE.  INDENT is the
+   indentation level and FLAGS is as in print_generic_expr.  */
+
+static void
+dump_scope_block (FILE *file, int indent, tree scope, int flags)
+{
+  tree var, t;
+  unsigned int i;
+
+  fprintf (file, "\n%*s{ Scope block #%i%s%s",indent, "" , BLOCK_NUMBER (scope),
+          TREE_USED (scope) ? "" : " (unused)",
+          BLOCK_ABSTRACT (scope) ? " (abstract)": "");
+  if (BLOCK_SOURCE_LOCATION (scope) != UNKNOWN_LOCATION)
+    {
+      expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope));
+      fprintf (file, " %s:%i", s.file, s.line);
+    }
+  if (BLOCK_ABSTRACT_ORIGIN (scope))
+    {
+      tree origin = block_ultimate_origin (scope);
+      if (origin)
+       {
+         fprintf (file, " Originating from :");
+         if (DECL_P (origin))
+           print_generic_decl (file, origin, flags);
+         else
+           fprintf (file, "#%i", BLOCK_NUMBER (origin));
+       }
+    }
+  fprintf (file, " \n");
+  for (var = BLOCK_VARS (scope); var; var = DECL_CHAIN (var))
+    {
+      bool used = false;
+
+      if (var_ann (var))
+       used = is_used_p (var);
+
+      fprintf (file, "%*s", indent, "");
+      print_generic_decl (file, var, flags);
+      fprintf (file, "%s\n", used ? "" : " (unused)");
+    }
+  for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (scope); i++)
+    {
+      fprintf (file, "%*s",indent, "");
+      print_generic_decl (file, BLOCK_NONLOCALIZED_VAR (scope, i),
+                         flags);
+      fprintf (file, " (nonlocalized)\n");
+    }
+  for (t = BLOCK_SUBBLOCKS (scope); t ; t = BLOCK_CHAIN (t))
+    dump_scope_block (file, indent + 2, t, flags);
+  fprintf (file, "\n%*s}\n",indent, "");
+}
+
+/* Dump the tree of lexical scopes starting at SCOPE to stderr.  FLAGS
+   is as in print_generic_expr.  */
+
+DEBUG_FUNCTION void
+debug_scope_block (tree scope, int flags)
+{
+  dump_scope_block (stderr, 0, scope, flags);
+}
+
+
+/* Dump the tree of lexical scopes of current_function_decl to FILE.
+   FLAGS is as in print_generic_expr.  */
+
+void
+dump_scope_blocks (FILE *file, int flags)
+{
+  dump_scope_block (file, 0, DECL_INITIAL (current_function_decl), flags);
+}
+
+
+/* Dump the tree of lexical scopes of current_function_decl to stderr.
+   FLAGS is as in print_generic_expr.  */
+
+DEBUG_FUNCTION void
+debug_scope_blocks (int flags)
+{
+  dump_scope_blocks (stderr, flags);
+}
+
 /* Remove local variables that are not referenced in the IL.  */
 
 void
 remove_unused_locals (void)
 {
   basic_block bb;
-  tree t, *cell;
+  tree var, t;
   referenced_var_iterator rvi;
-  var_ann_t ann;
+  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
+     layout.  */
+  if (!optimize)
+    return;
+
+  timevar_push (TV_REMOVE_UNUSED);
 
   mark_scope_block_unused (DECL_INITIAL (current_function_decl));
+
   /* Assume all locals are unused.  */
-  FOR_EACH_REFERENCED_VAR (t, rvi)
-    var_ann (t)->used = false;
+  FOR_EACH_REFERENCED_VAR (cfun, t, rvi)
+    clear_is_used (t);
 
   /* Walk the CFG marking all referenced symbols.  */
   FOR_EACH_BB (bb)
     {
-      block_stmt_iterator bsi;
-      tree phi, def;
+      gimple_stmt_iterator gsi;
+      size_t i;
+      edge_iterator ei;
+      edge e;
 
       /* Walk the statements.  */
-      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-       mark_all_vars_used (bsi_stmt_ptr (bsi));
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+         tree b = gimple_block (stmt);
+
+         if (is_gimple_debug (stmt))
+           continue;
 
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+         if (gimple_clobber_p (stmt))
+           {
+             have_local_clobbers = true;
+             continue;
+           }
+
+         if (b)
+           TREE_USED (b) = true;
+
+         for (i = 0; i < gimple_num_ops (stmt); i++)
+           mark_all_vars_used (gimple_op_ptr (gsi_stmt (gsi), i), NULL);
+       }
+
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
         {
           use_operand_p arg_p;
           ssa_op_iter i;
+         tree def;
+         gimple phi = gsi_stmt (gsi);
 
          /* No point processing globals.  */
-         if (is_global_var (SSA_NAME_VAR (PHI_RESULT (phi))))
+         if (is_global_var (SSA_NAME_VAR (gimple_phi_result (phi))))
            continue;
 
-          def = PHI_RESULT (phi);
-          mark_all_vars_used (&def);
+         def = gimple_phi_result (phi);
+         mark_all_vars_used (&def, NULL);
 
           FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
             {
              tree arg = USE_FROM_PTR (arg_p);
-             mark_all_vars_used (&arg);
+             mark_all_vars_used (&arg, NULL);
             }
         }
+
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       if (e->goto_locus)
+         TREE_USED (e->goto_block) = true;
     }
 
-  /* Remove unmarked vars and clear used flag.  */
-  for (cell = &cfun->unexpanded_var_list; *cell; )
-    {
-      tree var = TREE_VALUE (*cell);
+  /* 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.  */
+  num = VEC_length (tree, cfun->local_decls);
+  for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
+    {
+      var = VEC_index (tree, cfun->local_decls, srcidx);
       if (TREE_CODE (var) != FUNCTION_DECL
-         && (!(ann = var_ann (var))
-             || !ann->used))
+         && (!var_ann (var)
+             || !is_used_p (var)))
+       {
+         if (is_global_var (var))
+           {
+             if (global_unused_vars == NULL)
+               global_unused_vars = BITMAP_ALLOC (NULL);
+             bitmap_set_bit (global_unused_vars, DECL_UID (var));
+           }
+         else
+           continue;
+       }
+      else if (TREE_CODE (var) == VAR_DECL
+              && DECL_HARD_REGISTER (var)
+              && !is_global_var (var))
+       cfun->has_local_explicit_reg_vars = true;
+
+      if (srcidx != dstidx)
+       VEC_replace (tree, cfun->local_decls, dstidx, var);
+      dstidx++;
+    }
+  if (dstidx != num)
+    VEC_truncate (tree, cfun->local_decls, dstidx);
+
+  /* Remove unmarked global vars from local_decls.  */
+  if (global_unused_vars != NULL)
+    {
+      tree var;
+      unsigned ix;
+      FOR_EACH_LOCAL_DECL (cfun, ix, var)
+       if (TREE_CODE (var) == VAR_DECL
+           && is_global_var (var)
+           && var_ann (var) != NULL
+           && 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);
+      for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
        {
-         *cell = TREE_CHAIN (*cell);
-         continue;
+         var = VEC_index (tree, cfun->local_decls, srcidx);
+         if (TREE_CODE (var) == VAR_DECL
+             && is_global_var (var)
+             && bitmap_bit_p (global_unused_vars, DECL_UID (var)))
+           continue;
+
+         if (srcidx != dstidx)
+           VEC_replace (tree, cfun->local_decls, dstidx, var);
+         dstidx++;
        }
-      cell = &TREE_CHAIN (*cell);
+      if (dstidx != num)
+       VEC_truncate (tree, cfun->local_decls, dstidx);
+      BITMAP_FREE (global_unused_vars);
     }
 
-  /* Remove unused variables from REFERENCED_VARs.  As a special
-     exception keep the variables that are believed to be aliased.
-     Those can't be easily removed from the alias sets and operand
-     caches.  They will be removed shortly after the next may_alias
-     pass is performed.  */
-  FOR_EACH_REFERENCED_VAR (t, rvi)
+  /* Remove unused variables from REFERENCED_VARs.  */
+  FOR_EACH_REFERENCED_VAR (cfun, t, rvi)
     if (!is_global_var (t)
-       && !MTAG_P (t)
        && TREE_CODE (t) != PARM_DECL
        && TREE_CODE (t) != RESULT_DECL
-       && !(ann = var_ann (t))->used
-       && !ann->symbol_mem_tag
-       && !TREE_ADDRESSABLE (t))
+       && !is_used_p (t))
       remove_referenced_var (t);
   remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Scope blocks after cleanups:\n");
+      dump_scope_blocks (dump_file, dump_flags);
+    }
+
+  timevar_pop (TV_REMOVE_UNUSED);
 }
 
 
@@ -661,7 +904,7 @@ new_tree_live_info (var_map map)
 
 /* Free storage for live range info object LIVE.  */
 
-void 
+void
 delete_tree_live_info (tree_live_info_p live)
 {
   int x;
@@ -681,12 +924,12 @@ delete_tree_live_info (tree_live_info_p live)
 }
 
 
-/* Visit basic block BB and propagate any required live on entry bits from 
-   LIVE into the predecessors.  VISITED is the bitmap of visited blocks.  
+/* Visit basic block BB and propagate any required live on entry bits from
+   LIVE into the predecessors.  VISITED is the bitmap of visited blocks.
    TMP is a temporary work bitmap which is passed in to avoid reallocating
    it each time.  */
 
-static void 
+static void
 loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited,
                 bitmap tmp)
 {
@@ -706,12 +949,12 @@ loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited,
       if (pred_bb == ENTRY_BLOCK_PTR)
        continue;
       /* TMP is variables live-on-entry from BB that aren't defined in the
-        predecessor block.  This should be the live on entry vars to pred.  
+        predecessor block.  This should be the live on entry vars to pred.
         Note that liveout is the DEFs in a block while live on entry is
         being calculated.  */
       bitmap_and_compl (tmp, loe, live->liveout[pred_bb->index]);
 
-      /* Add these bits to live-on-entry for the pred. if there are any 
+      /* Add these bits to live-on-entry for the pred. if there are any
         changes, and pred_bb has been visited already, add it to the
         revisit stack.  */
       change = bitmap_ior_into (live_on_entry (live, pred_bb), tmp);
@@ -724,7 +967,7 @@ loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited,
 }
 
 
-/* Using LIVE, fill in all the live-on-entry blocks between the defs and uses 
+/* Using LIVE, fill in all the live-on-entry blocks between the defs and uses
    of all the variables.  */
 
 static void
@@ -762,7 +1005,7 @@ static void
 set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
 {
   int p;
-  tree stmt;
+  gimple stmt;
   use_operand_p use;
   basic_block def_bb = NULL;
   imm_use_iterator imm_iter;
@@ -775,7 +1018,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
   stmt = SSA_NAME_DEF_STMT (ssa_name);
   if (stmt)
     {
-      def_bb = bb_for_stmt (stmt);
+      def_bb = gimple_bb (stmt);
       /* Mark defs in liveout bitmap temporarily.  */
       if (def_bb)
        bitmap_set_bit (live->liveout[def_bb->index], p);
@@ -787,29 +1030,31 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
      add it to the list of live on entry blocks.  */
   FOR_EACH_IMM_USE_FAST (use, imm_iter, ssa_name)
     {
-      tree use_stmt = USE_STMT (use);
+      gimple use_stmt = USE_STMT (use);
       basic_block add_block = NULL;
 
-      if (TREE_CODE (use_stmt) == PHI_NODE)
+      if (gimple_code (use_stmt) == GIMPLE_PHI)
         {
          /* Uses in PHI's are considered to be live at exit of the SRC block
             as this is where a copy would be inserted.  Check to see if it is
             defined in that block, or whether its live on entry.  */
          int index = PHI_ARG_INDEX_FROM_USE (use);
-         edge e = PHI_ARG_EDGE (use_stmt, index);
+         edge e = gimple_phi_arg_edge (use_stmt, index);
          if (e->src != ENTRY_BLOCK_PTR)
            {
              if (e->src != def_bb)
                add_block = e->src;
            }
        }
+      else if (is_gimple_debug (use_stmt))
+       continue;
       else
         {
          /* If its not defined in this block, its live on entry.  */
-         basic_block use_bb = bb_for_stmt (use_stmt);
+         basic_block use_bb = gimple_bb (use_stmt);
          if (use_bb != def_bb)
            add_block = use_bb;
-       }  
+       }
 
       /* If there was a live on entry use, set the bit.  */
       if (add_block)
@@ -831,9 +1076,6 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
 void
 calculate_live_on_exit (tree_live_info_p liveinfo)
 {
-  unsigned i;
-  int p;
-  tree t, phi;
   basic_block bb;
   edge e;
   edge_iterator ei;
@@ -845,20 +1087,29 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
   /* Set all the live-on-exit bits for uses in PHIs.  */
   FOR_EACH_BB (bb)
     {
+      gimple_stmt_iterator gsi;
+      size_t i;
+
       /* Mark the PHI arguments which are live on exit to the pred block.  */
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-       for (i = 0; i < (unsigned)PHI_NUM_ARGS (phi); i++)
-         { 
-           t = PHI_ARG_DEF (phi, i);
-           if (TREE_CODE (t) != SSA_NAME)
-             continue;
-           p = var_to_partition (liveinfo->map, t);
-           if (p == NO_PARTITION)
-             continue;
-           e = PHI_ARG_EDGE (phi, i);
-           if (e->src != ENTRY_BLOCK_PTR)
-             bitmap_set_bit (liveinfo->liveout[e->src->index], p);
-         }
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple phi = gsi_stmt (gsi);
+         for (i = 0; i < gimple_phi_num_args (phi); i++)
+           {
+             tree t = PHI_ARG_DEF (phi, i);
+             int p;
+
+             if (TREE_CODE (t) != SSA_NAME)
+               continue;
+
+             p = var_to_partition (liveinfo->map, t);
+             if (p == NO_PARTITION)
+               continue;
+             e = gimple_phi_arg_edge (phi, i);
+             if (e->src != ENTRY_BLOCK_PTR)
+               bitmap_set_bit (liveinfo->liveout[e->src->index], p);
+           }
+       }
 
       /* Add each successors live on entry to this bock live on exit.  */
       FOR_EACH_EDGE (e, ei, bb->succs)
@@ -869,10 +1120,10 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
 }
 
 
-/* Given partition map MAP, calculate all the live on entry bitmaps for 
+/* Given partition map MAP, calculate all the live on entry bitmaps for
    each partition.  Return a new live info object.  */
 
-tree_live_info_p 
+tree_live_info_p
 calculate_live_ranges (var_map map)
 {
   tree var;
@@ -916,7 +1167,7 @@ dump_var_map (FILE *f, var_map map)
       else
        p = x;
 
-      if (map->partition_to_var[p] == NULL_TREE)
+      if (ssa_name (p) == NULL_TREE)
         continue;
 
       t = 0;
@@ -982,6 +1233,94 @@ dump_live_info (FILE *f, tree_live_info_p live, int flag)
     }
 }
 
+struct GTY(()) numbered_tree_d
+{
+  tree t;
+  int num;
+};
+typedef struct numbered_tree_d numbered_tree;
+
+DEF_VEC_O (numbered_tree);
+DEF_VEC_ALLOC_O (numbered_tree, heap);
+
+/* Compare two declarations references by their DECL_UID / sequence number.
+   Called via qsort.  */
+
+static int
+compare_decls_by_uid (const void *pa, const void *pb)
+{
+  const numbered_tree *nt_a = ((const numbered_tree *)pa);
+  const numbered_tree *nt_b = ((const numbered_tree *)pb);
+
+  if (DECL_UID (nt_a->t) != DECL_UID (nt_b->t))
+    return  DECL_UID (nt_a->t) - DECL_UID (nt_b->t);
+  return nt_a->num - nt_b->num;
+}
+
+/* Called via walk_gimple_stmt / walk_gimple_op by dump_enumerated_decls.  */
+static tree
+dump_enumerated_decls_push (tree *tp, int *walk_subtrees, void *data)
+{
+  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+  VEC (numbered_tree, heap) **list = (VEC (numbered_tree, heap) **) &wi->info;
+  numbered_tree nt;
+
+  if (!DECL_P (*tp))
+    return NULL_TREE;
+  nt.t = *tp;
+  nt.num = VEC_length (numbered_tree, *list);
+  VEC_safe_push (numbered_tree, heap, *list, &nt);
+  *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
+/* Find all the declarations used by the current function, sort them by uid,
+   and emit the sorted list.  Each declaration is tagged with a sequence
+   number indicating when it was found during statement / tree walking,
+   so that TDF_NOUID comparisons of anonymous declarations are still
+   meaningful.  Where a declaration was encountered more than once, we
+   emit only the sequence number of the first encounter.
+   FILE is the dump file where to output the list and FLAGS is as in
+   print_generic_expr.  */
+void
+dump_enumerated_decls (FILE *file, int flags)
+{
+  basic_block bb;
+  struct walk_stmt_info wi;
+  VEC (numbered_tree, heap) *decl_list = VEC_alloc (numbered_tree, heap, 40);
+
+  memset (&wi, '\0', sizeof (wi));
+  wi.info = (void*) decl_list;
+  FOR_EACH_BB (bb)
+    {
+      gimple_stmt_iterator gsi;
+
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       if (!is_gimple_debug (gsi_stmt (gsi)))
+         walk_gimple_stmt (&gsi, NULL, dump_enumerated_decls_push, &wi);
+    }
+  decl_list = (VEC (numbered_tree, heap) *) wi.info;
+  VEC_qsort (numbered_tree, decl_list, compare_decls_by_uid);
+  if (VEC_length (numbered_tree, decl_list))
+    {
+      unsigned ix;
+      numbered_tree *ntp;
+      tree last = NULL_TREE;
+
+      fprintf (file, "Declarations used by %s, sorted by DECL_UID:\n",
+              current_function_name ());
+      FOR_EACH_VEC_ELT (numbered_tree, decl_list, ix, ntp)
+       {
+         if (ntp->t == last)
+           continue;
+         fprintf (file, "%d: ", ntp->num);
+         print_generic_decl (file, ntp->t, flags);
+         fprintf (file, "\n");
+         last = ntp->t;
+       }
+    }
+  VEC_free (numbered_tree, heap, decl_list);
+}
 
 #ifdef ENABLE_CHECKING
 /* Verify that SSA_VAR is a non-virtual SSA_NAME.  */
@@ -1007,7 +1346,7 @@ verify_live_on_entry (tree_live_info_p live)
 {
   unsigned i;
   tree var;
-  tree phi, stmt;
+  gimple stmt;
   basic_block bb;
   edge e;
   int num;
@@ -1031,13 +1370,13 @@ verify_live_on_entry (tree_live_info_p live)
          bitmap loe;
          var = partition_to_var (map, i);
          stmt = SSA_NAME_DEF_STMT (var);
-         tmp = bb_for_stmt (stmt);
+         tmp = gimple_bb (stmt);
          d = gimple_default_def (cfun, SSA_NAME_VAR (var));
 
          loe = live_on_entry (live, e->dest);
          if (loe && bitmap_bit_p (loe, i))
            {
-             if (!IS_EMPTY_STMT (stmt))
+             if (!gimple_nop_p (stmt))
                {
                  num++;
                  print_generic_expr (stderr, var, TDF_SLIM);
@@ -1045,8 +1384,8 @@ verify_live_on_entry (tree_live_info_p live)
                  if (tmp)
                    fprintf (stderr, " in BB%d, ", tmp->index);
                  fprintf (stderr, "by:\n");
-                 print_generic_expr (stderr, stmt, TDF_SLIM);
-                 fprintf (stderr, "\nIt is also live-on-entry to entry BB %d", 
+                 print_gimple_stmt (stderr, stmt, 0, TDF_SLIM);
+                 fprintf (stderr, "\nIt is also live-on-entry to entry BB %d",
                           entry_block);
                  fprintf (stderr, " So it appears to have multiple defs.\n");
                }
@@ -1056,7 +1395,8 @@ verify_live_on_entry (tree_live_info_p live)
                    {
                      num++;
                      print_generic_expr (stderr, var, TDF_SLIM);
-                     fprintf (stderr, " is live-on-entry to BB%d ",entry_block);
+                     fprintf (stderr, " is live-on-entry to BB%d ",
+                              entry_block);
                      if (d)
                        {
                          fprintf (stderr, " but is not the default def of ");
@@ -1071,17 +1411,20 @@ verify_live_on_entry (tree_live_info_p live)
          else
            if (d == var)
              {
-               /* The only way this var shouldn't be marked live on entry is 
+               /* The only way this var shouldn't be marked live on entry is
                   if it occurs in a PHI argument of the block.  */
-               int z, ok = 0;
-               for (phi = phi_nodes (e->dest); 
-                    phi && !ok; 
-                    phi = PHI_CHAIN (phi))
+               size_t z;
+               bool ok = false;
+               gimple_stmt_iterator gsi;
+               for (gsi = gsi_start_phis (e->dest);
+                    !gsi_end_p (gsi) && !ok;
+                    gsi_next (&gsi))
                  {
-                   for (z = 0; z < PHI_NUM_ARGS (phi); z++)
-                     if (var == PHI_ARG_DEF (phi, z))
+                   gimple phi = gsi_stmt (gsi);
+                   for (z = 0; z < gimple_phi_num_args (phi); z++)
+                     if (var == gimple_phi_arg_def (phi, z))
                        {
-                         ok = 1;
+                         ok = true;
                          break;
                        }
                  }
@@ -1089,7 +1432,7 @@ verify_live_on_entry (tree_live_info_p live)
                  continue;
                num++;
                print_generic_expr (stderr, var, TDF_SLIM);
-               fprintf (stderr, " is not marked live-on-entry to entry BB%d ", 
+               fprintf (stderr, " is not marked live-on-entry to entry BB%d ",
                         entry_block);
                fprintf (stderr, "but it is a default def so it should be.\n");
              }