Comments
Patch
@@ -800,6 +800,9 @@ dwarf2out_cfi_label (bool force)
/* True if remember_state should be emitted before following CFI directive. */
static bool emit_cfa_remember;
+/* True if any CFI directives were emitted at the current insn. */
+static bool any_cfis_emitted;
+
/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
or to the CIE if LABEL is NULL. */
@@ -879,6 +882,7 @@ add_fde_cfi (const char *label, dw_cfi_r
output_cfi_directive (cfi);
list_head = &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
@@ -916,6 +920,7 @@ add_fde_cfi (const char *label, dw_cfi_r
}
list_head = &fde->dw_fde_cfi;
+ any_cfis_emitted = true;
}
add_cfi (list_head, cfi);
@@ -2745,6 +2750,7 @@ dwarf2out_frame_debug (rtx insn, bool af
}
label = dwarf2out_cfi_label (false);
+ any_cfis_emitted = false;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
switch (REG_NOTE_KIND (note))
@@ -2830,7 +2836,11 @@ dwarf2out_frame_debug (rtx insn, bool af
break;
}
if (handled_one)
- return;
+ {
+ if (any_cfis_emitted)
+ dwarf2out_flush_queued_reg_saves ();
+ return;
+ }
insn = PATTERN (insn);
found:
@@ -2839,7 +2849,7 @@ dwarf2out_frame_debug (rtx insn, bool af
/* 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 (clobbers_queued_reg_save (insn))
+ if (any_cfis_emitted || clobbers_queued_reg_save (insn))
dwarf2out_flush_queued_reg_saves ();
}
Hi! Ulrich recently pointed out that with -gdwarf2-cfi-asm (the default with not too obsolete binutils) the unwind info is unnecessarily large. E.g. .cfi_startproc pushq %rbx .cfi_def_cfa_offset 16 movq %rdi, %rbx .cfi_offset 3, -16 /* asm using %rbx */ popq %rbx .cfi_def_cfa_offset 8 ret .cfi_endproc there is an unnecessary DW_CFA_advance_loc* - the pushq insn both adjusts CFA and saves the %rbx register. When emitting .eh_frame by hand, we emit the queued register saves at last_reg_save_label instead of current spot, but when emitting .cfi_* directives we don't have that luxury when this processing is done during insn output. The patch below flushes all queued register saves not just on jumps/calls/barriers or insns that clobber any of the registers that have register saves queued, but any time we already had to emit some directives at the current spot. On i686-linux cc1plus, the .eh_frame size went down from 771220 to 757260. readelf -wf ../objbefore/gcc/cc1plus | grep DW_CFA_ | egrep -v DW_CFA_nop | wc -l 317205 readelf -wf ../objafter/gcc/cc1plus | grep DW_CFA_ | egrep -v DW_CFA_nop | wc -l 308218 readelf -wf ../objbefore/gcc/cc1plus | grep DW_CFA_ | egrep -v DW_CFA_'(nop|advance)' | wc -l 197091 readelf -wf ../objafter/gcc/cc1plus | grep DW_CFA_ | egrep -v DW_CFA_'(nop|advance)' | wc -l 197102 The 11 non-advance/nop ops addition is due to the changes in dwarf2out.c, on dwarf2out.o only. Similarly on x86_64-linux cc1plus, size went down from 766028 to 754532. readelf -wf ../objbefore/gcc/cc1plus | grep DW_CFA | egrep -v DW_CFA_nop | wc -l 270890 readelf -wf ../objafter/gcc/cc1plus | grep DW_CFA | egrep -v DW_CFA_nop | wc -l 255556 readelf -wf ../objbefore/gcc/cc1plus | grep DW_CFA | egrep -v DW_CFA_'(nop|advance)' | wc -l 152807 readelf -wf ../objafter/gcc/cc1plus | grep DW_CFA | egrep -v DW_CFA_'(nop|advance)' | wc -l 152816 Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2010-09-20 Jakub Jelinek <jakub@redhat.com> * dwarf2out.c (any_cfis_emitted): New static variable. (add_fde_cfi): Set it. (dwarf2out_frame_debug): Clear it before processing, if it is set afterwards, flush any queued reg saves. Jakub