libitm.exp: Reorder lib loads into dependency order.
[gcc.git] / gcc / cgraphunit.c
index c21ddb84c2f00d244c3d32a70b8d5836ab923db7..731a0e91294c9d5fd0eadb57049d26b34039ca5c 100644 (file)
@@ -1,6 +1,5 @@
 /* Driver of optimization process
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 2003-2013 Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
 This file is part of GCC.
@@ -34,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
       (There is one exception needed for implementing GCC extern inline
        function.)
 
-    - varpool_finalize_variable
+    - varpool_finalize_decl
 
       This function has same behavior as the above but is used for static
       variables.
@@ -51,7 +50,7 @@ along with GCC; see the file COPYING3.  If not see
       The symbol table is constructed starting from the trivially needed
       symbols finalized by the frontend.  Functions are lowered into
       GIMPLE representation and callgraph/reference lists are constructed.
-      Those are used to discover other neccesary functions and variables.
+      Those are used to discover other necessary functions and variables.
 
       At the end the bodies of unreachable functions are removed.
 
@@ -176,7 +175,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "cgraph.h"
 #include "diagnostic.h"
-#include "timevar.h"
 #include "params.h"
 #include "fibheap.h"
 #include "intl.h"
@@ -194,6 +192,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-utils.h"
 #include "lto-streamer.h"
 #include "except.h"
+#include "cfgloop.h"
 #include "regset.h"     /* FIXME: For reg_obstack.  */
 
 /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
@@ -204,7 +203,8 @@ cgraph_node_set cgraph_new_nodes;
 static void expand_all_functions (void);
 static void mark_functions_to_output (void);
 static void expand_function (struct cgraph_node *);
-static void cgraph_analyze_function (struct cgraph_node *);
+static void analyze_function (struct cgraph_node *);
+static void handle_alias_pairs (void);
 
 FILE *cgraph_dump_file;
 
@@ -217,37 +217,45 @@ static GTY(()) struct asm_node *asm_last_node;
 /* Used for vtable lookup in thunk adjusting.  */
 static GTY (()) tree vtable_entry_type;
 
