This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PR 41469 followup: improve __builtin_stack_restore removal


> 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))
 	    {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]