332 lines
10 KiB
Diff
332 lines
10 KiB
Diff
2010-02-17 Alexandre Oliva <aoliva@redhat.com>
|
|
|
|
* var-tracking.c (dataflow_set_preserve_mem_locs): Update cur_loc.
|
|
|
|
2010-02-17 Jakub Jelinek <jakub@redhat.com>
|
|
|
|
PR debug/43051
|
|
* var-tracking.c (struct dfset_merge): Move definition earlier.
|
|
(value_pair): New variable.
|
|
(ignore_first_value_pair): New function.
|
|
(find_loc_in_1pdv_1): Change last argument to struct dfset_merge *.
|
|
If node->loc is VALUE, don't call rtx_equal_p at all, instead just
|
|
compare pointers and then recurse. For other rtxes, call
|
|
rtx_equal_p_cb instead of rtx_equal_p and ignore first VALUE pair
|
|
during comparison, if some has been found, compare those VALUEs
|
|
recursively.
|
|
(find_loc_in_1pdv): Change last argument to struct dfset_merge *.
|
|
(intersect_loc_chains, variable_post_merge_perm_vals): Adjust callers.
|
|
|
|
* gcc.dg/guality/pr43051-1.c: New test.
|
|
|
|
--- gcc/var-tracking.c.jj 2010-02-07 11:53:22.000000000 +0100
|
|
+++ gcc/var-tracking.c 2010-02-15 12:37:00.000000000 +0100
|
|
@@ -428,7 +428,8 @@ static int variable_union_info_cmp_pos (
|
|
static int variable_union (void **, void *);
|
|
static int variable_canonicalize (void **, void *);
|
|
static void dataflow_set_union (dataflow_set *, dataflow_set *);
|
|
-static location_chain find_loc_in_1pdv (rtx, variable, htab_t);
|
|
+struct dfset_merge;
|
|
+static location_chain find_loc_in_1pdv (rtx, variable, struct dfset_merge *);
|
|
static bool canon_value_cmp (rtx, rtx);
|
|
static int loc_cmp (rtx, rtx);
|
|
static bool variable_part_different_p (variable_part *, variable_part *);
|
|
@@ -2234,6 +2235,53 @@ dv_changed_p (decl_or_value dv)
|
|
: DECL_CHANGED (dv_as_decl (dv)));
|
|
}
|
|
|
|
+/* Hash table iteration argument passed to variable_merge. */
|
|
+struct dfset_merge
|
|
+{
|
|
+ /* The set in which the merge is to be inserted. */
|
|
+ dataflow_set *dst;
|
|
+ /* The set that we're iterating in. */
|
|
+ dataflow_set *cur;
|
|
+ /* The set that may contain the other dv we are to merge with. */
|
|
+ dataflow_set *src;
|
|
+ /* Number of onepart dvs in src. */
|
|
+ int src_onepart_cnt;
|
|
+};
|
|
+
|
|
+/* First encountered differing VALUE pair remembered by
|
|
+ ignore_first_value_pair hook. */
|
|
+
|
|
+static rtx value_pair[2];
|
|
+
|
|
+/* Helper for rtx_equal_p_cb. Pretend the first encountered VALUE pair
|
|
+ is the same and remember it. */
|
|
+
|
|
+static int
|
|
+ignore_first_value_pair (const_rtx *px, const_rtx *py, rtx *nx, rtx *ny)
|
|
+{
|
|
+ const_rtx x = *px, y;
|
|
+
|
|
+ if (GET_CODE (x) != VALUE)
|
|
+ return 0;
|
|
+ y = *py;
|
|
+ if (GET_CODE (y) != VALUE)
|
|
+ return 0;
|
|
+ if (x == y)
|
|
+ return 0;
|
|
+ if (GET_MODE (x) != GET_MODE (y))
|
|
+ return 0;
|
|
+ /* If this isn't the first encountered VALUE pair, fail. */
|
|
+ if (value_pair[0])
|
|
+ return 0;
|
|
+ /* Remember the first encountered VALUE pair and pretend the VALUEs are the
|
|
+ same. */
|
|
+ value_pair[0] = CONST_CAST_RTX (x);
|
|
+ value_pair[1] = CONST_CAST_RTX (y);
|
|
+ *nx = CONST_CAST_RTX (x);
|
|
+ *ny = CONST_CAST_RTX (x);
|
|
+ return 1;
|
|
+}
|
|
+
|
|
/* Vector of VALUEs that should have VALUE_RECURSED_INTO bit cleared
|
|
at the end of find_loc_in_1pdv. Not a static variable in find_loc_in_1pdv
|
|
to avoid constant allocation/freeing of it. */
|
|
@@ -2245,7 +2293,7 @@ static VEC(rtx, heap) *values_to_unmark;
|
|
any values recursively mentioned in the location lists. */
|
|
|
|
static location_chain
|
|
-find_loc_in_1pdv_1 (rtx loc, variable var, htab_t vars)
|
|
+find_loc_in_1pdv_1 (rtx loc, variable var, struct dfset_merge *dsm)
|
|
{
|
|
location_chain node;
|
|
|
|
@@ -2260,22 +2308,65 @@ find_loc_in_1pdv_1 (rtx loc, variable va
|
|
gcc_assert (var->var_part[0].offset == 0);
|
|
|
|
for (node = var->var_part[0].loc_chain; node; node = node->next)
|
|
- if (rtx_equal_p (loc, node->loc))
|
|
- return node;
|
|
- else if (GET_CODE (node->loc) == VALUE
|
|
- && !VALUE_RECURSED_INTO (node->loc))
|
|
+ if (GET_CODE (node->loc) == VALUE)
|
|
{
|
|
- decl_or_value dv = dv_from_value (node->loc);
|
|
- variable var = (variable)
|
|
- htab_find_with_hash (vars, dv, dv_htab_hash (dv));
|
|
+ if (loc == node->loc)
|
|
+ return node;
|
|
+ if (!VALUE_RECURSED_INTO (node->loc))
|
|
+ {
|
|
+ decl_or_value dv = dv_from_value (node->loc);
|
|
+ htab_t vars = shared_hash_htab (dsm->src->vars);
|
|
+ variable var
|
|
+ = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
|
|
|
|
- if (var)
|
|
+ if (var)
|
|
+ {
|
|
+ location_chain where;
|
|
+ VALUE_RECURSED_INTO (node->loc) = true;
|
|
+ VEC_safe_push (rtx, heap, values_to_unmark, node->loc);
|
|
+ if ((where = find_loc_in_1pdv_1 (loc, var, dsm)))
|
|
+ return where;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else if (GET_CODE (node->loc) == GET_CODE (loc))
|
|
+ {
|
|
+ rtx val1, val2;
|
|
+ if (!rtx_equal_p_cb (loc, node->loc, ignore_first_value_pair))
|
|
{
|
|
- location_chain where;
|
|
- VALUE_RECURSED_INTO (node->loc) = true;
|
|
- VEC_safe_push (rtx, heap, values_to_unmark, node->loc);
|
|
- if ((where = find_loc_in_1pdv_1 (loc, var, vars)))
|
|
- return where;
|
|
+ value_pair[0] = NULL;
|
|
+ value_pair[1] = NULL;
|
|
+ continue;
|
|
+ }
|
|
+ if (!value_pair[0])
|
|
+ return node;
|
|
+ val1 = value_pair[0];
|
|
+ val2 = value_pair[1];
|
|
+ value_pair[0] = NULL;
|
|
+ value_pair[1] = NULL;
|
|
+ if (dsm->cur)
|
|
+ {
|
|
+ decl_or_value dv;
|
|
+ htab_t vars;
|
|
+ variable var1, var2;
|
|
+ dv = dv_from_value (val1);
|
|
+ vars = shared_hash_htab (dsm->cur->vars);
|
|
+ var1 = (variable) htab_find_with_hash (vars, dv,
|
|
+ dv_htab_hash (dv));
|
|
+ if (var1)
|
|
+ {
|
|
+ dv = dv_from_value (val2);
|
|
+ vars = shared_hash_htab (dsm->src->vars);
|
|
+ var2 = (variable) htab_find_with_hash (vars, dv,
|
|
+ dv_htab_hash (dv));
|
|
+ if (var2)
|
|
+ {
|
|
+ location_chain s1node = var1->var_part[0].loc_chain;
|
|
+ for (; s1node; s1node = s1node->next)
|
|
+ if (find_loc_in_1pdv_1 (s1node->loc, var2, dsm))
|
|
+ return node;
|
|
+ }
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -2287,32 +2378,19 @@ find_loc_in_1pdv_1 (rtx loc, variable va
|
|
any values recursively mentioned in the location lists. */
|
|
|
|
static location_chain
|
|
-find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
|
|
+find_loc_in_1pdv (rtx loc, variable var, struct dfset_merge *dsm)
|
|
{
|
|
location_chain ret;
|
|
unsigned int i;
|
|
rtx value;
|
|
|
|
- ret = find_loc_in_1pdv_1 (loc, var, vars);
|
|
+ ret = find_loc_in_1pdv_1 (loc, var, dsm);
|
|
for (i = 0; VEC_iterate (rtx, values_to_unmark, i, value); i++)
|
|
VALUE_RECURSED_INTO (value) = false;
|
|
VEC_truncate (rtx, values_to_unmark, 0);
|
|
return ret;
|
|
}
|
|
|
|
-/* Hash table iteration argument passed to variable_merge. */
|
|
-struct dfset_merge
|
|
-{
|
|
- /* The set in which the merge is to be inserted. */
|
|
- dataflow_set *dst;
|
|
- /* The set that we're iterating in. */
|
|
- dataflow_set *cur;
|
|
- /* The set that may contain the other dv we are to merge with. */
|
|
- dataflow_set *src;
|
|
- /* Number of onepart dvs in src. */
|
|
- int src_onepart_cnt;
|
|
-};
|
|
-
|
|
/* Insert LOC in *DNODE, if it's not there yet. The list must be in
|
|
loc_cmp order, and it is maintained as such. */
|
|
|
|
@@ -2351,7 +2429,6 @@ intersect_loc_chains (rtx val, location_
|
|
location_chain s1node, variable s2var)
|
|
{
|
|
dataflow_set *s1set = dsm->cur;
|
|
- dataflow_set *s2set = dsm->src;
|
|
location_chain found;
|
|
|
|
for (; s1node; s1node = s1node->next)
|
|
@@ -2359,8 +2436,7 @@ intersect_loc_chains (rtx val, location_
|
|
if (s1node->loc == val)
|
|
continue;
|
|
|
|
- if ((found = find_loc_in_1pdv (s1node->loc, s2var,
|
|
- shared_hash_htab (s2set->vars))))
|
|
+ if ((found = find_loc_in_1pdv (s1node->loc, s2var, dsm)))
|
|
{
|
|
insert_into_intersection (dest, s1node->loc,
|
|
MIN (s1node->init, found->init));
|
|
@@ -3592,7 +3668,10 @@ variable_post_merge_perm_vals (void **ps
|
|
var = shared_hash_find (set->vars, dv);
|
|
if (var)
|
|
{
|
|
- if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
|
|
+ struct dfset_merge dsm;
|
|
+ memset (&dsm, '\0', sizeof (dsm));
|
|
+ dsm.src = set;
|
|
+ if (find_loc_in_1pdv (pnode->loc, var, &dsm))
|
|
return 1;
|
|
val_reset (set, dv);
|
|
}
|
|
@@ -3808,6 +3808,7 @@ dataflow_set_preserve_mem_locs (void **s
|
|
{
|
|
tree decl = dv_as_decl (var->dv);
|
|
location_chain loc, *locp;
|
|
+ bool changed = false;
|
|
|
|
if (!var->n_var_parts)
|
|
return 1;
|
|
@@ -3881,6 +3882,9 @@ dataflow_set_preserve_mem_locs (void **s
|
|
if (emit_notes)
|
|
remove_value_chains (var->dv, old_loc);
|
|
*locp = loc->next;
|
|
+ if (var->var_part[0].cur_loc
|
|
+ && rtx_equal_p (loc->loc, var->var_part[0].cur_loc))
|
|
+ changed = true;
|
|
pool_free (loc_chain_pool, loc);
|
|
}
|
|
|
|
@@ -3889,6 +3893,12 @@ dataflow_set_preserve_mem_locs (void **s
|
|
var->n_var_parts--;
|
|
if (emit_notes && dv_is_value_p (var->dv))
|
|
remove_cselib_value_chains (var->dv);
|
|
+ gcc_assert (changed);
|
|
+ }
|
|
+ if (changed)
|
|
+ {
|
|
+ if (var->n_var_parts && var->var_part[0].loc_chain)
|
|
+ var->var_part[0].cur_loc = var->var_part[0].loc_chain->loc;
|
|
variable_was_changed (var, set);
|
|
}
|
|
}
|
|
--- gcc/testsuite/gcc.dg/guality/pr43051-1.c.jj 2010-02-17 10:17:12.000000000 +0100
|
|
+++ gcc/testsuite/gcc.dg/guality/pr43051-1.c 2010-02-17 10:41:43.000000000 +0100
|
|
@@ -0,0 +1,57 @@
|
|
+/* PR debug/43051 */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-g" } */
|
|
+
|
|
+extern void abort (void);
|
|
+
|
|
+static void __attribute__ ((noinline))
|
|
+foo (const char *x, long long y, int z)
|
|
+{
|
|
+ asm volatile ("" : : "r" (x), "r" ((int) y), "r" (z) : "memory");
|
|
+}
|
|
+
|
|
+struct S
|
|
+{
|
|
+ struct S *n;
|
|
+ int v;
|
|
+};
|
|
+
|
|
+struct S a[10];
|
|
+
|
|
+struct S * __attribute__ ((noinline))
|
|
+bar (struct S *c, int v, struct S *e)
|
|
+{
|
|
+#ifdef __i386__
|
|
+ register int si asm ("esi"), di asm ("edi"), bx
|
|
+# if !defined (__pic__) && !defined (__APPLE__)
|
|
+ asm ("ebx")
|
|
+# endif
|
|
+ ;
|
|
+ asm volatile ("" : "=r" (si), "=r" (di), "=r" (bx));
|
|
+#endif
|
|
+ while (c < e)
|
|
+ {
|
|
+ foo ("c", (unsigned long) c, 0); /* { dg-final { gdb-test 34 "c" "\&a\[0\]" } } */
|
|
+ foo ("v", v, 1); /* { dg-final { gdb-test 35 "v" "1" } } */
|
|
+ foo ("e", (unsigned long) e, 2); /* { dg-final { gdb-test 36 "e" "\&a\[1\]" } } */
|
|
+ if (c->v == v)
|
|
+ return c;
|
|
+ foo ("c", (unsigned long) c, 3); /* { dg-final { gdb-test 39 "c" "\&a\[0\]" } } */
|
|
+ foo ("v", v, 4); /* { dg-final { gdb-test 40 "v" "1" } } */
|
|
+ foo ("e", (unsigned long) e, 5); /* { dg-final { gdb-test 41 "e" "\&a\[1\]" } } */
|
|
+ c++;
|
|
+ }
|
|
+#ifdef __i386__
|
|
+ asm volatile ("" : : "r" (si), "r" (di), "r" (bx));
|
|
+#endif
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+main ()
|
|
+{
|
|
+ asm volatile ("" : : "r" (&a[0]) : "memory");
|
|
+ if (bar (&a[a[0].v], a[0].v + 1, &a[a[0].v + 1]))
|
|
+ abort ();
|
|
+ return 0;
|
|
+}
|