-/* Determine if function DECL is trivially needed and should stay in the
-   compilation unit.  This is used at the symbol table construction time
-   and differs from later logic removing unnecesary functions that can
-   take into account results of analysis, whole program info etc.  */
-
-static bool
-cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
+/* Determine if symbol DECL is needed.  That is, visible to something
+   either outside this translation unit, something magic in the system
+   configury */
+bool
+decide_is_symbol_needed (symtab_node node)
 {
-  /* If the user told us it is used, then it must be so.  */
-  if (node->symbol.force_output)
-    return true;
+  tree decl = node->symbol.decl;
 
   /* Double check that no one output the function into assembly file
      early.  */
   gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
-                      || (node->thunk.thunk_p || node->same_body_alias)
-                      ||  !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
+                      || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
 
+  if (!node->symbol.definition)
+    return false;
 
-  /* Keep constructors, destructors and virtual functions.  */
-  if (DECL_STATIC_CONSTRUCTOR (decl)
-      || DECL_STATIC_DESTRUCTOR (decl)
-      || (DECL_VIRTUAL_P (decl)
-         && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
-     return true;
+  /* Devirtualization may access these.  */
+  if (DECL_VIRTUAL_P (decl) && optimize)
+    return true;
 
-  /* Externally visible functions must be output.  The exception is
-     COMDAT functions that must be output only when they are needed.  */
+  if (DECL_EXTERNAL (decl))
+    return false;
 
-  if (TREE_PUBLIC (decl)
-      && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+  /* If the user told us it is used, then it must be so.  */
+  if (node->symbol.force_output)
+    return true;
+
+  /* ABI forced symbols are needed when they are external.  */
+  if (node->symbol.forced_by_abi && TREE_PUBLIC (decl))
+    return true;
+
+ /* Keep constructors, destructors and virtual functions.  */
+   if (TREE_CODE (decl) == FUNCTION_DECL
+       && (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl)))
+    return true;
+
+  /* Externally visible variables must be output.  The exception is
+     COMDAT variables that must be output only when they are needed.  */
+  if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
     return true;
 
   return false;
@@ -284,6 +292,7 @@ cgraph_process_new_functions (void)
 
   if (!cgraph_new_nodes)
     return false;
+  handle_alias_pairs ();
   /*  Note that this queue may grow as its being processed, as the new
       functions may generate new ones.  */
   for (csi = csi_start (cgraph_new_nodes); !csi_end_p (csi); csi_next (&csi))
@@ -309,10 +318,9 @@ cgraph_process_new_functions (void)
             cgraph but not on this function.  */
 
          gimple_register_cfg_hooks ();
-         if (!node->analyzed)
-           cgraph_analyze_function (node);
+         if (!node->symbol.analyzed)
+           analyze_function (node);
          push_cfun (DECL_STRUCT_FUNCTION (fndecl));
-         current_function_decl = fndecl;
          if ((cgraph_state == CGRAPH_STATE_IPA_SSA
              && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
              /* When not optimizing, be sure we run early local passes anyway
@@ -324,7 +332,6 @@ cgraph_process_new_functions (void)
          free_dominance_info (CDI_POST_DOMINATORS);
          free_dominance_info (CDI_DOMINATORS);
          pop_cfun ();
-         current_function_decl = NULL;
           cgraph_call_function_insertion_hooks (node);
          break;
 
@@ -356,7 +363,7 @@ cgraph_process_new_functions (void)
    ??? It may make more sense to use one body for inlining and other
    body for expanding the function but this is difficult to do.  */
 
-static void
+void
 cgraph_reset_node (struct cgraph_node *node)
 {
   /* If node->process is set, then we have already begun whole-unit analysis.
@@ -370,10 +377,14 @@ cgraph_reset_node (struct cgraph_node *node)
   memset (&node->local, 0, sizeof (node->local));
   memset (&node->global, 0, sizeof (node->global));
   memset (&node->rtl, 0, sizeof (node->rtl));
-  node->analyzed = false;
-  node->local.finalized = false;
+  node->symbol.analyzed = false;
+  node->symbol.definition = false;
+  node->symbol.alias = false;
+  node->symbol.weakref = false;
+  node->symbol.cpp_implicit_alias = false;
 
   cgraph_node_remove_callees (node);
+  ipa_remove_all_references (&node->symbol.ref_list);
 }
 
 /* Return true when there are references to NODE.  */
@@ -383,11 +394,12 @@ referred_to_p (symtab_node node)
 {
   struct ipa_ref *ref;
 
-  /* See if there are any refrences at all.  */
+  /* See if there are any references at all.  */
   if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
     return true;
   /* For functions check also calls.  */
-  if (symtab_function_p (node) && cgraph (node)->callers)
+  cgraph_node *cn = dyn_cast <cgraph_node> (node);
+  if (cn && cn->callers)
     return true;
   return false;
 }
@@ -402,14 +414,14 @@ cgraph_finalize_function (tree decl, bool nested)
 {
   struct cgraph_node *node = cgraph_get_create_node (decl);
 
-  if (node->local.finalized)
+  if (node->symbol.definition)
     {
       cgraph_reset_node (node);
       node->local.redefined_extern_inline = true;
     }
 
   notice_global_symbol (decl);
-  node->local.finalized = true;
+  node->symbol.definition = true;
   node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
 
   /* With -fkeep-inline-functions we are keeping all inline functions except
@@ -426,7 +438,7 @@ cgraph_finalize_function (tree decl, bool nested)
      in the original implementation and it is unclear whether we want
      to change the behavior here.  */
   if ((!optimize
-       && !node->same_body_alias
+       && !node->symbol.cpp_implicit_alias
        && !DECL_DISREGARD_INLINE_LIMITS (decl)
        && !DECL_DECLARED_INLINE_P (decl)
        && !(DECL_CONTEXT (decl)
@@ -446,7 +458,7 @@ cgraph_finalize_function (tree decl, bool nested)
     ggc_collect ();
 
   if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
-      && (cgraph_decide_is_function_needed (node, decl)
+      && (decide_is_symbol_needed ((symtab_node) node)
          || referred_to_p ((symtab_node)node)))
     enqueue_node ((symtab_node)node);
 }
@@ -489,19 +501,17 @@ cgraph_add_new_function (tree fndecl, bool lowered)
           analyzing and compilation.  */
        node = cgraph_get_create_node (fndecl);
        node->local.local = false;
-       node->local.finalized = true;
+       node->symbol.definition = true;
        node->symbol.force_output = true;
        if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
          {
            push_cfun (DECL_STRUCT_FUNCTION (fndecl));
-           current_function_decl = fndecl;
            gimple_register_cfg_hooks ();
            bitmap_obstack_initialize (NULL);
            execute_pass_list (all_lowering_passes);
            execute_pass_list (pass_early_local_passes.pass.sub);
            bitmap_obstack_release (NULL);
            pop_cfun ();
-           current_function_decl = NULL;
 
            lowered = true;
          }
@@ -518,9 +528,9 @@ cgraph_add_new_function (tree fndecl, bool lowered)
        node = cgraph_create_node (fndecl);
        if (lowered)
          node->lowered = true;
-       cgraph_analyze_function (node);
+       node->symbol.definition = true;
+       analyze_function (node);
        push_cfun (DECL_STRUCT_FUNCTION (fndecl));
-       current_function_decl = fndecl;
        gimple_register_cfg_hooks ();
        bitmap_obstack_initialize (NULL);
        if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
@@ -528,7 +538,6 @@ cgraph_add_new_function (tree fndecl, bool lowered)
        bitmap_obstack_release (NULL);
        pop_cfun ();
        expand_function (node);
-       current_function_decl = NULL;
        break;
 
       default:
@@ -576,68 +585,40 @@ output_asm_statements (void)
   asm_nodes = NULL;
 }
 
-/* C++ FE sometimes change linkage flags after producing same body aliases.  */
-void
-fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias)
-{
-  DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (alias);
-  if (TREE_PUBLIC (node->symbol.decl))
-    {
-      DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (alias);
-      DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (alias);
-      DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (alias);
-      if (DECL_ONE_ONLY (alias)
-         && !node->symbol.same_comdat_group)
-       symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target);
-    }
-}
-
 /* Analyze the function scheduled to be output.  */
 static void
-cgraph_analyze_function (struct cgraph_node *node)
+analyze_function (struct cgraph_node *node)
 {
-  tree save = current_function_decl;
   tree decl = node->symbol.decl;
   location_t saved_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (decl);
 
-  if (node->alias && node->thunk.alias)
-    {
-      struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
-      struct cgraph_node *n;
-
-      for (n = tgt; n && n->alias;
-          n = n->analyzed ? cgraph_alias_aliased_node (n) : NULL)
-       if (n == node)
-         {
-           error ("function %q+D part of alias cycle", node->symbol.decl);
-           node->alias = false;
-           input_location = saved_loc;
-           return;
-         }
-      if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
-        ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
-                             IPA_REF_ALIAS, NULL);
-      if (node->same_body_alias)
-       { 
-         DECL_DECLARED_INLINE_P (node->symbol.decl)
-            = DECL_DECLARED_INLINE_P (node->thunk.alias);
-         DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
-            = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
-         fixup_same_cpp_alias_visibility ((symtab_node) node, (symtab_node) tgt, node->thunk.alias);
-       }
-
-      if (node->symbol.address_taken)
-       cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
-    }
+  if (node->symbol.alias)
+    symtab_resolve_alias
+       ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target));
   else if (node->thunk.thunk_p)
     {
       cgraph_create_edge (node, cgraph_get_node (node->thunk.alias),
                          NULL, 0, CGRAPH_FREQ_BASE);
+      node->thunk.alias = NULL;
+    }
+  else if (node->dispatcher_function)
+    {
+      /* Generate the dispatcher body of multi-versioned functions.  */
+      struct cgraph_function_version_info *dispatcher_version_info
+       = get_cgraph_node_version (node);
+      if (dispatcher_version_info != NULL
+          && (dispatcher_version_info->dispatcher_resolver
+             == NULL_TREE))
+       {
+         tree resolver = NULL_TREE;
+         gcc_assert (targetm.generate_version_dispatcher_body);
+         resolver = targetm.generate_version_dispatcher_body (node);
+         gcc_assert (resolver != NULL_TREE);
+       }
     }
   else
     {
-      current_function_decl = decl;
       push_cfun (DECL_STRUCT_FUNCTION (decl));
 
       assign_assembler_name_if_neeeded (node->symbol.decl);
@@ -669,9 +650,8 @@ cgraph_analyze_function (struct cgraph_node *node)
 
       pop_cfun ();
     }
-  node->analyzed = true;
+  node->symbol.analyzed = true;
 
-  current_function_decl = save;
   input_location = saved_loc;
 }
 
@@ -684,16 +664,15 @@ cgraph_analyze_function (struct cgraph_node *node)
 void
 cgraph_process_same_body_aliases (void)
 {
-  struct cgraph_node *node;
-  FOR_EACH_FUNCTION (node)
-    if (node->same_body_alias
-       && !VEC_length (ipa_ref_t, node->symbol.ref_list.references))
-      {
-        struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
-        ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
-                             IPA_REF_ALIAS, NULL);
-      }
-  same_body_aliases_done = true;
+  symtab_node node;
+  FOR_EACH_SYMBOL (node)
+    if (node->symbol.cpp_implicit_alias && !node->symbol.analyzed)
+      symtab_resolve_alias
+        (node,
+        TREE_CODE (node->symbol.alias_target) == VAR_DECL
+        ? (symtab_node)varpool_node_for_decl (node->symbol.alias_target)
+        : (symtab_node)cgraph_get_create_node (node->symbol.alias_target));
+  cpp_implicit_aliases_done = true;
 }
 
 /* Process attributes common for vars and functions.  */
@@ -759,7 +738,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
                        " attribute have effect only on public objects");
        }
       if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
