Index: gcc/config/arm/arm.c
===================================================================
--- gcc.orig/config/arm/arm.c
+++ gcc/config/arm/arm.c
@@ -19977,18 +19977,19 @@ thumb_pushpop (FILE *f, unsigned long ma
 
   if (push && pushed_words && dwarf2out_do_frame ())
     {
-      char *l = dwarf2out_cfi_label (false);
       int pushed_mask = real_regs;
 
+      dwarf2out_maybe_emit_cfi_label ();
+
       *cfa_offset += pushed_words * 4;
-      dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset);
+      dwarf2out_def_cfa (SP_REGNUM, *cfa_offset);
 
       pushed_words = 0;
       pushed_mask = real_regs;
       for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1)
 	{
 	  if (pushed_mask & 1)
-	    dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset);
+	    dwarf2out_reg_save (regno, 4 * pushed_words++ - *cfa_offset);
 	}
     }
 }
@@ -20997,10 +20998,9 @@ thumb1_output_function_prologue (FILE *f
 	 the stack pointer.  */
       if (dwarf2out_do_frame ())
 	{
-	  char *l = dwarf2out_cfi_label (false);
-
+	  dwarf2out_maybe_emit_cfi_label ();
 	  cfa_offset = cfa_offset + crtl->args.pretend_args_size;
-	  dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
+	  dwarf2out_def_cfa (SP_REGNUM, cfa_offset);
 	}
     }
 
