diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 760713f288fe19b67c9b9d4a089205e2cd16c8c8..eda5b975669b586492e302c8c1e2e10a89cffb82 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2011-09-27  Andi Kleen  <ak@linux.intel.com>
+	    Jan Hubicka  <jh@suse.cz>
+
+	* doc/invoke.texi (ffat-lto-objects): Document.
+	* toplev.c (compile_file): Do not output assembly when doing slim lto;
+	Output __gnu_slim_lto when doing slim lto.
+	* cgraphunit.c (ipa_passes): Do only analysis when producing slim lto.
+	(cgraph_optimize): Return early when doing slim lto.
+	* opts.c (finish_options): Complain about lack of linker plugin
+	when doing slim lto.
+	* common.opt (ffat-lto-objects): New.
+
 2011-09-27  Richard Sandiford  <richard.sandiford@linaro.org>
 
 	* ipa-inline-analysis.c (predicate_probability): Avoid comparison
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 2dedcc5c31a27b7dc53383472ac039f8ecc39e83..999b238233377c5308904050dc716e951c08fa09 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2042,7 +2042,7 @@ ipa_passes (void)
   if (flag_generate_lto)
     targetm.asm_out.lto_end ();
 
-  if (!flag_ltrans)
+  if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
     execute_ipa_pass_list (all_regular_ipa_passes);
   invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
@@ -2080,8 +2080,9 @@ cgraph_optimize (void)
   if (!seen_error ())
     ipa_passes ();
 
-  /* Do nothing else if any IPA pass found errors.  */
-  if (seen_error ())
+  /* Do nothing else if any IPA pass found errors or if we are just streaming LTO.  */
+  if (seen_error ()
+      || (!in_lto_p && flag_lto && !flag_fat_lto_objects))
     {
       timevar_pop (TV_CGRAPHOPT);
       return;
diff --git a/gcc/common.opt b/gcc/common.opt
index ba3e254dd1432febf773be72df9bf2e74c4296fb..f237f76956ec4d8de125dbafb19162cca5b1b210 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1087,6 +1087,10 @@ Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
 ffast-math
 Common
 
+ffat-lto-objects
+Common Var(flag_fat_lto_objects) Init(1)
+Output lto objects containing both the intermediate language and binary output.
+
 ffinite-math-only
 Common Report Var(flag_finite_math_only) Optimization SetByCombined
 Assume no NaNs or infinities are generated
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1f04612c7aa9536b626dd83d791b370f72fa51a4..9df741439f40412094d9f33086b0db3351efef85 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -355,8 +355,8 @@ Objective-C and Objective-C++ Dialects}.
 -fcx-limited-range @gol
 -fdata-sections -fdce -fdce -fdelayed-branch @gol
 -fdelete-null-pointer-checks -fdse -fdevirtualize -fdse @gol
--fearly-inlining -fipa-sra -fexpensive-optimizations -ffast-math @gol
--ffinite-math-only -ffloat-store -fexcess-precision=@var{style} @gol
+-fearly-inlining -fipa-sra -fexpensive-optimizations -ffat-lto-objects @gol
+-ffast-math -ffinite-math-only -ffloat-store -fexcess-precision=@var{style} @gol
 -fforward-propagate -ffp-contract=@var{style} -ffunction-sections @gol
 -fgcse -fgcse-after-reload -fgcse-las -fgcse-lm -fgraphite-identity @gol
 -fgcse-sm -fif-conversion -fif-conversion2 -findirect-inlining @gol
@@ -7891,6 +7891,22 @@ use it.
 Enabled by default when LTO support in GCC is enabled and GCC was compiled
 with a linker supporting plugins (GNU ld 2.21 or newer or gold).
 
+@item -ffat-lto-objects
+@opindex ffat-lto-objects
+Fat LTO objects are object files that contain both the intermediate language
+and the object code. This makes them useable for both LTO linking and normal
+linking. This option makes effect only with @option{-flto} and is ignored 
+at linktime.
+
+@option{-fno-fat-lto-objects} improves compilation time over plain LTO, but
+requires the complete toolchain to be aware of LTO. It requires a linker with
+linker plugin support for basic functionality.  Additionally, nm, ar and ranlib
+need to support linker plugins to allow a full-featured build environment
+(capable of building static libraries etc).
+
+The default is @option{-ffat-lto-objects} but this default is intended to
+change in future releases when linker plugin enabled environments become more
+common.
 @item -fcompare-elim
 @opindex fcompare-elim
 After register allocation and post-register allocation instruction splitting,