-         && (node->local.finalized && !node->alias))
+         && (node->symbol.definition && !node->symbol.alias))
        {
          warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
                      "%<weakref%> attribute ignored"
@@ -782,6 +761,9 @@ process_function_and_variable_attributes (struct cgraph_node *first,
        vnode = varpool_next_variable (vnode))
     {
       tree decl = vnode->symbol.decl;
+      if (DECL_EXTERNAL (decl)
+         && DECL_INITIAL (decl))
+       varpool_finalize_decl (decl);
       if (DECL_PRESERVE_P (decl))
        vnode->symbol.force_output = true;
       else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
@@ -792,7 +774,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
                        " attribute have effect only on public objects");
        }
       if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
-         && vnode->finalized
+         && vnode->symbol.definition
          && DECL_INITIAL (decl))
        {
          warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
@@ -813,14 +795,14 @@ process_function_and_variable_attributes (struct cgraph_node *first,
 void
 varpool_finalize_decl (tree decl)
 {
-  struct varpool_node *node = varpool_node (decl);
+  struct varpool_node *node = varpool_node_for_decl (decl);
 
-  gcc_assert (TREE_STATIC (decl));
+  gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
 
-  if (node->finalized)
+  if (node->symbol.definition)
     return;
   notice_global_symbol (decl);
-  node->finalized = true;
+  node->symbol.definition = true;
   if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
       /* Traditionally we do not eliminate static variables when not
         optimizing and when not doing toplevel reoder.  */
@@ -829,7 +811,7 @@ varpool_finalize_decl (tree decl)
     node->symbol.force_output = true;
 
   if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
-      && (decide_is_variable_needed (node, decl)
+      && (decide_is_symbol_needed ((symtab_node) node)
          || referred_to_p ((symtab_node)node)))
     enqueue_node ((symtab_node)node);
   if (cgraph_state >= CGRAPH_STATE_IPA_SSA)
@@ -840,11 +822,12 @@ varpool_finalize_decl (tree decl)
     varpool_assemble_decl (node);
 }
 
+
 /* Discover all functions and variables that are trivially needed, analyze
    them as well as all functions and variables referred by them  */
 
 static void
-cgraph_analyze_functions (void)
+analyze_functions (void)
 {
   /* Keep track of already processed nodes when called multiple times for
      intermodule optimization.  */
@@ -861,6 +844,13 @@ cgraph_analyze_functions (void)
   bitmap_obstack_initialize (NULL);
   cgraph_state = CGRAPH_STATE_CONSTRUCTION;
 
+  /* Ugly, but the fixup can not happen at a time same body alias is created;
+     C++ FE is confused about the COMDAT groups being right.  */
+  if (cpp_implicit_aliases_done)
+    FOR_EACH_SYMBOL (node)
+      if (node->symbol.cpp_implicit_alias)
+         fixup_same_cpp_alias_visibility (node, symtab_alias_target (node));
+
   /* Analysis adds static variables that in turn adds references to new functions.
      So we need to iterate the process until it stabilize.  */
   while (changed)
@@ -874,13 +864,7 @@ cgraph_analyze_functions (void)
           node != (symtab_node)first_analyzed
           && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
        {
-         if ((symtab_function_p (node)
-              && cgraph (node)->local.finalized
-              && cgraph_decide_is_function_needed (cgraph (node), node->symbol.decl))
-             || (symtab_variable_p (node)
-                 && varpool (node)->finalized
-                 && !DECL_EXTERNAL (node->symbol.decl)
-                 && decide_is_variable_needed (varpool (node), node->symbol.decl)))
+         if (decide_is_symbol_needed (node))
            {
              enqueue_node (node);
              if (!changed && cgraph_dump_file)
@@ -907,49 +891,49 @@ cgraph_analyze_functions (void)
          changed = true;
          node = first;
          first = (symtab_node)first->symbol.aux;
-         if (symtab_function_p (node) && cgraph (node)->local.finalized)
+         cgraph_node *cnode = dyn_cast <cgraph_node> (node);
+         if (cnode && cnode->symbol.definition)
            {
              struct cgraph_edge *edge;
-             struct cgraph_node *cnode;
-             tree decl;
-
-             cnode = cgraph (node);
-             decl = cnode->symbol.decl;
+             tree decl = cnode->symbol.decl;
 
-             /* ??? It is possible to create extern inline function and later using
-                weak alias attribute to kill its body. See
-                gcc.c-torture/compile/20011119-1.c  */
+             /* ??? It is possible to create extern inline function
+             and later using weak alias attribute to kill its body.
+             See gcc.c-torture/compile/20011119-1.c  */
              if (!DECL_STRUCT_FUNCTION (decl)
-                 && (!cnode->alias || !cnode->thunk.alias)
-                 && !cnode->thunk.thunk_p)
+                 && !cnode->symbol.alias
+                 && !cnode->thunk.thunk_p
+                 && !cnode->dispatcher_function)
                {
                  cgraph_reset_node (cnode);
                  cnode->local.redefined_extern_inline = true;
                  continue;
                }
 
-             if (!cnode->analyzed)
-               cgraph_analyze_function (cnode);
+             if (!cnode->symbol.analyzed)
+               analyze_function (cnode);
 
              for (edge = cnode->callees; edge; edge = edge->next_callee)
-               if (edge->callee->local.finalized)
-                 enqueue_node ((symtab_node)edge->callee);
+               if (edge->callee->symbol.definition)
+                  enqueue_node ((symtab_node)edge->callee);
 
-             /* If decl is a clone of an abstract function, mark that abstract
-                function so that we don't release its body. The DECL_INITIAL() of that
-                abstract function declaration will be later needed to output debug
-                info.  */
+             /* If decl is a clone of an abstract function,
+             mark that abstract function so that we don't release its body.
+             The DECL_INITIAL() of that abstract function declaration
+             will be later needed to output debug info.  */
              if (DECL_ABSTRACT_ORIGIN (decl))
                {
-                 struct cgraph_node *origin_node;
-                 origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
+                 struct cgraph_node *origin_node
+                 = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
                  origin_node->abstract_and_needed = true;
                }
-
            }
-         else if (symtab_variable_p (node)
-                  && varpool (node)->finalized)
-           varpool_analyze_node (varpool (node));
+         else
+           {
+             varpool_node *vnode = dyn_cast <varpool_node> (node);
+             if (vnode && vnode->symbol.definition && !vnode->symbol.analyzed)
+               varpool_analyze_node (vnode);
+           }
 
          if (node->symbol.same_comdat_group)
            {
@@ -960,8 +944,7 @@ cgraph_analyze_functions (void)
                enqueue_node (next);
            }
          for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
-           if ((symtab_function_p (ref->referred) && cgraph (ref->referred)->local.finalized)
-               || (symtab_variable_p (ref->referred) && varpool (ref->referred)->finalized))
+           if (ref->referred->symbol.definition)
              enqueue_node (ref->referred);
           cgraph_process_new_functions ();
        }
@@ -989,20 +972,19 @@ cgraph_analyze_functions (void)
          symtab_remove_node (node);
          continue;
        }
-      if (symtab_function_p (node))
+      if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
        {
          tree decl = node->symbol.decl;
-         struct cgraph_node *cnode = cgraph (node);
 
-         if (cnode->local.finalized && !gimple_has_body_p (decl)
-             && (!cnode->alias || !cnode->thunk.alias)
+         if (cnode->symbol.definition && !gimple_has_body_p (decl)
+             && !cnode->symbol.alias
              && !cnode->thunk.thunk_p)
            cgraph_reset_node (cnode);
 
-         gcc_assert (!cnode->local.finalized || cnode->thunk.thunk_p
-                     || cnode->alias
+         gcc_assert (!cnode->symbol.definition || cnode->thunk.thunk_p
+                     || cnode->symbol.alias
                      || gimple_has_body_p (decl));
-         gcc_assert (cnode->analyzed == cnode->local.finalized);
+         gcc_assert (cnode->symbol.analyzed == cnode->symbol.definition);
        }
       node->symbol.aux = NULL;
     }
@@ -1026,70 +1008,70 @@ handle_alias_pairs (void)
 {
   alias_pair *p;
   unsigned i;
-  struct cgraph_node *target_node;
-  struct cgraph_node *src_node;
-  struct varpool_node *target_vnode;
   
-  for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
+  for (i = 0; alias_pairs && alias_pairs->iterate (i, &p);)
     {
+      symtab_node target_node = symtab_node_for_asm (p->target);
+
+      /* Weakrefs with target not defined in current unit are easy to handle; they
+        behave just as external variables except we need to note the alias flag
+        to later output the weakref pseudo op into asm file.  */
+      if (!target_node && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL)
+       {
+         symtab_node node = symtab_get_node (p->decl);
+         if (node)
+           {
+             node->symbol.alias_target = p->target;
+             node->symbol.weakref = true;
+             node->symbol.alias = true;
+           }
+         alias_pairs->unordered_remove (i);
+         continue;
+       }
+      else if (!target_node)
+       {
+         error ("%q+D aliased to undefined symbol %qE", p->decl, p->target);
+         alias_pairs->unordered_remove (i);
+         continue;
+       }
+
+      if (DECL_EXTERNAL (target_node->symbol.decl)
+         /* We use local aliases for C++ thunks to force the tailcall
+            to bind locally.  This is a hack - to keep it working do
+            the following (which is not strictly correct).  */
+         && (! TREE_CODE (target_node->symbol.decl) == FUNCTION_DECL
+             || ! DECL_VIRTUAL_P (target_node->symbol.decl))
+         && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
+       {
+         error ("%q+D aliased to external symbol %qE",
+                p->decl, p->target);
+       }
+
       if (TREE_CODE (p->decl) == FUNCTION_DECL
-         && (target_node = cgraph_node_for_asm (p->target)) != NULL)
+          && target_node && is_a <cgraph_node> (target_node))
        {
-         src_node = cgraph_get_node (p->decl);
-         if (src_node && src_node->local.finalized)
+         struct cgraph_node *src_node = cgraph_get_node (p->decl);
+         if (src_node && src_node->symbol.definition)
             cgraph_reset_node (src_node);
-         /* Normally EXTERNAL flag is used to mark external inlines,
-            however for aliases it seems to be allowed to use it w/o
-            any meaning. See gcc.dg/attr-alias-3.c  
-            However for weakref we insist on EXTERNAL flag being set.
-            See gcc.dg/attr-alias-5.c  */
-         if (DECL_EXTERNAL (p->decl))
-           DECL_EXTERNAL (p->decl)
-             = lookup_attribute ("weakref",
-                                 DECL_ATTRIBUTES (p->decl)) != NULL;
          cgraph_create_function_alias (p->decl, target_node->symbol.decl);
-         VEC_unordered_remove (alias_pair, alias_pairs, i);
+         alias_pairs->unordered_remove (i);
        }
       else if (TREE_CODE (p->decl) == VAR_DECL
-              && (target_vnode = varpool_node_for_asm (p->target)) != NULL)
+              && target_node && is_a <varpool_node> (target_node))
        {
-         /* Normally EXTERNAL flag is used to mark external inlines,
-            however for aliases it seems to be allowed to use it w/o
-            any meaning. See gcc.dg/attr-alias-3.c  
-            However for weakref we insist on EXTERNAL flag being set.
-            See gcc.dg/attr-alias-5.c  */
-         if (DECL_EXTERNAL (p->decl))
-           DECL_EXTERNAL (p->decl)
-             = lookup_attribute ("weakref",
-                                 DECL_ATTRIBUTES (p->decl)) != NULL;
-         varpool_create_variable_alias (p->decl, target_vnode->symbol.decl);
-         VEC_unordered_remove (alias_pair, alias_pairs, i);
-       }
-      /* Weakrefs with target not defined in current unit are easy to handle; they
-        behave just as external variables except we need to note the alias flag
-        to later output the weakref pseudo op into asm file.  */
-      else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL
-              && (TREE_CODE (p->decl) == FUNCTION_DECL
-                  ? (varpool_node_for_asm (p->target) == NULL)
-                  : (cgraph_node_for_asm (p->target) == NULL)))
-       {
-         if (TREE_CODE (p->decl) == FUNCTION_DECL)
-           cgraph_get_create_node (p->decl)->alias = true;
-         else
-           varpool_get_node (p->decl)->alias = true;
-         DECL_EXTERNAL (p->decl) = 1;
-         VEC_unordered_remove (alias_pair, alias_pairs, i);
+         varpool_create_variable_alias (p->decl, target_node->symbol.decl);
+         alias_pairs->unordered_remove (i);
        }
       else
        {
-         if (dump_file)
-           fprintf (dump_file, "Unhandled alias %s->%s\n",
-                    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
-                    IDENTIFIER_POINTER (p->target));
-
-         i++;
+         error ("%q+D alias in between function and variable is not supported",
+                p->decl);
+         warning (0, "%q+D aliased declaration",
+                  target_node->symbol.decl);
+         alias_pairs->unordered_remove (i);
        }
     }
+  vec_free (alias_pairs);
 }
 
 
@@ -1117,9 +1099,9 @@ mark_functions_to_output (void)
       /* We need to output all local functions that are used and not
         always inlined, as well as those that are reachable from
         outside the current compilation unit.  */
-      if (node->analyzed
+      if (node->symbol.analyzed
          && !node->thunk.thunk_p
-         && !node->alias
+         && !node->symbol.alias
          && !node->global.inlined_to
          && !TREE_ASM_WRITTEN (decl)
          && !DECL_EXTERNAL (decl))
@@ -1131,7 +1113,7 @@ mark_functions_to_output (void)
              for (next = cgraph (node->symbol.same_comdat_group);
                   next != node;
                   next = cgraph (next->symbol.same_comdat_group))
-               if (!next->thunk.thunk_p && !next->alias)
+               if (!next->thunk.thunk_p && !next->symbol.alias)
                  next->process = 1;
            }
        }
