Index: cgraph.c
===================================================================
--- cgraph.c	(revision 202093)
+++ cgraph.c	(working copy)
@@ -2046,6 +2046,8 @@ cgraph_function_body_availability (struc
     avail = AVAIL_NOT_AVAILABLE;
   else if (node->local.local)
     avail = AVAIL_LOCAL;
+  else if (node->symbol.alias && node->symbol.weakref)
+    cgraph_function_or_thunk_node (node, &avail);
   else if (!node->symbol.externally_visible)
     avail = AVAIL_AVAILABLE;
   /* Inline functions are safe to be analyzed even if their symbol can
Index: testsuite/gcc.dg/tree-ssa/attr-alias.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/attr-alias.c	(revision 202092)
+++ testsuite/gcc.dg/tree-ssa/attr-alias.c	(working copy)
@@ -8,7 +8,7 @@ int test()
    return 0;
 }
 static int test2() __attribute__ ((alias("test")));
-static int test3() __attribute__ ((weakref)) __attribute__ ((alias("test2")));
+static int test1() __attribute__ ((weakref)) __attribute__ ((alias("test2")));
 static int test4() __attribute__ ((weakref)) __attribute__ ((alias("test")));
 main()
 {
Index: passes.def
===================================================================
--- passes.def	(revision 202092)
+++ passes.def	(working copy)
@@ -126,7 +126,6 @@ along with GCC; see the file COPYING3.
   /* These passes are run after IPA passes on every function that is being
      output to the assembler file.  */
   INSERT_PASSES_AFTER (all_passes)
-  NEXT_PASS (pass_fixup_cfg);
   NEXT_PASS (pass_lower_eh_dispatch);
   NEXT_PASS (pass_all_optimizations);
   PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations)
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 202092)
+++ ipa-inline.c	(working copy)
@@ -1904,6 +1904,10 @@ ipa_inline (void)
     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
   int i;
   int cold;
+  bool remove_functions = false;
+
+  if (!optimize)
+    return 0;
 
   if (in_lto_p && optimize)
     ipa_update_after_lto_read ();
@@ -1984,6 +1988,7 @@ ipa_inline (void)
 		{
 		  cgraph_resolve_speculation (edge, NULL);
 		  update = true;
+		  remove_functions = true;
 		}
 	    }
 	  if (update)
@@ -2018,6 +2023,7 @@ ipa_inline (void)
 		    }
 
 		  inline_call (node->callers, true, NULL, NULL, true);
+		  remove_functions = true;
 		  if (dump_file)
 		    fprintf (dump_file,
 			     " Inlined into %s which now has %i size\n",
@@ -2048,7 +2054,7 @@ ipa_inline (void)
   /* In WPA we use inline summaries for partitioning process.  */
   if (!flag_wpa)
     inline_free_summary ();
-  return 0;
+  return remove_functions ? TODO_remove_functions : 0;
 }
 
 /* Inline always-inline function calls in NODE.  */
@@ -2292,13 +2298,13 @@ make_pass_early_inline (gcc::context *ct
 /* When to run IPA inlining.  Inlining of always-inline functions
    happens during early inlining.
 
-   Enable inlining unconditoinally at -flto.  We need size estimates to
-   drive partitioning.  */
+   Enable inlining unconditoinally, because callgraph redirection
+   happens here.   */
 
 static bool
 gate_ipa_inline (void)
 {
-  return optimize || flag_lto || flag_wpa;
+  return true;
 }
 
 namespace {
@@ -2315,7 +2321,7 @@ const pass_data pass_data_ipa_inline =
   0, /* properties_provided */
   0, /* properties_destroyed */
   TODO_remove_functions, /* todo_flags_start */
-  ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */
+  ( TODO_dump_symtab ), /* todo_flags_finish */
 };
 
 class pass_ipa_inline : public ipa_opt_pass_d
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c	(revision 202092)
+++ ipa-inline-analysis.c	(working copy)
@@ -3698,6 +3698,11 @@ inline_generate_summary (void)
 {
   struct cgraph_node *node;
 
+  /* When not optimizing, do not bother to analyze.  Inlining is still done
+     because edge redirection needs to happen there.  */
+  if (!optimize && !flag_lto && !flag_wpa)
+    return;
+
   function_insertion_hook_holder =
     cgraph_add_function_insertion_hook (&add_new_function, NULL);
 
Index: symtab.c
===================================================================
--- symtab.c	(revision 202092)
+++ symtab.c	(working copy)
@@ -390,6 +390,9 @@ change_decl_assembler_name (tree decl, t
       if (name == DECL_ASSEMBLER_NAME (decl))
 	return;
 
+      tree alias = (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl))
+		    ? TREE_CHAIN (DECL_ASSEMBLER_NAME (decl))
+		    : NULL);
       if (node)
 	unlink_from_assembler_name_hash (node, true);
       if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
@@ -397,6 +400,11 @@ change_decl_assembler_name (tree decl, t
 	warning (0, "%D renamed after being referenced in assembly", decl);
 
       SET_DECL_ASSEMBLER_NAME (decl, name);
+      if (alias)
+	{
+	  IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
+	  TREE_CHAIN (DECL_ASSEMBLER_NAME (name)) = alias;
+	}
       if (node)
 	insert_to_assembler_name_hash (node, true);
     }
@@ -1065,11 +1073,17 @@ symtab_nonoverwritable_alias (symtab_nod
 {
   tree new_decl;
   symtab_node new_node = NULL;
+
+  /* First try to look up existing alias or base object
+     (if that is already non-overwritable).  */
+  node = symtab_alias_ultimate_target (node, NULL);
+  gcc_assert (!node->symbol.alias && !node->symbol.weakref);
   symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1,
 		               (void *)&new_node, true);
   if (new_node)
     return new_node;
 
+  /* Otherwise create a new one.  */
   new_decl = copy_node (node->symbol.decl);
   DECL_NAME (new_decl) = clone_function_name (node->symbol.decl, "localalias");
   if (TREE_CODE (new_decl) == FUNCTION_DECL)
Index: varpool.c
===================================================================
--- varpool.c	(revision 202092)
+++ varpool.c	(working copy)
@@ -260,10 +260,22 @@ cgraph_variable_initializer_availability
     return AVAIL_NOT_AVAILABLE;
   if (!TREE_PUBLIC (node->symbol.decl))
     return AVAIL_AVAILABLE;
+  if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
+      || DECL_VIRTUAL_P (node->symbol.decl))
+    return AVAIL_AVAILABLE;
+  if (node->symbol.alias && node->symbol.weakref)
+    {
+      enum availability avail;
+
+      cgraph_variable_initializer_availability
+	      (varpool_variable_node (node, &avail));
+      return avail;
+    }
   /* If the variable can be overwritten, return OVERWRITABLE.  Takes
      care of at least one notable extension - the COMDAT variables
      used to share template instantiations in C++.  */
-  if (!decl_replaceable_p (node->symbol.decl))
+  if (decl_replaceable_p (node->symbol.decl)
+      || DECL_EXTERNAL (node->symbol.decl))
     return AVAIL_OVERWRITABLE;
   return AVAIL_AVAILABLE;
 }
