This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PR 41469 followup: improve __builtin_stack_restore removal
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 9 Nov 2009 00:53:47 +0100
- Subject: Re: PR 41469 followup: improve __builtin_stack_restore removal
- References: <4ABFF54A.8040003@redhat.com> <200911042306.52679.ebotcazou@adacore.com> <4AF1FFD8.9090903@redhat.com>
> It's only wrong if the RESX resolves within the function, i.e. the block
> has successors. If there are no successors to the bb, then we're about
> to (effectively) perform a longjmp, and there's no point in keeping the
> stack restore.
You're right, and that the problem arises on x86-64 but not on i586 should
have prompted me to further investigate.
It turns out that SP is set to a bogus value on entry to the cleanup because
of a bogus DW_CFA_GNU_args_size entry in the FDE at -O. Insns that adjust
the stack but aren't FRAME_RELATED_P are processed by dwarf2out_frame_debug
and discarded for ACCUMULATE_OUTGOING_ARGS targets:
if (! RTX_FRAME_RELATED_P (insn))
{
if (!ACCUMULATE_OUTGOING_ARGS)
dwarf2out_stack_adjust (insn, after_p);
return;
}
But if one of them is merged in a FRAME_RELATED_P insn by the csa pass, it is
further processed by dwarf2out_frame_debug_expr:
for (par_index = 0; par_index < limit; par_index++)
{
elem = XVECEXP (expr, 0, par_index);
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);
else if (GET_CODE (elem) == SET
&& par_index != 0
&& !RTX_FRAME_RELATED_P (elem))
{
/* Stack adjustment combining might combine some post-prologue
stack adjustment into a prologue stack adjustment. */
HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0);
if (offset != 0)
dwarf2out_args_size_adjust (offset, label);
}
}
Now the arg size adjustment is recorded whatever ACCUMULATE_OUTGOING_ARGS,
thus leading to a bogus discrepancy.
Hence the attached patch which fixes the bug as well as move some related
functions in dwarf2out.c around. Tested on x86-64, OK for mainline?
2009-11-08 Eric Botcazou <ebotcazou@adacore.com>
* tree.h (dwarf2out_args_size): Delete.
* dwarf2out.c (dwarf2out_args_size): Make static and move around.
(dwarf2out_args_size_adjust): Delete prototype and move around.
(dwarf2out_frame_debug_expr): Do not record arg size adjustments for
ACCUMULATE_OUTGOING_ARGS targets.
--
Eric Botcazou
Index: tree.h
===================================================================
--- tree.h (revision 153889)
+++ tree.h (working copy)
@@ -5161,11 +5161,6 @@ extern void dwarf2out_def_cfa (const cha
extern void dwarf2out_window_save (const char *);
-/* Add a CFI to update the running total of the size of arguments pushed
- onto the stack. */
-
-extern void dwarf2out_args_size (const char *, HOST_WIDE_INT);
-
/* Entry point for saving a register to the stack. */
extern void dwarf2out_reg_save (const char *, unsigned, HOST_WIDE_INT);
Index: dwarf2out.c
===================================================================
--- dwarf2out.c (revision 153889)
+++ dwarf2out.c (working copy)
@@ -470,8 +470,6 @@ static void output_cfi (dw_cfi_ref, dw_f
static void output_cfi_directive (dw_cfi_ref);
static void output_call_frame_info (int);
static void dwarf2out_note_section_used (void);
-static void dwarf2out_stack_adjust (rtx, bool);
-static void dwarf2out_args_size_adjust (HOST_WIDE_INT, const char *);
static void flush_queued_reg_saves (void);
static bool clobbers_queued_reg_save (const_rtx);
static void dwarf2out_frame_debug_expr (rtx, const char *);
@@ -1157,25 +1155,6 @@ dwarf2out_window_save (const char *label
add_fde_cfi (label, cfi);
}
-/* Add a CFI to update the running total of the size of arguments
- pushed onto the stack. */
-
-void
-dwarf2out_args_size (const char *label, HOST_WIDE_INT size)
-{
- dw_cfi_ref cfi;
-
- if (size == old_args_size)
- return;
-
- old_args_size = size;
-
- 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);
-}
-
/* Entry point for saving a register to the stack. REG is the GCC register
number. LABEL and OFFSET are passed to reg_save. */
@@ -1526,6 +1505,48 @@ compute_barrier_args_size (void)
VEC_free (rtx, heap, next);
}
+/* Add a CFI to update the running total of the size of arguments
+ pushed onto the stack. */
+
+static void
+dwarf2out_args_size (const char *label, HOST_WIDE_INT size)
+{
+ dw_cfi_ref cfi;
+
+ if (size == old_args_size)
+ return;
+
+ old_args_size = size;
+
+ 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);
+}
+
+/* Adjust args_size based on stack adjustment OFFSET. */
+
+static void
+dwarf2out_args_size_adjust (HOST_WIDE_INT offset, const char *label)
+{
+ if (cfa.reg == STACK_POINTER_REGNUM)
+ cfa.offset += offset;
+
+ if (cfa_store.reg == STACK_POINTER_REGNUM)
+ cfa_store.offset += offset;
+
+#ifndef STACK_GROWS_DOWNWARD
+ offset = -offset;
+#endif
+
+ args_size += offset;
+ if (args_size < 0)
+ args_size = 0;
+
+ def_cfa_1 (label, &cfa);
+ if (flag_asynchronous_unwind_tables)
+ dwarf2out_args_size (label, args_size);
+}
/* Check INSN to see if it looks like a push or a stack adjustment, and
make a note of it if it does. EH uses this information to find out how
@@ -1619,30 +1640,6 @@ dwarf2out_stack_adjust (rtx insn, bool a
dwarf2out_args_size_adjust (offset, label);
}
-/* Adjust args_size based on stack adjustment OFFSET. */
-
-static void
-dwarf2out_args_size_adjust (HOST_WIDE_INT offset, const char *label)
-{
- if (cfa.reg == STACK_POINTER_REGNUM)
- cfa.offset += offset;
-
- if (cfa_store.reg == STACK_POINTER_REGNUM)
- cfa_store.offset += offset;
-
-#ifndef STACK_GROWS_DOWNWARD
- offset = -offset;
-#endif
-
- args_size += offset;
- if (args_size < 0)
- args_size = 0;
-
- def_cfa_1 (label, &cfa);
- if (flag_asynchronous_unwind_tables)
- dwarf2out_args_size (label, args_size);
-}
-
#endif
/* We delay emitting a register save until either (a) we reach the end
@@ -2209,7 +2206,8 @@ dwarf2out_frame_debug_expr (rtx expr, co
&& (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
&& (RTX_FRAME_RELATED_P (elem) || par_index == 0))
dwarf2out_frame_debug_expr (elem, label);
- else if (GET_CODE (elem) == SET
+ else if (!ACCUMULATE_OUTGOING_ARGS
+ && GET_CODE (elem) == SET
&& par_index != 0
&& !RTX_FRAME_RELATED_P (elem))
{