@@ -1151,7 +1133,8 @@ mark_functions_to_output (void)
                 are inside partition, we can end up not removing the body since we no longer
                 have analyzed node pointing to it.  */
              && !node->symbol.in_other_partition
-             && !node->alias
+             && !node->symbol.alias
+             && !node->clones
              && !DECL_EXTERNAL (decl))
            {
              dump_cgraph_node (stderr, node);
@@ -1161,6 +1144,8 @@ mark_functions_to_output (void)
          gcc_assert (node->global.inlined_to
                      || !gimple_has_body_p (decl)
                      || node->symbol.in_other_partition
+                     || node->clones
+                     || DECL_ARTIFICIAL (decl)
                      || DECL_EXTERNAL (decl));
 
        }
@@ -1179,6 +1164,7 @@ mark_functions_to_output (void)
                 end up not removing the body since we no longer have an
                 analyzed node pointing to it.  */
              && !node->symbol.in_other_partition
+             && !node->clones
              && !DECL_EXTERNAL (decl))
            {
              dump_cgraph_node (stderr, node);
@@ -1190,13 +1176,13 @@ mark_functions_to_output (void)
 }
 
 /* DECL is FUNCTION_DECL.  Initialize datastructures so DECL is a function
-   in lowered gimple form.
+   in lowered gimple form.  IN_SSA is true if the gimple is in SSA.
    
    Set current_function_decl and cfun to newly constructed empty function body.
    return basic block in the function body.  */
 