@@ -21046,10 +21046,10 @@ thumb1_output_function_prologue (FILE *f
 
       if (dwarf2out_do_frame ())
 	{
-	  char *l = dwarf2out_cfi_label (false);
+	  dwarf2out_maybe_emit_cfi_label ();
 
 	  cfa_offset = cfa_offset + 16;
-	  dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
+	  dwarf2out_def_cfa (SP_REGNUM, cfa_offset);
 	}
 
       if (l_mask)
@@ -22749,7 +22749,7 @@ arm_except_unwind_info (struct gcc_optio
    stack alignment.  */
 
 static void
-arm_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index)
+arm_dwarf_handle_frame_unspec (rtx pattern, int index)
 {
   rtx unspec = SET_SRC (pattern);
   gcc_assert (GET_CODE (unspec) == UNSPEC);
@@ -22760,8 +22760,7 @@ arm_dwarf_handle_frame_unspec (const cha
       /* ??? We should set the CFA = (SP & ~7).  At this point we haven't
          put anything on the stack, so hopefully it won't matter.
          CFA = SP will be correct after alignment.  */
-      dwarf2out_reg_save_reg (label, stack_pointer_rtx,
-                              SET_DEST (pattern));
+      dwarf2out_reg_save_reg (stack_pointer_rtx, SET_DEST (pattern));
       break;
     default:
       gcc_unreachable ();
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc.orig/config/ia64/ia64.c
+++ gcc/config/ia64/ia64.c
@@ -330,7 +330,7 @@ static enum machine_mode ia64_promote_fu
 static void ia64_trampoline_init (rtx, tree, rtx);
 static void ia64_override_options_after_change (void);
 
-static void ia64_dwarf_handle_frame_unspec (const char *, rtx, int);
+static void ia64_dwarf_handle_frame_unspec (rtx, int);
 static tree ia64_builtin_decl (unsigned, bool);
 
 static reg_class_t ia64_preferred_reload_class (rtx, reg_class_t);
@@ -9710,9 +9710,7 @@ ia64_dwarf2out_def_steady_cfa (rtx insn,
    processing.  The real CFA definition is set up above.  */
 
 static void
-ia64_dwarf_handle_frame_unspec (const char * ARG_UNUSED (label),
-				rtx ARG_UNUSED (pattern),
-				int index)
+ia64_dwarf_handle_frame_unspec (rtx ARG_UNUSED (pattern), int index)
 {
   gcc_assert (index == UNSPECV_ALLOC);
 }
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc.orig/config/sparc/sparc.c
+++ gcc/config/sparc/sparc.c
@@ -454,7 +454,7 @@ static unsigned int sparc_function_arg_b
 						 const_tree);
 static int sparc_arg_partial_bytes (CUMULATIVE_ARGS *,
 				    enum machine_mode, tree, bool);
-static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
+static void sparc_dwarf_handle_frame_unspec (rtx, int);
 static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static void sparc_file_end (void);
 static bool sparc_frame_pointer_required (void);
@@ -9423,12 +9423,11 @@ get_some_local_dynamic_name_1 (rtx *px, 
    This is called from dwarf2out.c to emit call frame instructions
    for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */
 static void
-sparc_dwarf_handle_frame_unspec (const char *label,
-				 rtx pattern ATTRIBUTE_UNUSED,
+sparc_dwarf_handle_frame_unspec (rtx pattern ATTRIBUTE_UNUSED,
 				 int index ATTRIBUTE_UNUSED)
 {
   gcc_assert (index == UNSPECV_SAVEW);
-  dwarf2out_window_save (label);
+  dwarf2out_window_save ();
 }
 
 /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
Index: gcc/config/vax/vax.c
===================================================================
--- gcc.orig/config/vax/vax.c
+++ gcc/config/vax/vax.c
@@ -163,17 +163,18 @@ vax_output_function_prologue (FILE * fil
 
   if (dwarf2out_do_frame ())
     {
-      const char *label = dwarf2out_cfi_label (false);
       int offset = 0;
 
+      dwarf2out_maybe_emit_cfi_label ();
+
       for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno)
 	if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
-	  dwarf2out_reg_save (label, regno, offset -= 4);
+	  dwarf2out_reg_save (regno, offset -= 4);
 
-      dwarf2out_reg_save (label, PC_REGNUM, offset -= 4);
-      dwarf2out_reg_save (label, FRAME_POINTER_REGNUM, offset -= 4);
-      dwarf2out_reg_save (label, ARG_POINTER_REGNUM, offset -= 4);
-      dwarf2out_def_cfa (label, FRAME_POINTER_REGNUM, -(offset - 4));
+      dwarf2out_reg_save (PC_REGNUM, offset -= 4);
+      dwarf2out_reg_save (FRAME_POINTER_REGNUM, offset -= 4);
+      dwarf2out_reg_save (ARG_POINTER_REGNUM, offset -= 4);
+      dwarf2out_def_cfa (false, FRAME_POINTER_REGNUM, -(offset - 4));
     }
 
   size -= STARTING_FRAME_OFFSET;
Index: gcc/dwarf2out.c
===================================================================
--- gcc.orig/dwarf2out.c
+++ gcc/dwarf2out.c
@@ -456,11 +456,11 @@ static GTY(()) section *cold_text_sectio
 static char *stripattributes (const char *);
 static const char *dwarf_cfi_name (unsigned);
 static dw_cfi_ref new_cfi (void);
-static void add_cfi (cfi_vec *, dw_cfi_ref);
-static void add_fde_cfi (const char *, dw_cfi_ref);
+static void add_fde_cfi (dw_cfi_ref);
+static void add_cie_cfi (dw_cfi_ref);
 static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *, dw_cfa_location *);
 static void lookup_cfa (dw_cfa_location *);
-static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT);
+static void reg_save (bool, unsigned, unsigned, HOST_WIDE_INT);
 static void initial_return_save (rtx);
 static HOST_WIDE_INT stack_adjust_offset (const_rtx, HOST_WIDE_INT,
 					  HOST_WIDE_INT);
@@ -469,7 +469,7 @@ static void output_cfi_directive (dw_cfi
 static void output_call_frame_info (int);
 static void dwarf2out_note_section_used (void);
 static bool clobbers_queued_reg_save (const_rtx);
-static void dwarf2out_frame_debug_expr (rtx, const char *);
+static void dwarf2out_frame_debug_expr (rtx);
 static void dwarf2out_cfi_begin_epilogue (rtx);
 static void dwarf2out_frame_debug_restore_state (void);
 
@@ -482,7 +482,7 @@ static struct dw_loc_descr_struct *build
   (dw_cfa_location *, HOST_WIDE_INT);
 static struct dw_loc_descr_struct *build_cfa_aligned_loc
   (HOST_WIDE_INT, HOST_WIDE_INT);
-static void def_cfa_1 (const char *, dw_cfa_location *);
+static void def_cfa_1 (bool, dw_cfa_location *);
 static struct dw_loc_descr_struct *mem_loc_descriptor
   (rtx, enum machine_mode mode, enum var_init_status);
 
@@ -820,35 +820,6 @@ new_cfi (void)
   return cfi;
 }
 
-/* Add a Call Frame Instruction to list of instructions.  */
-
-static inline void
-add_cfi (cfi_vec *vec, dw_cfi_ref cfi)
-{
-  dw_fde_ref fde = current_fde ();
-
-  /* When DRAP is used, CFA is defined with an expression.  Redefine
-     CFA may lead to a different CFA value.   */
-  /* ??? Of course, this heuristic fails when we're annotating epilogues,
-     because of course we'll always want to redefine the CFA back to the
-     stack pointer on the way out.  Where should we move this check?  */
-  if (0 && fde && fde->drap_reg != INVALID_REGNUM)
-    switch (cfi->dw_cfi_opc)
-      {
-        case DW_CFA_def_cfa_register:
-        case DW_CFA_def_cfa_offset:
-        case DW_CFA_def_cfa_offset_sf:
-        case DW_CFA_def_cfa:
-        case DW_CFA_def_cfa_sf:
-	  gcc_unreachable ();
-
-        default:
-          break;
-      }
-
-  VEC_safe_push (dw_cfi_ref, gc, *vec, cfi);
-}
-
 /* The insn after which a new CFI note should be emitted.  */
 static rtx cfi_insn;
 
@@ -858,45 +829,51 @@ static bool emit_cfa_remember;
 /* True if any CFI directives were emitted at the current insn.  */
 static bool any_cfis_emitted;
 
-/* Generate a new label for the CFI info to refer to.  FORCE is true
-   if a label needs to be output even when using .cfi_* directives.  */
+/* Generate a new label for the CFI info to refer to.  */
 
-char *
-dwarf2out_cfi_label (bool force)
+static char *
+dwarf2out_cfi_label (void)
 {
   static char label[20];
 
-  if (!force && dwarf2out_do_cfi_asm ())
-    {
-      /* In this case, we will be emitting the asm directive instead of
-	 the label, so just return a placeholder to keep the rest of the
-	 interfaces happy.  */
-      strcpy (label, "<do not output>");
-    }
-  else
-    {
-      int num = dwarf2out_cfi_label_num++;
-      ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num);
-      cfi_insn = emit_note_after (NOTE_INSN_CFI_LABEL, cfi_insn);
-      NOTE_LABEL_NUMBER (cfi_insn) = num;
-    }
+  int num = dwarf2out_cfi_label_num++;
+  ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num);
 
   return label;
 }
 
+/* Called by target specific code if it wants to emit CFI insns in the text
+   prologue.  If necessary, emit a CFI label and an advance_loc CFI.  See
+   also cfi_label_required_p.  */
+void
+dwarf2out_maybe_emit_cfi_label (void)
+{
+  if ((dwarf_version == 2
+       && debug_info_level > DINFO_LEVEL_TERSE
+       && (write_symbols == DWARF2_DEBUG
+	   || write_symbols == VMS_AND_DWARF2_DEBUG))
+      || !dwarf2out_do_cfi_asm ())
+    {
+      const char *l;
+      dw_cfi_ref xcfi;
+
+      ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", dwarf2out_cfi_label_num);
+      l = dwarf2out_cfi_label ();
+      l = xstrdup (l);
+
+      xcfi = new_cfi ();
+      xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
+      xcfi->dw_cfi_oprnd1.dw_cfi_addr = l;
+      add_fde_cfi (xcfi);
+    }
+}
+
 /* Add CFI to the current fde at the PC value indicated by LABEL if specified,
    or to the CIE if LABEL is NULL.  */
 
 static void
-add_fde_cfi (const char *label, dw_cfi_ref cfi)
+add_fde_cfi (dw_cfi_ref cfi)
 {
-  cfi_vec *vec;
-
-  if (cie_cfi_vec == NULL)
-    cie_cfi_vec = VEC_alloc (dw_cfi_ref, gc, 20);
-
-  vec = &cie_cfi_vec;
-
   if (emit_cfa_remember)
     {
       dw_cfi_ref cfi_remember;
@@ -905,110 +882,30 @@ add_fde_cfi (const char *label, dw_cfi_r
       emit_cfa_remember = false;
       cfi_remember = new_cfi ();
       cfi_remember->dw_cfi_opc = DW_CFA_remember_state;
-      add_fde_cfi (label, cfi_remember);
+      add_fde_cfi (cfi_remember);
     }
 
-  if (dwarf2out_do_cfi_asm ())
+  any_cfis_emitted = true;
+  if (cfi_insn != NULL)
     {
-      if (label)
-	{
-	  dw_fde_ref fde = current_fde ();
-
-	  gcc_assert (fde != NULL);
-
-	  /* We still have to add the cfi to the list so that lookup_cfa
-	     works later on.  When -g2 and above we even need to force
-	     emitting of CFI labels and add to list a DW_CFA_set_loc for
-	     convert_cfa_to_fb_loc_list purposes.  If we're generating
-	     DWARF3 output we use DW_OP_call_frame_cfa and so don't use
-	     convert_cfa_to_fb_loc_list.  */
-	  if (dwarf_version == 2
-	      && debug_info_level > DINFO_LEVEL_TERSE
-	      && (write_symbols == DWARF2_DEBUG
-		  || write_symbols == VMS_AND_DWARF2_DEBUG))
-	    {
-	      switch (cfi->dw_cfi_opc)
-		{
-		case DW_CFA_def_cfa_offset:
-		case DW_CFA_def_cfa_offset_sf:
-		case DW_CFA_def_cfa_register:
-		case DW_CFA_def_cfa:
-		case DW_CFA_def_cfa_sf:
-		case DW_CFA_def_cfa_expression:
-		case DW_CFA_restore_state:
-		  if (*label == 0 || strcmp (label, "<do not output>") == 0)
-		    label = dwarf2out_cfi_label (true);
-
-		  if (fde->dw_fde_current_label == NULL
-		      || strcmp (label, fde->dw_fde_current_label) != 0)
-		    {
-		      dw_cfi_ref xcfi;
-
-		      label = xstrdup (label);
-
-		      /* Set the location counter to the new label.  */
-		      xcfi = new_cfi ();
-		      /* It doesn't metter whether DW_CFA_set_loc
-		         or DW_CFA_advance_loc4 is added here, those aren't
-		         emitted into assembly, only looked up by
-		         convert_cfa_to_fb_loc_list.  */
-		      xcfi->dw_cfi_opc = DW_CFA_set_loc;
-		      xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
-		      add_cfi (&fde->dw_fde_cfi, xcfi);
-		      fde->dw_fde_current_label = label;
-		    }
-		  break;
-		default:
-		  break;
-	        }
-	    }
-
-	  cfi_insn = emit_note_after (NOTE_INSN_CFI, cfi_insn);
-	  NOTE_CFI (cfi_insn) = cfi;
-
-	  vec = &fde->dw_fde_cfi;
-	  any_cfis_emitted = true;
-	}
-      /* ??? If this is a CFI for the CIE, we don't emit.  This
-	 assumes that the standard CIE contents that the assembler
-	 uses matches the standard CIE contents that the compiler
-	 uses.  This is probably a bad assumption.  I'm not quite
-	 sure how to address this for now.  */
+      cfi_insn = emit_note_after (NOTE_INSN_CFI, cfi_insn);
+      NOTE_CFI (cfi_insn) = cfi;
     }
-  else if (label)
+  else
     {
       dw_fde_ref fde = current_fde ();
-
-      gcc_assert (fde != NULL);
-
-      if (*label == 0)
-	label = dwarf2out_cfi_label (false);
-
-      if (fde->dw_fde_current_label == NULL
-	  || strcmp (label, fde->dw_fde_current_label) != 0)
-	{
-	  dw_cfi_ref xcfi;
-
-	  label = xstrdup (label);
-
-	  /* Set the location counter to the new label.  */
-	  xcfi = new_cfi ();
-	  /* If we have a current label, advance from there, otherwise
-	     set the location directly using set_loc.  */
-	  xcfi->dw_cfi_opc = fde->dw_fde_current_label
-			     ? DW_CFA_advance_loc4
-			     : DW_CFA_set_loc;
-	  xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
-	  add_cfi (&fde->dw_fde_cfi, xcfi);
-
-	  fde->dw_fde_current_label = label;
-	}
-
-      vec = &fde->dw_fde_cfi;
-      any_cfis_emitted = true;
+      VEC_safe_push (dw_cfi_ref, gc, fde->dw_fde_cfi, cfi);
+      dwarf2out_emit_cfi (cfi);
     }
+}
+
+static void
+add_cie_cfi (dw_cfi_ref cfi)
+{
+  if (cie_cfi_vec == NULL)
+    cie_cfi_vec = VEC_alloc (dw_cfi_ref, gc, 20);
 
-  add_cfi (vec, cfi);
+  VEC_safe_push (dw_cfi_ref, gc, cie_cfi_vec, cfi);
 }
 
 /* Subroutine of lookup_cfa.  */
@@ -1076,6 +973,9 @@ lookup_cfa (dw_cfa_location *loc)
 /* The current rule for calculating the DWARF2 canonical frame address.  */
 static dw_cfa_location cfa;
 
+/* A copy of CFA, for comparison purposes  */
+static dw_cfa_location old_cfa;
+
 /* The register used for saving registers to the stack, and its offset
    from the CFA.  */
 static dw_cfa_location cfa_store;
@@ -1083,25 +983,27 @@ static dw_cfa_location cfa_store;
 /* The current save location around an epilogue.  */
 static dw_cfa_location cfa_remember;
 
+/* Like cfa_remember, but a copy of old_cfa.  */
+static dw_cfa_location old_cfa_remember;
+
 /* The running total of the size of arguments pushed onto the stack.  */
 static HOST_WIDE_INT args_size;
 
 /* The last args_size we actually output.  */
 static HOST_WIDE_INT old_args_size;
 
-/* Entry point to update the canonical frame address (CFA).
-   LABEL is passed to add_fde_cfi.  The value of CFA is now to be
-   calculated from REG+OFFSET.  */
+/* Entry point to update the canonical frame address (CFA).  The value
+   of CFA is now to be calculated from REG+OFFSET.  */
 
 void
-dwarf2out_def_cfa (const char *label, unsigned int reg, HOST_WIDE_INT offset)
+dwarf2out_def_cfa (bool for_cie, unsigned int reg, HOST_WIDE_INT offset)
 {
   dw_cfa_location loc;
   loc.indirect = 0;
   loc.base_offset = 0;
   loc.reg = reg;
   loc.offset = offset;
-  def_cfa_1 (label, &loc);
+  def_cfa_1 (for_cie, &loc);
 }
 
 /* Determine if two dw_cfa_location structures define the same data.  */
@@ -1120,10 +1022,10 @@ cfa_equal_p (const dw_cfa_location *loc1
    the dw_cfa_location structure.  */
 
 static void
-def_cfa_1 (const char *label, dw_cfa_location *loc_p)
+def_cfa_1 (bool for_cie, dw_cfa_location *loc_p)
 {
   dw_cfi_ref cfi;
-  dw_cfa_location old_cfa, loc;
+  dw_cfa_location loc;
 
   cfa = *loc_p;
   loc = *loc_p;
@@ -1132,7 +1034,6 @@ def_cfa_1 (const char *label, dw_cfa_loc
     cfa_store.offset = loc.offset;
 
   loc.reg = DWARF_FRAME_REGNUM (loc.reg);
-  lookup_cfa (&old_cfa);
 
   /* If nothing changed, no need to issue any call frame instructions.  */
   if (cfa_equal_p (&loc, &old_cfa))
@@ -1193,16 +1094,19 @@ def_cfa_1 (const char *label, dw_cfa_loc
       cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list;
     }
 
-  add_fde_cfi (label, cfi);
+  if (for_cie)
+    add_cie_cfi (cfi);
+  else
+    add_fde_cfi (cfi);
+  old_cfa = loc;
 }
 
 /* Add the CFI for saving a register.  REG is the CFA column number.
-   LABEL is passed to add_fde_cfi.
    If SREG is -1, the register is saved at OFFSET from the CFA;
    otherwise it is saved in SREG.  */
 
 static void
-reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT offset)
+reg_save (bool for_cie, unsigned int reg, unsigned int sreg, HOST_WIDE_INT offset)
 {
   dw_cfi_ref cfi = new_cfi ();
   dw_fde_ref fde = current_fde ();
@@ -1238,10 +1142,13 @@ reg_save (const char *label, unsigned in
       cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg;
     }
 
-  add_fde_cfi (label, cfi);
+  if (for_cie)
+    add_cie_cfi (cfi);
+  else
+    add_fde_cfi (cfi);
 }
 
-/* Add the CFI for saving a register window.  LABEL is passed to reg_save.
+/* Add the CFI for saving a register window.
    This CFI tells the unwinder that it needs to restore the window registers
    from the previous frame's window save area.
 
@@ -1249,39 +1156,39 @@ reg_save (const char *label, unsigned in
    assuming 0(cfa)) and what registers are in the window.  */
 
 void
-dwarf2out_window_save (const char *label)
+dwarf2out_window_save (void)
 {
   dw_cfi_ref cfi = new_cfi ();
 
   cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
-  add_fde_cfi (label, cfi);
+  add_fde_cfi (cfi);
 }
 
 /* Entry point for saving a register to the stack.  REG is the GCC register
    number.  LABEL and OFFSET are passed to reg_save.  */
 
 void
-dwarf2out_reg_save (const char *label, unsigned int reg, HOST_WIDE_INT offset)
+dwarf2out_reg_save (unsigned int reg, HOST_WIDE_INT offset)
 {
-  reg_save (label, DWARF_FRAME_REGNUM (reg), INVALID_REGNUM, offset);
+  reg_save (false, DWARF_FRAME_REGNUM (reg), INVALID_REGNUM, offset);
 }
 
 /* Entry point for saving the return address in the stack.
    LABEL and OFFSET are passed to reg_save.  */
 
 void
-dwarf2out_return_save (const char *label, HOST_WIDE_INT offset)
+dwarf2out_return_save (HOST_WIDE_INT offset)
 {
-  reg_save (label, DWARF_FRAME_RETURN_COLUMN, INVALID_REGNUM, offset);
+  reg_save (false, DWARF_FRAME_RETURN_COLUMN, INVALID_REGNUM, offset);
 }
 
 /* Entry point for saving the return address in a register.
    LABEL and SREG are passed to reg_save.  */
 
 void
-dwarf2out_return_reg (const char *label, unsigned int sreg)
+dwarf2out_return_reg (unsigned int sreg)
 {
-  reg_save (label, DWARF_FRAME_RETURN_COLUMN, DWARF_FRAME_REGNUM (sreg), 0);
+  reg_save (false, DWARF_FRAME_RETURN_COLUMN, DWARF_FRAME_REGNUM (sreg), 0);
 }
 
 /* Record the initial position of the return address.  RTL is
@@ -1339,7 +1246,7 @@ initial_return_save (rtx rtl)
     }
 
   if (reg != DWARF_FRAME_RETURN_COLUMN)
-    reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
+    reg_save (true, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
 }
 
 /* Given a SET, calculate the amount of stack adjustment it
@@ -1609,7 +1516,7 @@ compute_barrier_args_size (void)
    pushed onto the stack.  */
 
 static void
-dwarf2out_args_size (const char *label, HOST_WIDE_INT size)
+dwarf2out_args_size (HOST_WIDE_INT size)
 {
   dw_cfi_ref cfi;
 
@@ -1621,13 +1528,13 @@ dwarf2out_args_size (const char *label, 
   cfi = new_cfi ();
   cfi->dw_cfi_opc = DW_CFA_GNU_args_size;
   cfi->dw_cfi_oprnd1.dw_cfi_offset = size;
-  add_fde_cfi (label, cfi);
+  add_fde_cfi (cfi);
 }
 
 /* Record a stack adjustment of OFFSET bytes.  */
 
 static void
-dwarf2out_stack_adjust (HOST_WIDE_INT offset, const char *label)
+dwarf2out_stack_adjust (HOST_WIDE_INT offset)
 {
   if (cfa.reg == STACK_POINTER_REGNUM)
     cfa.offset += offset;
@@ -1646,9 +1553,9 @@ dwarf2out_stack_adjust (HOST_WIDE_INT of
   if (args_size < 0)
     args_size = 0;
 
-  def_cfa_1 (label, &cfa);
+  def_cfa_1 (false, &cfa);
   if (flag_asynchronous_unwind_tables)
-    dwarf2out_args_size (label, args_size);
+    dwarf2out_args_size (args_size);
 }
 
 /* Check INSN to see if it looks like a push or a stack adjustment, and
@@ -1659,7 +1566,6 @@ static void
 dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
 {
   HOST_WIDE_INT offset;
-  const char *label;
   int i;
 
   /* Don't handle epilogues at all.  Certainly it would be wrong to do so
@@ -1690,7 +1596,7 @@ dwarf2out_notice_stack_adjust (rtx insn,
 	  if (GET_CODE (insn) == SET)
 	    insn = SET_SRC (insn);
 	  gcc_assert (GET_CODE (insn) == CALL);
-	  dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+	  dwarf2out_args_size (INTVAL (XEXP (insn, 1)));
 	}
       return;
     }
@@ -1698,7 +1604,7 @@ dwarf2out_notice_stack_adjust (rtx insn,
   if (CALL_P (insn) && !after_p)
     {
       if (!flag_asynchronous_unwind_tables)
-	dwarf2out_args_size ("", args_size);
+	dwarf2out_args_size (args_size);
       return;
     }
   else if (BARRIER_P (insn))
@@ -1739,8 +1645,7 @@ dwarf2out_notice_stack_adjust (rtx insn,
   if (offset == 0)
     return;
 
-  label = dwarf2out_cfi_label (false);
-  dwarf2out_stack_adjust (offset, label);
+  dwarf2out_stack_adjust (offset);
 }
 
 /* We delay emitting a register save until either (a) we reach the end
@@ -1769,13 +1674,11 @@ struct GTY(()) reg_saved_in_data {
 static GTY(()) struct reg_saved_in_data regs_saved_in_regs[4];
 static GTY(()) size_t num_regs_saved_in_regs;
 
-static const char *last_reg_save_label;
-
 /* Add an entry to QUEUED_REG_SAVES saying that REG is now saved at
    SREG, or if SREG is NULL then it is saved at OFFSET to the CFA.  */
 
 static void
-queue_reg_save (const char *label, rtx reg, rtx sreg, HOST_WIDE_INT offset)
+queue_reg_save (rtx reg, rtx sreg, HOST_WIDE_INT offset)
 {
   struct queued_reg_save *q;
 
@@ -1796,8 +1699,6 @@ queue_reg_save (const char *label, rtx r
   q->reg = reg;
   q->cfa_offset = offset;
   q->saved_reg = sreg;
-
-  last_reg_save_label = label;
 }
 
 /* Output all the entries in QUEUED_REG_SAVES.  */
@@ -1831,11 +1732,10 @@ dwarf2out_flush_queued_reg_saves (void)
 	sreg = DWARF_FRAME_REGNUM (REGNO (q->saved_reg));
       else
 	sreg = INVALID_REGNUM;
-      reg_save (last_reg_save_label, reg, sreg, q->cfa_offset);
+      reg_save (false, reg, sreg, q->cfa_offset);
     }
 
   queued_reg_saves = NULL;
-  last_reg_save_label = NULL;
 }
 
 /* Does INSN clobber any register which QUEUED_REG_SAVES lists a saved
@@ -1865,7 +1765,7 @@ clobbers_queued_reg_save (const_rtx insn
 /* Entry point for saving the first register into the second.  */
 
 void
-dwarf2out_reg_save_reg (const char *label, rtx reg, rtx sreg)
+dwarf2out_reg_save_reg (rtx reg, rtx sreg)
 {
   size_t i;
   unsigned int regno, sregno;
@@ -1883,7 +1783,7 @@ dwarf2out_reg_save_reg (const char *labe
 
   regno = DWARF_FRAME_REGNUM (REGNO (reg));
   sregno = DWARF_FRAME_REGNUM (REGNO (sreg));
-  reg_save (label, regno, sregno, 0);
+  reg_save (false, regno, sregno, 0);
 }
 
 /* What register, if any, is currently saved in REG?  */
@@ -1916,7 +1816,7 @@ static dw_cfa_location cfa_temp;
 /* A subroutine of dwarf2out_frame_debug, process a REG_DEF_CFA note.  */
 
 static void
-dwarf2out_frame_debug_def_cfa (rtx pat, const char *label)
+dwarf2out_frame_debug_def_cfa (rtx pat)
 {
   memset (&cfa, 0, sizeof (cfa));
 
@@ -1947,13 +1847,13 @@ dwarf2out_frame_debug_def_cfa (rtx pat, 
       gcc_unreachable ();
     }
 
-  def_cfa_1 (label, &cfa);
+  def_cfa_1 (false, &cfa);
 }
 
 /* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note.  */
 
 static void
-dwarf2out_frame_debug_adjust_cfa (rtx pat, const char *label)
+dwarf2out_frame_debug_adjust_cfa (rtx pat)
 {
   rtx src, dest;
 
@@ -1978,13 +1878,13 @@ dwarf2out_frame_debug_adjust_cfa (rtx pa
   cfa.reg = REGNO (dest);
   gcc_assert (cfa.indirect == 0);
 
-  def_cfa_1 (label, &cfa);
+  def_cfa_1 (false, &cfa);
 }
 
 /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_OFFSET note.  */
 
 static void
-dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
+dwarf2out_frame_debug_cfa_offset (rtx set)
 {
   HOST_WIDE_INT offset;
   rtx src, addr, span;
@@ -2014,7 +1914,7 @@ dwarf2out_frame_debug_cfa_offset (rtx se
   /* ??? We'd like to use queue_reg_save, but we need to come up with
      a different flushing heuristic for epilogues.  */
   if (!span)
-    reg_save (label, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset);
+    reg_save (false, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset);
   else
     {
       /* We have a PARALLEL describing where the contents of SRC live.
@@ -2030,7 +1930,7 @@ dwarf2out_frame_debug_cfa_offset (rtx se
 	{
 	  rtx elem = XVECEXP (span, 0, par_index);
 
-	  reg_save (label, DWARF_FRAME_REGNUM (REGNO (elem)),
+	  reg_save (false, DWARF_FRAME_REGNUM (REGNO (elem)),
 		    INVALID_REGNUM, span_offset);
 	  span_offset += GET_MODE_SIZE (GET_MODE (elem));
 	}
@@ -2040,7 +1940,7 @@ dwarf2out_frame_debug_cfa_offset (rtx se
 /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_REGISTER note.  */
 
 static void
-dwarf2out_frame_debug_cfa_register (rtx set, const char *label)
+dwarf2out_frame_debug_cfa_register (rtx set)
 {
   rtx src, dest;
   unsigned sregno, dregno;
@@ -2057,13 +1957,13 @@ dwarf2out_frame_debug_cfa_register (rtx 
 
   /* ??? We'd like to use queue_reg_save, but we need to come up with
      a different flushing heuristic for epilogues.  */
-  reg_save (label, sregno, dregno, 0);
+  reg_save (false, sregno, dregno, 0);
 }
 
 /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note. */
 
 static void
-dwarf2out_frame_debug_cfa_expression (rtx set, const char *label)
+dwarf2out_frame_debug_cfa_expression (rtx set)
 {
   rtx src, dest, span;
   dw_cfi_ref cfi = new_cfi ();
@@ -2085,13 +1985,13 @@ dwarf2out_frame_debug_cfa_expression (rt
 
   /* ??? We'd like to use queue_reg_save, were the interface different,
      and, as above, we could manage flushing for epilogues.  */
-  add_fde_cfi (label, cfi);
+  add_fde_cfi (cfi);
 }
 
 /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note.  */
 
 static void
-dwarf2out_frame_debug_cfa_restore (rtx reg, const char *label)
+dwarf2out_frame_debug_cfa_restore (rtx reg)
 {
   dw_cfi_ref cfi = new_cfi ();
   unsigned int regno = DWARF_FRAME_REGNUM (REGNO (reg));
@@ -2099,7 +1999,102 @@ dwarf2out_frame_debug_cfa_restore (rtx r
   cfi->dw_cfi_opc = (regno & ~0x3f ? DW_CFA_restore_extended : DW_CFA_restore);
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = regno;
 
-  add_fde_cfi (label, cfi);
+  add_fde_cfi (cfi);
+}
+
+/* Examine CFI and return true if a cfi label and set_loc is needed before
+   it.  Even when generating CFI assembler instructions, we still have to
+   add the cfi to the list so that lookup_cfa works later on.  When
+   -g2 and above we even need to force emitting of CFI labels and add
+   to list a DW_CFA_set_loc for convert_cfa_to_fb_loc_list purposes.
+   If we're generating DWARF3 output we use DW_OP_call_frame_cfa and
+   so don't use convert_cfa_to_fb_loc_list.  */
+
+static bool
+cfi_label_required_p (dw_cfi_ref cfi)
+{
+  if (!dwarf2out_do_cfi_asm ())
+    return true;
+
+  if (dwarf_version == 2
+      && debug_info_level > DINFO_LEVEL_TERSE
+      && (write_symbols == DWARF2_DEBUG
+	  || write_symbols == VMS_AND_DWARF2_DEBUG))
+    {
+      switch (cfi->dw_cfi_opc)
+	{
+	case DW_CFA_def_cfa_offset:
+	case DW_CFA_def_cfa_offset_sf:
+	case DW_CFA_def_cfa_register:
+	case DW_CFA_def_cfa:
+	case DW_CFA_def_cfa_sf:
+	case DW_CFA_def_cfa_expression:
+	case DW_CFA_restore_state:
+	  return true;
+	default:
+	  return false;
+	}
+    }
+  return false;
+}
+
+/* Walk the functino, looking for NOTE_INSN_CFI notes.  Add the CFIs to the
+   function's FDE, adding CFI labels and set_loc/advance_loc opcodes as
+   necessary.  */
+static void
+add_cfis_to_fde (void)
+{
+  dw_fde_ref fde = current_fde ();
+  rtx insn, next;
+  /* We always start with a function_begin label.  */
+  bool first = false;
+
+  for (insn = get_insns (); insn; insn = next)
+    {
+      next = NEXT_INSN (insn);
+
+      if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+	/* Don't attempt to advance_loc4 between labels in different
+	   sections.  */
+	first = true;
+
+      if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_CFI)
+	{
+	  bool required = cfi_label_required_p (NOTE_CFI (insn));
+	  while (next && NOTE_P (next) && NOTE_KIND (next) == NOTE_INSN_CFI)
+	    {
+	      required |= cfi_label_required_p (NOTE_CFI (next));
+	      next = NEXT_INSN (next);
+	    }
+	  if (required)
+	    {
+	      int num = dwarf2out_cfi_label_num;
+	      const char *label = dwarf2out_cfi_label ();
+	      dw_cfi_ref xcfi;
+	      rtx tmp;
+
+	      label = xstrdup (label);
+
+	      /* Set the location counter to the new label.  */
+	      xcfi = new_cfi ();
+	      xcfi->dw_cfi_opc = (first ? DW_CFA_set_loc
+				  : DW_CFA_advance_loc4);
+	      xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
+	      VEC_safe_push (dw_cfi_ref, gc, fde->dw_fde_cfi, xcfi);
+
+	      tmp = emit_note_before (NOTE_INSN_CFI_LABEL, insn);
+	      NOTE_LABEL_NUMBER (tmp) = num;
+	    }
+
+	  do
+	    {
+	      VEC_safe_push (dw_cfi_ref, gc, fde->dw_fde_cfi, NOTE_CFI (insn));
+	      insn = NEXT_INSN (insn);
+	    }
+	  while (insn != next);
+	  first = false;
+	}
+    }
 }
 
 /* Record call frame debugging information for an expression EXPR,
@@ -2298,7 +2293,7 @@ dwarf2out_frame_debug_cfa_restore (rtx r
   	   cfa.reg == fde->drap_reg  */
 
 static void
-dwarf2out_frame_debug_expr (rtx expr, const char *label)
+dwarf2out_frame_debug_expr (rtx expr)
 {
   rtx src, dest, span;
   HOST_WIDE_INT offset;
@@ -2327,7 +2322,7 @@ dwarf2out_frame_debug_expr (rtx expr, co
 	    if (GET_CODE (elem) == SET
 		&& MEM_P (SET_DEST (elem))
 		&& (RTX_FRAME_RELATED_P (elem) || par_index == 0))
-	      dwarf2out_frame_debug_expr (elem, label);
+	      dwarf2out_frame_debug_expr (elem);
 	  }
 
       for (par_index = 0; par_index < limit; par_index++)
@@ -2336,7 +2331,7 @@ dwarf2out_frame_debug_expr (rtx expr, co
 	  if (GET_CODE (elem) == SET
 	      && (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
 	      && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
-	    dwarf2out_frame_debug_expr (elem, label);
+	    dwarf2out_frame_debug_expr (elem);
 	  else if (GET_CODE (elem) == SET
 		   && par_index != 0
 		   && !RTX_FRAME_RELATED_P (elem))
@@ -2346,7 +2341,7 @@ dwarf2out_frame_debug_expr (rtx expr, co
 	      HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0);
 
 	      if (offset != 0)
-		dwarf2out_stack_adjust (offset, label);
+		dwarf2out_stack_adjust (offset);
 	    }
 	}
       return;
@@ -2406,7 +2401,7 @@ dwarf2out_frame_debug_expr (rtx expr, co
 			    && fde->drap_reg != INVALID_REGNUM
 			    && cfa.reg != REGNO (src));
 	      else
-		queue_reg_save (label, src, dest, 0);
+		queue_reg_save (src, dest, 0);
 	    }
 	  break;
 
@@ -2536,7 +2531,7 @@ dwarf2out_frame_debug_expr (rtx expr, co
 	case UNSPEC:
 	case UNSPEC_VOLATILE:
 	  gcc_assert (targetm.dwarf_handle_frame_unspec);
-	  targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1));
+	  targetm.dwarf_handle_frame_unspec (expr, XINT (src, 1));
 	  return;
 
 	  /* Rule 16 */
@@ -2565,7 +2560,7 @@ dwarf2out_frame_debug_expr (rtx expr, co
 	  gcc_unreachable ();
 	}
 
-      def_cfa_1 (label, &cfa);
+      def_cfa_1 (false, &cfa);
       break;
 
     case MEM:
@@ -2721,15 +2716,15 @@ dwarf2out_frame_debug_expr (rtx expr, co
 
 		  fde->drap_reg_saved = 1;
 
-		  def_cfa_1 (label, &cfa_exp);
+		  def_cfa_1 (false, &cfa_exp);
 		  break;
                 }
 
 	      /* If the source register is exactly the CFA, assume
 		 we're saving SP like any other register; this happens
 		 on the ARM.  */
-	      def_cfa_1 (label, &cfa);
-	      queue_reg_save (label, stack_pointer_rtx, NULL_RTX, offset);
+	      def_cfa_1 (false, &cfa);
+	      queue_reg_save (stack_pointer_rtx, NULL_RTX, offset);
 	      break;
 	    }
 	  else
@@ -2745,17 +2740,17 @@ dwarf2out_frame_debug_expr (rtx expr, co
 	      cfa.reg = REGNO (x);
 	      cfa.base_offset = offset;
 	      cfa.indirect = 1;
-	      def_cfa_1 (label, &cfa);
+	      def_cfa_1 (false, &cfa);
 	      break;
 	    }
 	}
 
-      def_cfa_1 (label, &cfa);
+      def_cfa_1 (false, &cfa);
       {
 	span = targetm.dwarf_register_span (src);
 
 	if (!span)
-	  queue_reg_save (label, src, NULL_RTX, offset);
+	  queue_reg_save (src, NULL_RTX, offset);
 	else
 	  {
 	    /* We have a PARALLEL describing where the contents of SRC
@@ -2772,7 +2767,7 @@ dwarf2out_frame_debug_expr (rtx expr, co
 	      {
 		rtx elem = XVECEXP (span, 0, par_index);
 
-		queue_reg_save (label, elem, NULL_RTX, span_offset);
+		queue_reg_save (elem, NULL_RTX, span_offset);
 		span_offset += GET_MODE_SIZE (GET_MODE (elem));
 	      }
 	  }
@@ -2794,7 +2789,6 @@ dwarf2out_frame_debug_expr (rtx expr, co
 void
 dwarf2out_frame_debug (rtx insn, bool after_p)
 {
-  const char *label;
   rtx note, n;
   bool handled_one = false;
 
@@ -2813,10 +2807,10 @@ dwarf2out_frame_debug (rtx insn, bool af
 	 is still used to save registers.  */
       if (!ACCUMULATE_OUTGOING_ARGS)
 	dwarf2out_notice_stack_adjust (insn, after_p);
+      cfi_insn = NULL;
       return;
     }
 
-  label = dwarf2out_cfi_label (false);
   any_cfis_emitted = false;
 
   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
@@ -2827,7 +2821,7 @@ dwarf2out_frame_debug (rtx insn, bool af
 	goto found;
 
       case REG_CFA_DEF_CFA:
-	dwarf2out_frame_debug_def_cfa (XEXP (note, 0), label);
+	dwarf2out_frame_debug_def_cfa (XEXP (note, 0));
 	handled_one = true;
 	break;
 
@@ -2839,7 +2833,7 @@ dwarf2out_frame_debug (rtx insn, bool af
 	    if (GET_CODE (n) == PARALLEL)
 	      n = XVECEXP (n, 0, 0);
 	  }
-	dwarf2out_frame_debug_adjust_cfa (n, label);
+	dwarf2out_frame_debug_adjust_cfa (n);
 	handled_one = true;
 	break;
 
@@ -2847,7 +2841,7 @@ dwarf2out_frame_debug (rtx insn, bool af
 	n = XEXP (note, 0);
 	if (n == NULL)
 	  n = single_set (insn);
-	dwarf2out_frame_debug_cfa_offset (n, label);
+	dwarf2out_frame_debug_cfa_offset (n);
 	handled_one = true;
 	break;
 
@@ -2859,7 +2853,7 @@ dwarf2out_frame_debug (rtx insn, bool af
 	    if (GET_CODE (n) == PARALLEL)
 	      n = XVECEXP (n, 0, 0);
 	  }
-	dwarf2out_frame_debug_cfa_register (n, label);
+	dwarf2out_frame_debug_cfa_register (n);
 	handled_one = true;
 	break;
 
@@ -2867,7 +2861,7 @@ dwarf2out_frame_debug (rtx insn, bool af
 	n = XEXP (note, 0);
 	if (n == NULL)
 	  n = single_set (insn);
-	dwarf2out_frame_debug_cfa_expression (n, label);
+	dwarf2out_frame_debug_cfa_expression (n);
 	handled_one = true;
 	break;
 
@@ -2880,7 +2874,7 @@ dwarf2out_frame_debug (rtx insn, bool af
 	      n = XVECEXP (n, 0, 0);
 	    n = XEXP (n, 0);
 	  }
-	dwarf2out_frame_debug_cfa_restore (n, label);
+	dwarf2out_frame_debug_cfa_restore (n);
 	handled_one = true;
 	break;
 
@@ -2906,18 +2900,20 @@ dwarf2out_frame_debug (rtx insn, bool af
     {
       if (any_cfis_emitted)
 	dwarf2out_flush_queued_reg_saves ();
+      cfi_insn = NULL;
       return;
     }
 
   insn = PATTERN (insn);
  found:
-  dwarf2out_frame_debug_expr (insn, label);
+  dwarf2out_frame_debug_expr (insn);
 
   /* Check again.  A parallel can save and update the same register.
      We could probably check just once, here, but this is safer than
      removing the check above.  */
   if (any_cfis_emitted || clobbers_queued_reg_save (insn))
     dwarf2out_flush_queued_reg_saves ();
+  cfi_insn = NULL;
 }
 
 /* Called once at the start of final to initialize some data for the
@@ -2926,7 +2922,6 @@ void
 dwarf2out_frame_debug_init (void)
 {
   size_t i;
-  rtx insn;
 
   /* Flush any queued register saves.  */
   dwarf2out_flush_queued_reg_saves ();
@@ -2936,6 +2931,7 @@ dwarf2out_frame_debug_init (void)
   gcc_assert (cfa.reg
 	      == (unsigned long)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
 
+  old_cfa = cfa;
   cfa.reg = STACK_POINTER_REGNUM;
   cfa_store = cfa;
   cfa_temp.reg = -1;
@@ -2947,7 +2943,15 @@ dwarf2out_frame_debug_init (void)
       regs_saved_in_regs[i].saved_in_reg = NULL_RTX;
     }
   num_regs_saved_in_regs = 0;
+}
+
+/* After the (optional) text prologue has been written, emit CFI insns
+   and update the FDE for frame-related instructions.  */
 
+void
+dwarf2out_frame_debug_after_prologue (void)
+{
+  rtx insn;
   if (barrier_args_size)
     {
       XDELETEVEC (barrier_args_size);
@@ -2973,6 +2977,7 @@ dwarf2out_frame_debug_init (void)
 	    case NOTE_INSN_CFA_RESTORE_STATE:
 	      cfi_insn = insn;
 	      dwarf2out_frame_debug_restore_state ();
+	      cfi_insn = NULL;
 	      break;
 	    }
 	  continue;
@@ -2999,12 +3004,15 @@ dwarf2out_frame_debug_init (void)
 	  )
 	dwarf2out_frame_debug (insn, true);
     }
+
+  add_cfis_to_fde ();
 }
 
 void
 dwarf2out_emit_cfi (dw_cfi_ref cfi)
 {
-  output_cfi_directive (cfi);
+  if (dwarf2out_do_cfi_asm ())
+    output_cfi_directive (cfi);
 }
 
 /* Determine if we need to save and restore CFI information around
@@ -3085,23 +3093,24 @@ dwarf2out_cfi_begin_epilogue (rtx insn)
   /* And emulate the state save.  */
   gcc_assert (!cfa_remember.in_use);
   cfa_remember = cfa;
+  old_cfa_remember = old_cfa;
   cfa_remember.in_use = 1;
 }
 
 /* A "subroutine" of dwarf2out_cfi_begin_epilogue.  Emit the restore
    required.  */
 
-void
+static void
 dwarf2out_frame_debug_restore_state (void)
 {
   dw_cfi_ref cfi = new_cfi ();
-  const char *label = dwarf2out_cfi_label (false);
 
   cfi->dw_cfi_opc = DW_CFA_restore_state;
-  add_fde_cfi (label, cfi);
+  add_fde_cfi (cfi);
 
   gcc_assert (cfa_remember.in_use);
   cfa = cfa_remember;
+  old_cfa = old_cfa_remember;
   cfa_remember.in_use = 0;
 }
 
@@ -4296,7 +4305,8 @@ dwarf2out_frame_init (void)
      sake of lookup_cfa.  */
 
   /* On entry, the Canonical Frame Address is at SP.  */
-  dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
+  old_cfa.reg = INVALID_REGNUM;
+  dwarf2out_def_cfa (true, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
 
   if (targetm.debug_unwind_info () == UI_DWARF2
       || targetm.except_unwind_info (&global_options) == UI_DWARF2)
@@ -4353,10 +4363,6 @@ dwarf2out_switch_text_section (void)
     }
   have_multiple_function_sections = true;
 
-  /* Reset the current label on switching text sections, so that we
-     don't attempt to advance_loc4 between labels in different sections.  */
-  fde->dw_fde_current_label = NULL;
-
   /* There is no need to mark used sections when not debugging.  */
   if (cold_text_section != NULL)
     dwarf2out_note_section_used ();
Index: gcc/dwarf2out.h
===================================================================
--- gcc.orig/dwarf2out.h
+++ gcc/dwarf2out.h
@@ -19,9 +19,41 @@ along with GCC; see the file COPYING3.  
 <http://www.gnu.org/licenses/>.  */
 
 struct dw_cfi_struct;
+/* In dwarf2out.c */
+/* Interface of the DWARF2 unwind info support.  */
+
+/* Generate a new label for the CFI info to refer to.  */
+
+extern void dwarf2out_maybe_emit_cfi_label (void);
+
+/* Entry point to update the canonical frame address (CFA).  */
+
+extern void dwarf2out_def_cfa (bool, unsigned, HOST_WIDE_INT);
+
+/* Add the CFI for saving a register window.  */
+
+extern void dwarf2out_window_save (void);
+
+/* Entry point for saving a register to the stack.  */
+
+extern void dwarf2out_reg_save (unsigned, HOST_WIDE_INT);
+
+/* Entry point for saving the return address in the stack.  */
+
+extern void dwarf2out_return_save (HOST_WIDE_INT);
+
+/* Entry point for saving the return address in a register.  */
+
+extern void dwarf2out_return_reg (unsigned);
+
+/* Entry point for saving the first register into the second.  */
+
+extern void dwarf2out_reg_save_reg (rtx, rtx);
+
 extern void dwarf2out_decl (tree);
 extern void dwarf2out_frame_debug (rtx, bool);
 extern void dwarf2out_frame_debug_init (void);
+extern void dwarf2out_frame_debug_after_prologue (void);
 extern void dwarf2out_emit_cfi (struct dw_cfi_struct *);
 extern void dwarf2out_flush_queued_reg_saves (void);
 
Index: gcc/final.c
===================================================================
--- gcc.orig/final.c
+++ gcc/final.c
@@ -1588,6 +1588,11 @@ final_start_function (rtx first ATTRIBUT
   /* First output the function prologue: code to set up the stack frame.  */
   targetm.asm_out.function_prologue (file, get_frame_size ());
 
+#if defined (HAVE_prologue)
+  if (dwarf2out_do_frame ())
+    dwarf2out_frame_debug_after_prologue ();
+#endif
+
   /* If the machine represents the prologue as RTL, the profiling code must
      be emitted when NOTE_INSN_PROLOGUE_END is scanned.  */
 #ifdef HAVE_prologue
Index: gcc/target.def
===================================================================
--- gcc.orig/target.def
+++ gcc/target.def
@@ -1792,7 +1792,7 @@ DEFHOOK
 DEFHOOK
 (dwarf_handle_frame_unspec,
  "",
- void, (const char *label, rtx pattern, int index), NULL)
+ void, (rtx pattern, int index), NULL)
 
 /* ??? Documenting this hook requires a GFDL license grant.  */
 DEFHOOK_UNDOC
Index: gcc/tree.h
===================================================================
--- gcc.orig/tree.h
+++ gcc/tree.h
@@ -5424,37 +5424,6 @@ extern tree tree_overlaps_hard_reg_set (
 #endif
 
 
-/* In dwarf2out.c */
-/* Interface of the DWARF2 unwind info support.  */
-
-/* Generate a new label for the CFI info to refer to.  */
-
-extern char *dwarf2out_cfi_label (bool);
-
-/* Entry point to update the canonical frame address (CFA).  */
-
-extern void dwarf2out_def_cfa (const char *, unsigned, HOST_WIDE_INT);
-
-/* Add the CFI for saving a register window.  */
-
-extern void dwarf2out_window_save (const char *);
-
-/* Entry point for saving a register to the stack.  */
-
-extern void dwarf2out_reg_save (const char *, unsigned, HOST_WIDE_INT);
-
-/* Entry point for saving the return address in the stack.  */
-
-extern void dwarf2out_return_save (const char *, HOST_WIDE_INT);
-
-/* Entry point for saving the return address in a register.  */
-
-extern void dwarf2out_return_reg (const char *, unsigned);
-
-/* Entry point for saving the first register into the second.  */
-
-extern void dwarf2out_reg_save_reg (const char *, rtx, rtx);
-
 /* In tree-inline.c  */
 
 /* The type of a set of already-visited pointers.  Functions for creating
Index: gcc/doc/tm.texi
===================================================================
--- gcc.orig/doc/tm.texi
+++ gcc/doc/tm.texi
@@ -3203,7 +3203,7 @@ someone decided it was a good idea to us
 terminate the stack backtrace.  New ports should avoid this.
 @end defmac
 
-@deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (const char *@var{label}, rtx @var{pattern}, int @var{index})
+@deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (rtx @var{pattern}, int @var{index})
 This target hook allows the backend to emit frame-related insns that
 contain UNSPECs or UNSPEC_VOLATILEs.  The DWARF 2 call frame debugging
 info engine will invoke it on insns of the form
