[PATCH] Don't mark set of vDRAP from DRAP as frame related (PR debug/43290)

Jakub Jelinek jakub@redhat.com
Wed Mar 10 11:10:00 GMT 2010


On Tue, Mar 09, 2010 at 10:41:30AM -0800, Richard Henderson wrote:
> On 03/08/2010 02:32 PM, Jakub Jelinek wrote:
> > 	PR debug/43290
> > 	* config/i386/i386.c (ix86_get_drap_rtx): Don't set
> > 	RTX_FRAME_RELATED_P.
> > 
> > 	* g++.dg/eh/unwind2.C: New test.
> 
> Ok.

Unfortunately, there was a reason for the /f flag there, just unfortunately
without a testcase in GCC testsuite, as pointed out by H.J.  The problem
is when emitting debug info at -O0 for stack arguments, they might use the
vDRAP register as base.

I think the guessword is already extremely fragile and guessing which of the
stores if vDRAP ends up to be a MEM is the vDRAP assignment and which is the
prologue save is not going to be ever robust.

So this patch instead creates a reg note for it.  The note is only needed
for -O0 - at -O1+ the arguments will be tracked properly by var-tracking
and combiner or other optimization passes are going to delete or modify the
vDRAP = DRAP insn anyway.  Plus for -O1+ we really shouldn't blindly replace
DW_OP_breg0 (if vDRAP is %rax e.g.) with DW_OP_fbreg, when the vDRAP might
be live only in a few insns and then reused for something completely else.

This patch also adds the testcases from PR36728, so that we don't regress on
this again.  The patch fixes -O0 regressions on the testcases, for -O1+ it
worked well before and after thanks to var-tracking.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2010-03-10  Jakub Jelinek  <jakub@redhat.com>

	PR debug/43290
	* reg-notes.def (REG_CFA_SET_VDRAP): New note.
	* dwarf2out.c (dwarf2out_frame_debug_expr): Remove rule 20 - setting
	of fde->vdrap_reg.
	(dwarf2out_frame_debug): Handle REG_CFA_SET_VDRAP note.
	(based_loc_descr): Only express drap or vdrap regno based expressions
	using DW_OP_fbreg when not optimizing.
	* config/i386/i386.c (ix86_get_drap_rtx): When not optimizing,
	make the vDRAP = DRAP assignment RTX_FRAME_RELATED_P and add
	REG_CFA_SET_VDRAP note.

	PR debug/36728
	* gcc.dg/guality/pr36728-1.c: New test.
	* gcc.dg/guality/pr36728-2.c: New test.

--- gcc/reg-notes.def.jj	2009-05-30 10:13:04.000000000 +0200
+++ gcc/reg-notes.def	2010-03-10 08:46:11.000000000 +0100
@@ -153,6 +153,11 @@ REG_NOTE (CFA_REGISTER)
    first pattern is the register to be restored.  */
 REG_NOTE (CFA_RESTORE)
 
+/* Attached to insn that is RTX_FRAME_RELATED_P, marks insn that sets
+   vDRAP from DRAP.  If vDRAP is a register, vdrap_reg is initalized
+   to the argument, if it is a MEM, it is ignored.  */
+REG_NOTE (CFA_SET_VDRAP)
+
 /* Indicates that REG holds the exception context for the function.
    This context is shared by inline functions, so the code to acquire
    the real exception context is delayed until after inlining.  */