-static basic_block
-init_lowered_empty_function (tree decl)
+basic_block
+init_lowered_empty_function (tree decl, bool in_ssa)
 {
   basic_block bb;
 
@@ -1204,20 +1190,30 @@ init_lowered_empty_function (tree decl)
   allocate_struct_function (decl, false);
   gimple_register_cfg_hooks ();
   init_empty_tree_cfg ();
-  init_tree_ssa (cfun);
-  init_ssa_operands ();
-  cfun->gimple_df->in_ssa_p = true;
+
+  if (in_ssa)
+    {
+      init_tree_ssa (cfun);
+      init_ssa_operands (cfun);
+      cfun->gimple_df->in_ssa_p = true;
+      cfun->curr_properties |= PROP_ssa;
+    }
+
   DECL_INITIAL (decl) = make_node (BLOCK);
 
   DECL_SAVED_TREE (decl) = error_mark_node;
-  cfun->curr_properties |=
-    (PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg | PROP_referenced_vars |
-     PROP_ssa | PROP_gimple_any);
+  cfun->curr_properties |= (PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_any
+                           | PROP_cfg | PROP_loops);
+
+  set_loops_for_fn (cfun, ggc_alloc_cleared_loops ());
+  init_loops_structure (cfun, loops_for_fn (cfun), 1);
+  loops_for_fn (cfun)->state |= LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
 
   /* Create BB for body of the function and connect it properly.  */
   bb = create_basic_block (NULL, (void *) 0, ENTRY_BLOCK_PTR);
-  make_edge (ENTRY_BLOCK_PTR, bb, 0);
+  make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU);
   make_edge (bb, EXIT_BLOCK_PTR, 0);
