Hi!

This patch fixes a few problems:
1) on arm bootstrap fails, because expansion creates ENTRY_VALUE
   of a MEM with virtual reg address, which then is changed for
   ap + constant and dwarf2out doesn't expect that.
   As in most passes ENTRY_VALUE is treated like a black box,
   we shouldn't accept anything but hard registers or
   MEMs with hard register addresses
2) DW_OP_GNU_entry_value 2 <DW_OP_fbreg 16> is something we should
   avoid
3) the var-tracking and cselib changes were added to make sure
   var-tracking can easily map ENTRY_VALUEs created by cfgexpand
   back to the canonical VALUEs holding the parameter.  This means
   they can expand even to the original argument registers if they
   haven't been modified or at least in the part of the function
   where they haven't been modified.  E.g. on x86_64-linux
   on the attached testcase we no longer generate any DW_OP_GNU_entry_value
   ops, as the registers aren't clobbered.

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

2011-03-20  Jakub Jelinek  <ja...@redhat.com>

        PR debug/48203
        * cfgexpand.c (expand_debug_expr) <case SSA_NAME>: Only
        create ENTRY_VALUE if incoming or address of incoming's MEM
        is a hard REG.
        * dwarf2out.c (mem_loc_descriptor): Don't emit
        DW_OP_GNU_entry_value of DW_OP_fbreg.
        * var-tracking.c (vt_add_function_parameter): Ensure cselib_lookup
        on ENTRY_VALUE is able to find the canonical parameter VALUE.
        * cselib.c (rtx_equal_for_cselib_1) <case ENTRY_VALUE>: Use
        rtx_equal_p instead of rtx_equal_for_cselib_1 to compare
        ENTRY_VALUE_EXPs.
        (cselib_hash_rtx) <case ENTRY_VALUE>: If ENTRY_VALUE_EXP
        is a REG_P or MEM_P with REG_P address, compute hash directly
        instead of calling cselib_hash_rtx on ENTRY_VALUE_EXP.
        (preserve_only_constants): Don't clear VALUES forwaring
        ENTRY_VALUE to some other VALUE.

        * gcc.dg/pr48203.c: New test.

--- gcc/cfgexpand.c.jj  2011-03-17 09:37:59.000000000 +0100
+++ gcc/cfgexpand.c     2011-03-19 17:45:32.000000000 +0100
@@ -3182,8 +3182,10 @@ expand_debug_expr (tree exp)
                    rtx incoming = DECL_INCOMING_RTL (SSA_NAME_VAR (exp));
                    if (incoming
                        && GET_MODE (incoming) != BLKmode
-                       && (REG_P (incoming)
-                           || (MEM_P (incoming) && REG_P (XEXP (incoming, 
0)))))
+                       && ((REG_P (incoming) && HARD_REGISTER_P (incoming))
+                           || (MEM_P (incoming)
+                               && REG_P (XEXP (incoming, 0))
+                               && HARD_REGISTER_P (XEXP (incoming, 0)))))
                      {
                        op0 = gen_rtx_ENTRY_VALUE (GET_MODE (incoming));
                        ENTRY_VALUE_EXP (op0) = incoming;
--- gcc/dwarf2out.c.jj  2011-03-19 17:28:32.000000000 +0100
+++ gcc/dwarf2out.c     2011-03-19 17:48:42.000000000 +0100
@@ -13877,7 +13877,7 @@ mem_loc_descriptor (rtx rtl, enum machin
          dw_loc_descr_ref ref
            = mem_loc_descriptor (ENTRY_VALUE_EXP (rtl), GET_MODE (rtl),
                                  VAR_INIT_STATUS_INITIALIZED);
-         if (ref == NULL)
+         if (ref == NULL || ref->dw_loc_opc == DW_OP_fbreg)
            return NULL;
          mem_loc_result->dw_loc_oprnd1.v.val_loc = ref;
        }
--- gcc/var-tracking.c.jj       2011-03-19 16:20:26.000000000 +0100
+++ gcc/var-tracking.c  2011-03-19 18:49:48.000000000 +0100
@@ -8472,7 +8472,7 @@ vt_add_function_parameter (tree parm)
                         VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
       if (dv_is_value_p (dv))
        {
-         cselib_val *val = CSELIB_VAL_PTR (dv_as_value (dv));
+         cselib_val *val = CSELIB_VAL_PTR (dv_as_value (dv)), *val2;
          struct elt_loc_list *el;
          el = (struct elt_loc_list *)
            ggc_alloc_cleared_atomic (sizeof (*el));
@@ -8481,6 +8481,23 @@ vt_add_function_parameter (tree parm)
          ENTRY_VALUE_EXP (el->loc) = incoming;
          el->setting_insn = get_insns ();
          val->locs = el;
+         val2 = cselib_lookup_from_insn (el->loc, GET_MODE (incoming),
+                                         true, VOIDmode, get_insns ());
+         if (val2
+             && val2 != val
+             && val2->locs
+             && rtx_equal_p (val2->locs->loc, el->loc))
+           {
+             struct elt_loc_list *el2;
+
+             preserve_value (val2);
+             el2 = (struct elt_loc_list *)
+               ggc_alloc_cleared_atomic (sizeof (*el2));
+             el2->next = val2->locs;
+             el2->loc = dv_as_value (dv);
+             el2->setting_insn = get_insns ();
+             val2->locs = el2;
+           }
          if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
              && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))
            {
@@ -8499,6 +8516,24 @@ vt_add_function_parameter (tree parm)
                  ENTRY_VALUE_EXP (el->loc) = mem;
                  el->setting_insn = get_insns ();
                  val->locs = el;
+                 val2 = cselib_lookup_from_insn (el->loc, GET_MODE (incoming),
+                                                 true, VOIDmode,
+                                                 get_insns ());
+                 if (val2
+                     && val2 != val
+                     && val2->locs
+                     && rtx_equal_p (val2->locs->loc, el->loc))
+                   {
+                     struct elt_loc_list *el2;
+
+                     preserve_value (val2);
+                     el2 = (struct elt_loc_list *)
+                       ggc_alloc_cleared_atomic (sizeof (*el2));
+                     el2->next = val2->locs;
+                     el2->loc = val->val_rtx;
+                     el2->setting_insn = get_insns ();
+                     val2->locs = el2;
+                   }
                }
            }
        }
