diff --git a/gcc/common.opt b/gcc/common.opt
index 634a72b..c01f935 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1132,6 +1132,10 @@ fdump-unnumbered-links
 Common Report Var(flag_dump_unnumbered_links)
 Suppress output of previous and next insn numbers in debugging dumps
 
+fdump-early-debug-stats
+Common Report Var(flag_dump_early_debug_stats)
+Dump all dwarf DIEs, specifying if they were generated during the early debug stage
+
 fdwarf2-cfi-asm
 Common Report Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE)
 Enable CFI tables via GAS assembler directives.
diff --git a/gcc/debug.h b/gcc/debug.h
index ec387ca..7158a48 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -190,11 +190,12 @@ extern bool dwarf2out_do_frame (void);
 extern bool dwarf2out_do_cfi_asm (void);
 extern void dwarf2out_switch_text_section (void);
 
+extern void dwarf2out_mark_early_dies (void);
+extern void dwarf2out_dump_early_debug_stats (void);
+
 const char *remap_debug_filename (const char *);
 void add_debug_prefix_map (const char *);
 
-extern void dwarf2out_early_decl (tree);
-
 /* For -fdump-go-spec.  */
 
 extern const struct gcc_debug_hooks *
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c92101f..a713435 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -5358,9 +5358,9 @@ print_die (dw_die_ref die, FILE *outfile)
   unsigned ix;
 
   print_spaces (outfile);
-  fprintf (outfile, "DIE %4ld: %s (%p)\n",
+  fprintf (outfile, "DIE %4ld: %s (%p)%s\n",
 	   die->die_offset, dwarf_tag_name (die->die_tag),
-	   (void*) die);
+	   (void*) die, die->dumped_early ? " (DUMPED EARLY)" : "");
   print_spaces (outfile);
   fprintf (outfile, "  abbrev id: %lu", die->die_abbrev);
   fprintf (outfile, " offset: %ld", die->die_offset);
@@ -5528,6 +5528,71 @@ debug_dwarf (void)
   print_die (comp_unit_die (), stderr);
 }
 
+/* Callback for htab_traverse_noresize.  Set the dumped_early bit for
+   a given DIE.  */
+
+static int
+mark_early_dies_helper (void **slot, void *info ATTRIBUTE_UNUSED)
+{
+  dw_die_ref ref = (dw_die_ref) *slot;
+
+  /* Unilaterally enabling this bit can potentially change the
+     behavior of dwarf2out_decl for DECLs that were discovered through
+     recursion of dwarf2out_decl(), and may not have the dumped_early
+     bit set.  Since this is only used for debugging the behavior of
+     dwarf2out, we should be ok-- but it's something to keep in
+     mind.  */
+  ref->dumped_early = true;
+  return 1;
+}
+
+/* Set the dumped_early bit for all DIEs.  */
+
+void
+dwarf2out_mark_early_dies (void)
+{
+  if (decl_die_table)
+    htab_traverse_noresize (decl_die_table, mark_early_dies_helper, NULL);
+}
+
+/* Dump the DIE table if available.  */
+
+void
+dwarf2out_dump_early_debug_stats (void)
+{
+  if (decl_die_table)
+    debug_dwarf ();
+}
+
+/* Sanity checks on DW_AT_inline DIEs.  */
+
+static void
+check_die_inline (dw_die_ref die)
+{
+  /* A debugging information entry that is a member of an abstract
+     instance tree [that has DW_AT_inline] should not contain any
+     attributes which describe aspects of the subroutine which vary
+     between distinct inlined expansions or distinct out-of-line
+     expansions.  */
+  unsigned ix;
+  dw_attr_ref a;
+  bool inline_found = false;
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    if (a->dw_attr == DW_AT_inline)
+      inline_found = true;
+  if (inline_found)
+    {
+      /* Catch the most common mistakes.  */
+      FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+	gcc_assert (a->dw_attr != DW_AT_low_pc
+		    && a->dw_attr != DW_AT_high_pc
+		    && a->dw_attr != DW_AT_location
+		    && a->dw_attr != DW_AT_frame_base
+		    && a->dw_attr != DW_AT_GNU_all_call_sites);
+    }
+
+}
+
 /* Perform some sanity checks on DIEs after they have been generated
    earlier in the compilation process.  */
 
@@ -5536,7 +5601,10 @@ check_die (dw_die_ref die, unsigned level)
 {
   static unsigned long mark = 1;
   dw_die_ref c, p;
-  /* Check that all our childs have their parent set to us.  */
+
+  check_die_inline (die);
+
+  /* Check that all of our children have their parent set to us.  */
   c = die->die_child;
   if (c) do {
       c = c->die_sib;
@@ -17721,7 +17789,12 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
     }
 
   bool reusing_die;
-  if (parm_die)
+  if (parm_die
+      /* Make sure the function to which this parameter belongs to is
+	 not an abstract instance.  If it is, we can't reuse anything.
+	 We must create a new DW_TAG_formal_parameter with a
+	 corresponding DW_AT_abstract_origin.  */
+      && !get_AT (context_die, DW_AT_abstract_origin))
     reusing_die = true;
   else
     {
@@ -17739,7 +17812,7 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
       if (reusing_die)
 	goto add_location;
 
-      if (origin != NULL && node != origin)
+      if (origin != NULL)
 	add_abstract_origin_attribute (parm_die, origin);
       else if (emit_name_p)
 	add_name_and_src_coords_attributes (parm_die, node);
@@ -18278,7 +18351,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       && debug_info_level > DINFO_LEVEL_TERSE)
     old_die = force_decl_die (decl);
 
-  if (origin != NULL && origin != decl)
+  if (origin != NULL && (origin != decl || old_die))
     {
       gcc_assert (!declaration || local_scope_p (context_die));
 
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 9f29dac..7dca017 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -573,6 +573,10 @@ compile_file (void)
   /* Run the actual compilation process.  */
   if (!in_lto_p)
     {
+      /* Mark all DIEs generated as dumped early.  */
+      if (flag_dump_early_debug_stats)
+	dwarf2out_mark_early_dies ();
+
       timevar_start (TV_PHASE_OPT_GEN);
       symtab->finalize_compilation_unit ();
       timevar_stop (TV_PHASE_OPT_GEN);
@@ -597,6 +601,9 @@ compile_file (void)
     debug_hooks->late_global_decl (node->decl);
   timevar_stop (TV_PHASE_DBGINFO);
 
+  if (!in_lto_p && flag_dump_early_debug_stats)
+    dwarf2out_dump_early_debug_stats ();
+
   timevar_start (TV_PHASE_LATE_ASM);
 
   /* Compilation unit is finalized.  When producing non-fat LTO object, we are