--- gcc/dwarf2out.c.jj	2010-03-10 08:42:55.000000000 +0100
+++ gcc/dwarf2out.c	2010-03-10 08:46:39.000000000 +0100
@@ -2160,15 +2160,7 @@ dwarf2out_frame_debug_cfa_restore (rtx r
                && cfa.indirect == 0
                && cfa.reg != HARD_FRAME_POINTER_REGNUM
   effects: Use DW_CFA_def_cfa_expression to define cfa
-  	   cfa.reg == fde->drap_reg
-
-  Rule 20:
-  (set reg fde->drap_reg)
-  constraints: fde->vdrap_reg == INVALID_REGNUM
-  effects: fde->vdrap_reg = reg.
-  (set mem fde->drap_reg)
-  constraints: fde->drap_reg_saved == 1
-  effects: none.  */
+  	   cfa.reg == fde->drap_reg  */
 
 static void
 dwarf2out_frame_debug_expr (rtx expr, const char *label)
@@ -2239,24 +2231,6 @@ dwarf2out_frame_debug_expr (rtx expr, co
 
   fde = current_fde ();
 
-  if (REG_P (src)
-      && fde
-      && fde->drap_reg == REGNO (src)
-      && (fde->drap_reg_saved
-	  || REG_P (dest)))
-    {
-      /* Rule 20 */
-      /* If we are saving dynamic realign argument pointer to a
-	 register, the destination is virtual dynamic realign
-	 argument pointer.  It may be used to access argument.  */
-      if (REG_P (dest))
-	{
-	  gcc_assert (fde->vdrap_reg == INVALID_REGNUM);
-	  fde->vdrap_reg = REGNO (dest);
-	}
-      return;
-    }
-
   switch (GET_CODE (dest))
     {
     case REG:
@@ -2781,6 +2755,20 @@ dwarf2out_frame_debug (rtx insn, bool af
 	handled_one = true;
 	break;
 
+      case REG_CFA_SET_VDRAP:
+	n = XEXP (note, 0);
+	if (REG_P (n))
+	  {
+	    dw_fde_ref fde = current_fde ();
+	    gcc_assert (fde
+			&& fde->drap_reg != INVALID_REGNUM
+			&& fde->vdrap_reg == INVALID_REGNUM);
+	    if (REG_P (n))
+	      fde->vdrap_reg = REGNO (n);
+	  }
+	handled_one = true;
+	break;
+
       default:
 	break;
       }
@@ -12736,13 +12724,18 @@ based_loc_descr (rtx reg, HOST_WIDE_INT 
 	  return new_loc_descr (DW_OP_fbreg, offset, 0);
 	}
     }
-  else if (fde
+  else if (!optimize
+	   && fde
 	   && fde->drap_reg != INVALID_REGNUM
 	   && (fde->drap_reg == REGNO (reg)
 	       || fde->vdrap_reg == REGNO (reg)))
     {
       /* Use cfa+offset to represent the location of arguments passed
-	 on stack when drap is used to align stack.  */
+	 on the stack when drap is used to align stack.
+	 Only do this when not optimizing, for optimized code var-tracking
+	 is supposed to track where the arguments live and the register
+	 used as vdrap or drap in some spot might be used for something
+	 else in other part of the routine.  */
       return new_loc_descr (DW_OP_fbreg, offset, 0);
     }
 
--- gcc/config/i386/i386.c.jj	2010-03-10 08:42:54.000000000 +0100
+++ gcc/config/i386/i386.c	2010-03-10 08:52:52.000000000 +0100
@@ -8382,7 +8382,7 @@ ix86_get_drap_rtx (void)
       unsigned int regno = find_drap_reg ();
       rtx drap_vreg;
       rtx arg_ptr;
-      rtx seq;
+      rtx seq, insn;
 
       arg_ptr = gen_rtx_REG (Pmode, regno);
       crtl->drap_reg = arg_ptr;
@@ -8391,8 +8391,13 @@ ix86_get_drap_rtx (void)
       drap_vreg = copy_to_reg (arg_ptr);
       seq = get_insns ();
       end_sequence ();
-
-      emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
+      
+      insn = emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
+      if (!optimize)
+	{
+	  add_reg_note (insn, REG_CFA_SET_VDRAP, drap_vreg);
+	  RTX_FRAME_RELATED_P (insn) = 1;
+	}
       return drap_vreg;
     }
   else
--- gcc/testsuite/gcc.dg/guality/pr36728-1.c.jj	2010-03-10 08:46:11.000000000 +0100
+++ gcc/testsuite/gcc.dg/guality/pr36728-1.c	2010-03-10 08:46:11.000000000 +0100
@@ -0,0 +1,43 @@
+/* PR debug/36728 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+int __attribute__((noinline))
+foo (int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7)
+{
+  char *x = __builtin_alloca (arg7);
+  int __attribute__ ((aligned(32))) y;
+
+  y = 2;
+  asm volatile ("" : "=m" (y) : "m" (y));
+  x[0] = 25;
+  asm volatile ("" : "=m" (x[0]) : "m" (x[0]));
+  return y;
+}
+
+/* { dg-final { gdb-test 12 "arg1" "1" } } */
+/* { dg-final { gdb-test 12 "arg2" "2" } } */
+/* { dg-final { gdb-test 12 "arg3" "3" } } */
+/* { dg-final { gdb-test 12 "arg4" "4" } } */
+/* { dg-final { gdb-test 12 "arg5" "5" } } */
+/* { dg-final { gdb-test 12 "arg6" "6" } } */
+/* { dg-final { gdb-test 12 "arg7" "30" } } */
+/* { dg-final { gdb-test 12 "y" "2" } } */
+/* { dg-final { gdb-test 14 "arg1" "1" } } */
+/* { dg-final { gdb-test 14 "arg2" "2" } } */
+/* { dg-final { gdb-test 14 "arg3" "3" } } */
+/* { dg-final { gdb-test 14 "arg4" "4" } } */
+/* { dg-final { gdb-test 14 "arg5" "5" } } */
+/* { dg-final { gdb-test 14 "arg6" "6" } } */
+/* { dg-final { gdb-test 14 "arg7" "30" } } */
+/* { dg-final { gdb-test 14 "*x" "(char) 25" } } */
+/* { dg-final { gdb-test 14 "y" "2" } } */
+
+int
+main ()
+{
+  int l = 0;
+  asm volatile ("" : "=r" (l) : "0" (l));
+  foo (l + 1, l + 2, l + 3, l + 4, l + 5, l + 6, l + 30);
+  return 0;
+}
--- gcc/testsuite/gcc.dg/guality/pr36728-2.c.jj	2010-03-10 08:46:11.000000000 +0100
+++ gcc/testsuite/gcc.dg/guality/pr36728-2.c	2010-03-10 08:46:11.000000000 +0100
@@ -0,0 +1,43 @@
+/* PR debug/36728 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+int __attribute__((noinline))
+foo (int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7)
+{
+  char x[30];
+  int __attribute__ ((aligned(32))) y;
+
+  y = 2;
+  asm volatile ("" : "=m" (y) : "m" (y));
+  x[0] = 25;
+  asm volatile ("" : "=m" (x[0]) : "m" (x[0]));
+  return y;
+}
+
+/* { dg-final { gdb-test 12 "arg1" "1" } } */
+/* { dg-final { gdb-test 12 "arg2" "2" } } */
+/* { dg-final { gdb-test 12 "arg3" "3" } } */
+/* { dg-final { gdb-test 12 "arg4" "4" } } */
+/* { dg-final { gdb-test 12 "arg5" "5" } } */
+/* { dg-final { gdb-test 12 "arg6" "6" } } */
+/* { dg-final { gdb-test 12 "arg7" "30" } } */
+/* { dg-final { gdb-test 12 "y" "2" } } */
+/* { dg-final { gdb-test 14 "arg1" "1" } } */
+/* { dg-final { gdb-test 14 "arg2" "2" } } */
+/* { dg-final { gdb-test 14 "arg3" "3" } } */
+/* { dg-final { gdb-test 14 "arg4" "4" } } */
+/* { dg-final { gdb-test 14 "arg5" "5" } } */
+/* { dg-final { gdb-test 14 "arg6" "6" } } */
+/* { dg-final { gdb-test 14 "arg7" "30" } } */
+/* { dg-final { gdb-test 14 "*x" "(char) 25" } } */
+/* { dg-final { gdb-test 14 "y" "2" } } */
+
+int
+main ()
+{
+  int l = 0;
+  asm volatile ("" : "=r" (l) : "0" (l));
+  foo (l + 1, l + 2, l + 3, l + 4, l + 5, l + 6, l + 30);
+  return 0;
+}


	Jakub



More information about the Gcc-patches mailing list