+  add_bb_to_loop (bb, ENTRY_BLOCK_PTR->loop_father);
 
   return bb;
 }
@@ -1264,7 +1260,7 @@ thunk_adjust (gimple_stmt_iterator * bsi,
        }
 
       vtabletmp =
-       make_rename_temp (build_pointer_type
+       create_tmp_reg (build_pointer_type
                          (build_pointer_type (vtable_entry_type)), "vptr");
 
       /* The vptr is always at offset zero in the object.  */
@@ -1274,7 +1270,7 @@ thunk_adjust (gimple_stmt_iterator * bsi,
       gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
 
       /* Form the vtable address.  */
-      vtabletmp2 = make_rename_temp (TREE_TYPE (TREE_TYPE (vtabletmp)),
+      vtabletmp2 = create_tmp_reg (TREE_TYPE (TREE_TYPE (vtabletmp)),
                                     "vtableaddr");
       stmt = gimple_build_assign (vtabletmp2,
                                  build_simple_mem_ref (vtabletmp));
@@ -1288,7 +1284,7 @@ thunk_adjust (gimple_stmt_iterator * bsi,
       gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
 
       /* Get the offset itself.  */
-      vtabletmp3 = make_rename_temp (TREE_TYPE (TREE_TYPE (vtabletmp2)),
+      vtabletmp3 = create_tmp_reg (TREE_TYPE (TREE_TYPE (vtabletmp2)),
                                     "vcalloffset");
       stmt = gimple_build_assign (vtabletmp3,
                                  build_simple_mem_ref (vtabletmp2));
@@ -1310,7 +1306,7 @@ thunk_adjust (gimple_stmt_iterator * bsi,
         ptrtmp = ptr;
       else
         {
-          ptrtmp = make_rename_temp (TREE_TYPE (ptr), "ptr");
+          ptrtmp = create_tmp_reg (TREE_TYPE (ptr), "ptr");
           stmt = gimple_build_assign (ptrtmp, ptr);
          gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
        }
@@ -1319,7 +1315,7 @@ thunk_adjust (gimple_stmt_iterator * bsi,
     }
 
   /* Emit the statement and gimplify the adjustment expression.  */
-  ret = make_rename_temp (TREE_TYPE (ptr), "adjusted_this");
+  ret = create_tmp_reg (TREE_TYPE (ptr), "adjusted_this");
   stmt = gimple_build_assign (ret, ptr);
   gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
 
@@ -1335,7 +1331,7 @@ assemble_thunk (struct cgraph_node *node)
   HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
   HOST_WIDE_INT virtual_value = node->thunk.virtual_value;
   tree virtual_offset = NULL;
-  tree alias = node->thunk.alias;
+  tree alias = node->callees->callee->symbol.decl;
   tree thunk_fndecl = node->symbol.decl;
   tree a = DECL_ARGUMENTS (thunk_fndecl);
 
@@ -1364,18 +1360,22 @@ assemble_thunk (struct cgraph_node *node)
       DECL_INITIAL (thunk_fndecl) = fn_block;
       init_function_start (thunk_fndecl);
       cfun->is_thunk = 1;
+      insn_locations_init ();
+      set_curr_insn_location (DECL_SOURCE_LOCATION (thunk_fndecl));
+      prologue_location = curr_insn_location ();
       assemble_start_function (thunk_fndecl, fnname);
 
       targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
                                       fixed_offset, virtual_value, alias);
 
       assemble_end_function (thunk_fndecl, fnname);
+      insn_locations_finalize ();
       init_insn_lengths ();
       free_after_compilation (cfun);
       set_cfun (NULL);
       TREE_ASM_WRITTEN (thunk_fndecl) = 1;
       node->thunk.thunk_p = false;
-      node->analyzed = false;
+      node->symbol.analyzed = false;
     }
   else
     {
@@ -1387,7 +1387,7 @@ assemble_thunk (struct cgraph_node *node)
       int i;
       tree resdecl;
       tree restmp = NULL;
-      VEC(tree, heap) *vargs;
+      vec<tree> vargs;
 
       gimple call;
       gimple ret;
@@ -1410,7 +1410,7 @@ assemble_thunk (struct cgraph_node *node)
       else
        resdecl = DECL_RESULT (thunk_fndecl);
 
-      bb = then_bb = else_bb = return_bb = init_lowered_empty_function (thunk_fndecl);
+      bb = then_bb = else_bb = return_bb = init_lowered_empty_function (thunk_fndecl, true);
 
       bsi = gsi_start_bb (bb);
 
@@ -1424,31 +1424,21 @@ assemble_thunk (struct cgraph_node *node)
              BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp;
            }
          else
-            restmp = make_rename_temp (restype, "retval");
+           restmp = create_tmp_reg (restype, "retval");
        }
 
       for (arg = a; arg; arg = DECL_CHAIN (arg))
         nargs++;
-      vargs = VEC_alloc (tree, heap, nargs);
+      vargs.create (nargs);
       if (this_adjusting)
-        VEC_quick_push (tree, vargs,
-                       thunk_adjust (&bsi,
-                                     a, 1, fixed_offset,
-                                     virtual_offset));
+        vargs.quick_push (thunk_adjust (&bsi, a, 1, fixed_offset,
+                                       virtual_offset));
       else
-        VEC_quick_push (tree, vargs, a);
-      add_referenced_var (a);
-      if (is_gimple_reg (a))
-       mark_sym_for_renaming (a);
+        vargs.quick_push (a);
       for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
-       {
-         add_referenced_var (arg);
-         if (is_gimple_reg (arg))
-           mark_sym_for_renaming (arg);
-         VEC_quick_push (tree, vargs, arg);
-       }
+       vargs.quick_push (arg);
       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs);
-      VEC_free (tree, heap, vargs);
+      vargs.release ();
       gimple_call_set_from_thunk (call, true);
       if (restmp)
         gimple_call_set_lhs (call, restmp);
@@ -1468,6 +1458,9 @@ assemble_thunk (struct cgraph_node *node)
              then_bb = create_basic_block (NULL, (void *) 0, bb);
              return_bb = create_basic_block (NULL, (void *) 0, then_bb);
              else_bb = create_basic_block (NULL, (void *) 0, else_bb);
+             add_bb_to_loop (then_bb, bb->loop_father);
+             add_bb_to_loop (return_bb, bb->loop_father);
+             add_bb_to_loop (else_bb, bb->loop_father);
              remove_edge (single_succ_edge (bb));
              true_label = gimple_block_label (then_bb);
              stmt = gimple_build_cond (NE_EXPR, restmp,
@@ -1512,11 +1505,12 @@ assemble_thunk (struct cgraph_node *node)
       bitmap_obstack_release (NULL);
     }
   current_function_decl = NULL;
+  set_cfun (NULL);
 }
 
 
 
-/* Assemble thunks and aliases asociated to NODE.  */
+/* Assemble thunks and aliases associated to NODE.  */
 
 static void
 assemble_thunks_and_aliases (struct cgraph_node *node)
@@ -1541,15 +1535,15 @@ assemble_thunks_and_aliases (struct cgraph_node *node)
     if (ref->use == IPA_REF_ALIAS)
       {
        struct cgraph_node *alias = ipa_ref_referring_node (ref);
-        bool saved_written = TREE_ASM_WRITTEN (alias->thunk.alias);
+        bool saved_written = TREE_ASM_WRITTEN (node->symbol.decl);
 
        /* Force assemble_alias to really output the alias this time instead
           of buffering it in same alias pairs.  */
-       TREE_ASM_WRITTEN (alias->thunk.alias) = 1;
-       assemble_alias (alias->symbol.decl,
-                       DECL_ASSEMBLER_NAME (alias->thunk.alias));
+       TREE_ASM_WRITTEN (node->symbol.decl) = 1;
+       do_assemble_alias (alias->symbol.decl,
+                          DECL_ASSEMBLER_NAME (node->symbol.decl));
        assemble_thunks_and_aliases (alias);
-       TREE_ASM_WRITTEN (alias->thunk.alias) = saved_written;
+       TREE_ASM_WRITTEN (node->symbol.decl) = saved_written;
       }
 }
 