diff --git a/gcc/opts.c b/gcc/opts.c
index 5d5bcb9602853b6e5f573d34e60f6ae43081161f..acf77895c8a1656a21e4c3f9ac13bcc43b866fbb 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -779,7 +779,9 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 #else
       error_at (loc, "LTO support has not been enabled in this configuration");
 #endif
-    }
+      if (!opts->x_flag_fat_lto_objects && !HAVE_LTO_PLUGIN)
+        error_at (loc, "-fno-fat-lto-objects are supported only with linker plugin.");
+}
   if ((opts->x_flag_lto_partition_balanced != 0) + (opts->x_flag_lto_partition_1to1 != 0)
        + (opts->x_flag_lto_partition_none != 0) >= 1)
     {
diff --git a/gcc/toplev.c b/gcc/toplev.c
index de0a58a67731c2f75d81990fae54b05eece077d1..3688c093a3f273871e9e277d395d103b5e51589f 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -569,40 +569,45 @@ compile_file (void)
       return;
     }
 
-  varpool_assemble_pending_decls ();
-  finish_aliases_2 ();
+  /* Compilation unit is finalized.  When producing non-fat LTO object, we are
+     basically finished.  */
+  if (in_lto_p || !flag_lto || flag_fat_lto_objects)
+    {
+      varpool_assemble_pending_decls ();
+      finish_aliases_2 ();
 
-  /* Likewise for mudflap static object registrations.  */
-  if (flag_mudflap)
-    mudflap_finish_file ();
+      /* Likewise for mudflap static object registrations.  */
+      if (flag_mudflap)
+	mudflap_finish_file ();
 
-  output_shared_constant_pool ();
-  output_object_blocks ();
+      output_shared_constant_pool ();
+      output_object_blocks ();
 
-  /* Write out any pending weak symbol declarations.  */
-  weak_finish ();
+      /* Write out any pending weak symbol declarations.  */
+      weak_finish ();
 
-  /* This must be at the end before unwind and debug info.
-     Some target ports emit PIC setup thunks here.  */
-  targetm.asm_out.code_end ();
+      /* This must be at the end before unwind and debug info.
+	 Some target ports emit PIC setup thunks here.  */
+      targetm.asm_out.code_end ();
 
-  /* Do dbx symbols.  */
-  timevar_push (TV_SYMOUT);
+      /* Do dbx symbols.  */
+      timevar_push (TV_SYMOUT);
 
-#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
-  if (dwarf2out_do_frame ())
-    dwarf2out_frame_finish ();
-#endif
+    #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
+      if (dwarf2out_do_frame ())
+	dwarf2out_frame_finish ();
+    #endif
 
-  (*debug_hooks->finish) (main_input_filename);
-  timevar_pop (TV_SYMOUT);
+      (*debug_hooks->finish) (main_input_filename);
+      timevar_pop (TV_SYMOUT);
 
-  /* Output some stuff at end of file if nec.  */
+      /* Output some stuff at end of file if nec.  */
 
-  dw2_output_indirect_constants ();
+      dw2_output_indirect_constants ();
 
-  /* Flush any pending external directives.  */
-  process_pending_assemble_externals ();
+      /* Flush any pending external directives.  */
+      process_pending_assemble_externals ();
+   }
 
   /* Emit LTO marker if LTO info has been previously emitted.  This is
      used by collect2 to determine whether an object file contains IL.
@@ -623,6 +628,23 @@ compile_file (void)
 			 (unsigned HOST_WIDE_INT) 1,
 			 (unsigned HOST_WIDE_INT) 1);
 #endif
+      /* Let linker plugin know that this is a slim object and must be LTOed
+         even when user did not ask for it.  */
+      if (!flag_fat_lto_objects)
+        {
+#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
+	  ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE,
+					  "__gnu_slim_lto",
+					  (unsigned HOST_WIDE_INT) 1, 8);
+#elif defined ASM_OUTPUT_ALIGNED_COMMON
+	  ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_slim_lto",
+				     (unsigned HOST_WIDE_INT) 1, 8);
+#else
+	  ASM_OUTPUT_COMMON (asm_out_file, "__gnu_slim_lto",
+			     (unsigned HOST_WIDE_INT) 1,
+			     (unsigned HOST_WIDE_INT) 1);
+#endif
+        }
     }
 
   /* Attach a special .ident directive to the end of the file to identify