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  <ja...@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

Reply via email to