@@ -1604,8 +1598,6 @@ expand_function (struct cgraph_node *node)
   /* Release the default bitmap obstack.  */
   bitmap_obstack_release (NULL);
 
-  set_cfun (NULL);
-
   /* If requested, warn about function definitions where the function will
      return a value (usually of some struct or union type) which itself will
      take up a lot of stack space.  */
@@ -1650,6 +1642,7 @@ expand_function (struct cgraph_node *node)
 
   /* Make sure that BE didn't give up on compiling.  */
   gcc_assert (TREE_ASM_WRITTEN (decl));
+  set_cfun (NULL);
   current_function_decl = NULL;
 
   /* It would make a lot more sense to output thunks before function body to get more
@@ -1750,7 +1743,7 @@ output_in_order (void)
 
   FOR_EACH_DEFINED_FUNCTION (pf)
     {
-      if (pf->process && !pf->thunk.thunk_p && !pf->alias)
+      if (pf->process && !pf->thunk.thunk_p && !pf->symbol.alias)
        {
          i = pf->symbol.order;
          gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
@@ -1760,12 +1753,13 @@ output_in_order (void)
     }
 
   FOR_EACH_DEFINED_VARIABLE (pv)
-    {
-      i = pv->symbol.order;
-      gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
-      nodes[i].kind = ORDER_VAR;
-      nodes[i].u.v = pv;
-    }
+    if (!DECL_EXTERNAL (pv->symbol.decl))
+      {
+       i = pv->symbol.order;
+       gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
+       nodes[i].kind = ORDER_VAR;
+       nodes[i].u.v = pv;
+      }
 
   for (pa = asm_nodes; pa; pa = pa->next)
     {
@@ -1884,27 +1878,37 @@ get_alias_symbol (tree decl)
 
 
 /* Weakrefs may be associated to external decls and thus not output
-   at expansion time.  Emit all neccesary aliases.  */
+   at expansion time.  Emit all necessary aliases.  */
 
 static void
 output_weakrefs (void)
 {
-  struct cgraph_node *node;
-  struct varpool_node *vnode;
-  FOR_EACH_FUNCTION (node)
-    if (node->alias && DECL_EXTERNAL (node->symbol.decl)
+  symtab_node node;
+  FOR_EACH_SYMBOL (node)
+    if (node->symbol.alias
         && !TREE_ASM_WRITTEN (node->symbol.decl)
-       && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
-      assemble_alias (node->symbol.decl,
-                     node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
-                     : get_alias_symbol (node->symbol.decl));
-  FOR_EACH_VARIABLE (vnode)
-    if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl)
-        && !TREE_ASM_WRITTEN (vnode->symbol.decl)
-       && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
-      assemble_alias (vnode->symbol.decl,
-                     vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
-                     : get_alias_symbol (vnode->symbol.decl));
+       && node->symbol.weakref)
+      {
+       tree target;
+
+       /* Weakrefs are special by not requiring target definition in current
+          compilation unit.  It is thus bit hard to work out what we want to
+          alias.
+          When alias target is defined, we need to fetch it from symtab reference,
+          otherwise it is pointed to by alias_target.  */
+       if (node->symbol.alias_target)
+         target = (DECL_P (node->symbol.alias_target)
+                   ? DECL_ASSEMBLER_NAME (node->symbol.alias_target)
+                   : node->symbol.alias_target);
+       else if (node->symbol.analyzed)
+         target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl);
+       else
+         {
+           gcc_unreachable ();
+           target = get_alias_symbol (node->symbol.decl);
+         }
+        do_assemble_alias (node->symbol.decl, target);
+      }
 }
 
 /* Initialize callgraph dump file.  */
