[patch] Fix var-tracking with dynamic stack realignment on x86

Jakub Jelinek jakub@redhat.com
Mon May 23 18:17:00 GMT 2011


On Mon, May 23, 2011 at 11:33:42AM +0200, Eric Botcazou wrote:
> > Anyway, IMHO the desired outcome is that the 
> > parameters will have DW_OP_fbreg {0,4} as their location, so perhaps the
> > DRAP register needs to be remapped somehow during adjust_insn.
> 
> So you don't care about their location during the prologue?

Here is an alternative, almost completely untested, patch, which
uses DW_OP_fbreg <N> for the arguments of dynamically realigned functions.
draptest.c now works...

2011-05-23  Jakub Jelinek  <jakub@redhat.com>

	* var-tracking.c (vt_add_function_parameter): Remap incoming
	MEMs with crtl->args.internal_arg_pointer based address
	if stack_realign_drap to arg_pointer_rtx.
	(vt_init_cfa_base): Add equate argument, don't equate cfa_base_rtx
	to hfp/sp if it is false.
	(vt_initialize): Adjust vt_init_cfa_base callers, don't call
	vt_init_cfa_base if frame_pointer_needed, but fp_cfa_offset is -1,
	set fp_cfa_offset to -1 if fp/argp hasn't been eliminated.

	* gcc.dg/guality/draptest.c: New test.

--- gcc/var-tracking.c.jj	2011-05-23 10:48:19.000000000 +0200
+++ gcc/var-tracking.c	2011-05-23 18:30:18.000000000 +0200
@@ -8449,6 +8449,8 @@ vt_get_decl_and_offset (rtx rtl, tree *d
   return false;
 }
 
+static void vt_init_cfa_base (bool);
+
 /* Insert function parameter PARM in IN and OUT sets of ENTRY_BLOCK.  */
 
 static void
@@ -8471,6 +8473,46 @@ vt_add_function_parameter (tree parm)
   if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
     return;
 
+  if (MEM_P (incoming)
+      && stack_realign_drap
+      && frame_pointer_needed
+      && crtl->stack_realign_tried
+      && (XEXP (incoming, 0) == crtl->args.internal_arg_pointer
+	  || (GET_CODE (XEXP (incoming, 0)) == PLUS
+	      && XEXP (XEXP (incoming, 0), 0)
+		 == crtl->args.internal_arg_pointer
+	      && CONST_INT_P (XEXP (XEXP (incoming, 0), 1)))))
+    {
+      rtx new_addr;
+      if (cfa_base_rtx == NULL_RTX)
+	{
+	  rtx reg, elim;
+
+#ifdef FRAME_POINTER_CFA_OFFSET
+	  reg = frame_pointer_rtx;
+#else
+	  reg = arg_pointer_rtx;
+#endif
+	  elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
+	  if (elim != reg)
+	    {
+	      if (GET_CODE (elim) == PLUS)
+		elim = XEXP (elim, 0);
+	      if (elim == hard_frame_pointer_rtx)
+		vt_init_cfa_base (false);
+	    }
+	}
+
+      if (cfa_base_rtx)
+	{
+	  HOST_WIDE_INT off = -FIRST_PARM_OFFSET (current_function_decl);
+	  new_addr = plus_constant (arg_pointer_rtx,
+				    (GET_CODE (XEXP (incoming, 0)) == PLUS
+				    ? INTVAL (XEXP (XEXP (incoming, 0), 1))
+				    : 0) + off);
+	  incoming = replace_equiv_address_nv (incoming, new_addr);
+	}
+    }
   if (!vt_get_decl_and_offset (incoming, &decl, &offset))
     {
       if (REG_P (incoming) || MEM_P (incoming))
@@ -8698,7 +8740,7 @@ note_register_arguments (rtx insn)
    has been eliminated.  */
 
 static void
-vt_init_cfa_base (void)
+vt_init_cfa_base (bool equate)
 {
   cselib_val *val;
 
@@ -8720,9 +8762,10 @@ vt_init_cfa_base (void)
 
   /* Tell alias analysis that cfa_base_rtx should share
      find_base_term value with stack pointer or hard frame pointer.  */
-  vt_equate_reg_base_value (cfa_base_rtx,
-			    frame_pointer_needed
-			    ? hard_frame_pointer_rtx : stack_pointer_rtx);
+  if (equate)
+    vt_equate_reg_base_value (cfa_base_rtx,
+			      frame_pointer_needed
+			      ? hard_frame_pointer_rtx : stack_pointer_rtx);
   val = cselib_lookup_from_insn (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1,
 				 VOIDmode, get_insns ());
   preserve_value (val);
@@ -8814,7 +8857,7 @@ vt_initialize (void)
 	  if (GET_CODE (elim) == PLUS)
 	    elim = XEXP (elim, 0);
 	  if (elim == stack_pointer_rtx)
-	    vt_init_cfa_base ();
+	    vt_init_cfa_base (true);
 	}
     }
   else if (!crtl->stack_realign_tried)
@@ -8841,6 +8884,8 @@ vt_initialize (void)
 	  else
 	    prologue_bb = single_succ (ENTRY_BLOCK_PTR);
 	}
+      else
+	fp_cfa_offset = -1;
     }
   if (frame_pointer_needed)
     {
@@ -8944,9 +8989,10 @@ vt_initialize (void)
 		  if (bb == prologue_bb
 		      && hard_frame_pointer_adjustment == -1
 		      && RTX_FRAME_RELATED_P (insn)
-		      && fp_setter (insn))
+		      && fp_setter (insn)
+		      && fp_cfa_offset != -1)
 		    {
-		      vt_init_cfa_base ();
+		      vt_init_cfa_base (true);
 		      hard_frame_pointer_adjustment = fp_cfa_offset;
 		    }
 		}
--- gcc/testsuite/gcc.dg/guality/draptest.c.jj	2011-05-23 18:32:16.000000000 +0200
+++ gcc/testsuite/gcc.dg/guality/draptest.c	2011-05-23 14:55:25.000000000 +0200
@@ -0,0 +1,27 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-g -mforce-drap" } */
+
+volatile int v;
+
+__attribute__((noinline, noclone)) int
+bar (int a, int b)
+{
+  int t = 0;
+  asm volatile ("" : "+c" (t));
+  return 0;
+}
+
+__attribute__((noinline, noclone)) int
+foo (int a, int b)
+{
+  __attribute__((aligned (32))) int c = bar (a, b);
+  v++;				/* { dg-final { gdb-test 18 "a" "5" } } */
+  return a + b + c;		/* { dg-final { gdb-test 18 "b" "6" } } */
+}
+
+int
+main ()
+{
+  foo (5, 6);
+  return 0;
+}


	Jakub



More information about the Gcc-patches mailing list