aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2011-03-29 01:53:46 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2011-03-29 01:53:46 +0200
commit2b80199f41d444c88474b32792a7e828f2a96b68 (patch)
tree7d5601e9e49e4f8fa5cf78fc46ce899d76d94f4f /gcc
parentb9da60aea69647fd7957dc328a8431412157d3a7 (diff)
downloadgcc-2b80199f41d444c88474b32792a7e828f2a96b68.zip
gcc-2b80199f41d444c88474b32792a7e828f2a96b68.tar.gz
gcc-2b80199f41d444c88474b32792a7e828f2a96b68.tar.bz2
re PR debug/48203 (ICE in dwarf2out.c while building eglibc.)
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. From-SVN: r171640
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/cfgexpand.c6
-rw-r--r--gcc/cselib.c33
-rw-r--r--gcc/dwarf2out.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr48203.c51
-rw-r--r--gcc/var-tracking.c37
7 files changed, 145 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eae6519..f3ee4b5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+2011-03-29 Jakub Jelinek <jakub@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.
+
2011-03-28 Richard Sandiford <richard.sandiford@linaro.org>
* builtins.c (expand_builtin_memset_args): Use gen_int_mode
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index da40aae..e075c53 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3172,8 +3172,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;
diff --git a/gcc/cselib.c b/gcc/cselib.c
index f9e13ff..dff0967 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -305,7 +305,8 @@ cselib_clear_table (void)
cselib_reset_table (1);
}
-/* Remove from hash table all VALUEs except constants. */
+/* Remove from hash table all VALUEs except constants
+ and function invariants. */
static int
preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED)
@@ -329,6 +330,14 @@ preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED)
return 1;
}
}
+ /* Keep around VALUEs that forward function invariant ENTRY_VALUEs
+ to corresponding parameter VALUEs. */
+ 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 +813,9 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, enum machine_mode memmode)
== DEBUG_IMPLICIT_PTR_DECL (y);
case ENTRY_VALUE:
- return rtx_equal_for_cselib_1 (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y),
- memmode);
+ /* ENTRY_VALUEs are function invariant, it is thus undesirable to
+ use rtx_equal_for_cselib_1 to compare the operands. */
+ return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
case LABEL_REF:
return XEXP (x, 0) == XEXP (y, 0);
@@ -954,7 +964,22 @@ cselib_hash_rtx (rtx x, int create, enum machine_mode memmode)
return hash ? hash : (unsigned int) DEBUG_IMPLICIT_PTR;
case ENTRY_VALUE:
- hash += cselib_hash_rtx (ENTRY_VALUE_EXP (x), create, memmode);
+ /* ENTRY_VALUEs are function invariant, thus try to avoid
+ recursing on argument if ENTRY_VALUE is one of the
+ forms emitted by expand_debug_expr, otherwise
+ ENTRY_VALUE hash would depend on the current value
+ in some register or memory. */
+ 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:
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 77d533e..182a894 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -13891,7 +13891,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dec92ef..513805d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-03-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/48203
+ * gcc.dg/pr48203.c: New test.
+
2011-03-28 Jeff Law <law@redhat.com>
* gcc.dg/tree-ssa/ssa-dom-thread-3.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr48203.c b/gcc/testsuite/gcc.dg/pr48203.c
new file mode 100644
index 0000000..b4b2b08
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr48203.c
@@ -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++;
+}
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index ef02937..9729956 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -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 (mem),
+ 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;
+ }
}
}
}