@@ -1988,7 +1992,32 @@ compile (void)
 #endif
   bitmap_obstack_release (NULL);
   mark_functions_to_output ();
-  output_weakrefs ();
+
+  /* When weakref support is missing, we autmatically translate all
+     references to NODE to references to its ultimate alias target.
+     The renaming mechanizm uses flag IDENTIFIER_TRANSPARENT_ALIAS and
+     TREE_CHAIN.
+
+     Set up this mapping before we output any assembler but once we are sure
+     that all symbol renaming is done.
+
+     FIXME: All this uglyness can go away if we just do renaming at gimple
+     level by physically rewritting the IL.  At the moment we can only redirect
+     calls, so we need infrastructure for renaming references as well.  */
+#ifndef ASM_OUTPUT_WEAKREF
+  symtab_node node;
+
+  FOR_EACH_SYMBOL (node)
+    if (node->symbol.alias
+       && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
+      {
+       IDENTIFIER_TRANSPARENT_ALIAS
+          (DECL_ASSEMBLER_NAME (node->symbol.decl)) = 1;
+       TREE_CHAIN (DECL_ASSEMBLER_NAME (node->symbol.decl))
+          = (node->symbol.alias_target ? node->symbol.alias_target
+             : DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl));
+      }
+#endif
 
   cgraph_state = CGRAPH_STATE_EXPANSION;
   if (!flag_toplevel_reorder)
@@ -2003,6 +2032,7 @@ compile (void)
 
   cgraph_process_new_functions ();
   cgraph_state = CGRAPH_STATE_FINISHED;
+  output_weakrefs ();
 
   if (cgraph_dump_file)
     {
@@ -2051,7 +2081,6 @@ finalize_compilation_unit (void)
   finalize_size_functions ();
 
   /* Mark alias targets necessary and emit diagnostics.  */
-  finish_aliases_1 ();
   handle_alias_pairs ();
 
   if (!quiet_flag)
@@ -2065,14 +2094,13 @@ finalize_compilation_unit (void)
 
   /* Gimplify and lower all functions, compute reachability and
      remove unreachable nodes.  */
-  cgraph_analyze_functions ();
+  analyze_functions ();
 
   /* Mark alias targets necessary and emit diagnostics.  */
-  finish_aliases_1 ();
   handle_alias_pairs ();
 
   /* Gimplify and lower thunks.  */
-  cgraph_analyze_functions ();
+  analyze_functions ();
 
   /* Finally drive the pass manager.  */
   compile ();