--- gcc/cselib.c.jj     2011-03-16 18:30:12.000000000 +0100
+++ gcc/cselib.c        2011-03-19 19:58:54.000000000 +0100
@@ -329,6 +329,12 @@ preserve_only_constants (void **x, void 
            return 1;
        }
     }
+  if (v->locs != NULL
+      && v->locs->next != NULL
+      && v->locs->next->next == NULL
+      && GET_CODE (v->locs->next->loc) == ENTRY_VALUE
+      && GET_CODE (v->locs->loc) == VALUE)
+    return 1;
 
   htab_clear_slot (cselib_hash_table, x);
   return 1;
@@ -804,8 +810,7 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, en
             == DEBUG_IMPLICIT_PTR_DECL (y);
 
     case ENTRY_VALUE:
-      return rtx_equal_for_cselib_1 (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y),
-                                    memmode);
+      return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
 
     case LABEL_REF:
       return XEXP (x, 0) == XEXP (y, 0);
@@ -954,7 +959,17 @@ cselib_hash_rtx (rtx x, int create, enum
       return hash ? hash : (unsigned int) DEBUG_IMPLICIT_PTR;
 
     case ENTRY_VALUE:
-      hash += cselib_hash_rtx (ENTRY_VALUE_EXP (x), create, memmode);
+      if (REG_P (ENTRY_VALUE_EXP (x)))
+       hash += (unsigned int) REG
+               + (unsigned int) GET_MODE (ENTRY_VALUE_EXP (x))
+               + (unsigned int) REGNO (ENTRY_VALUE_EXP (x));
+      else if (MEM_P (ENTRY_VALUE_EXP (x))
+              && REG_P (XEXP (ENTRY_VALUE_EXP (x), 0)))
+       hash += (unsigned int) MEM
+               + (unsigned int) GET_MODE (XEXP (ENTRY_VALUE_EXP (x), 0))
+               + (unsigned int) REGNO (XEXP (ENTRY_VALUE_EXP (x), 0));
+      else
+       hash += cselib_hash_rtx (ENTRY_VALUE_EXP (x), create, memmode);
       return hash ? hash : (unsigned int) ENTRY_VALUE;
 
     case CONST_INT:
--- gcc/testsuite/gcc.dg/pr48203.c.jj   2011-03-19 18:06:29.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr48203.c      2011-03-19 18:06:01.000000000 +0100
@@ -0,0 +1,51 @@
+/* PR debug/48203 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+
+volatile int v;
+
+void
+foo (long a, long b, long c, long d, long e, long f, long g, long h,
+     long i, long j, long k, long l, long m, long n, long o, long p)
+{
+  long a2 = a;
+  long b2 = b;
+  long c2 = c;
+  long d2 = d;
+  long e2 = e;
+  long f2 = f;
+  long g2 = g;
+  long h2 = h;
+  long i2 = i;
+  long j2 = j;
+  long k2 = k;
+  long l2 = l;
+  long m2 = m;
+  long n2 = n;
+  long o2 = o;
+  long p2 = p;
+  v++;
+}
+
+void
+bar (int a, int b, int c, int d, int e, int f, int g, int h,
+     int i, int j, int k, int l, int m, int n, int o, int p)
+{
+  int a2 = a;
+  int b2 = b;
+  int c2 = c;
+  int d2 = d;
+  int e2 = e;
+  int f2 = f;
+  int g2 = g;
+  int h2 = h;
+  int i2 = i;
+  int j2 = j;
+  int k2 = k;
+  int l2 = l;
+  int m2 = m;
+  int n2 = n;
+  int o2 = o;
+  int p2 = p;
+  v++;
+}

        Jakub

Reply via email to