re PR debug/41371 (var-tracking is slow and memory hungry)

PR debug/41371
* var-tracking.c (find_loc_in_1pdv): Remove recursion, only
tail-recurse into canonical node.  Fast-forward over
non-canonical VALUEs.

From-SVN: r160559
This commit is contained in:
Alexandre Oliva 2010-06-10 16:43:46 +00:00 committed by Alexandre Oliva
parent 0c179631b2
commit b933b33a18
2 changed files with 48 additions and 79 deletions

View File

@ -1,3 +1,10 @@
2010-06-10 Alexandre Oliva <aoliva@redhat.com>
PR debug/41371
* var-tracking.c (find_loc_in_1pdv): Remove recursion, only
tail-recurse into canonical node. Fast-forward over
non-canonical VALUEs.
2010-06-10 H.J. Lu <hongjiu.lu@intel.com>
PR boostrap/44470

View File

@ -2479,125 +2479,81 @@ dv_changed_p (decl_or_value dv)
/* Return a location list node whose loc is rtx_equal to LOC, in the
location list of a one-part variable or value VAR, or in that of
any values recursively mentioned in the location lists. */
any values recursively mentioned in the location lists. VARS must
be in star-canonical form. */
static location_chain
find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
{
location_chain node;
enum rtx_code loc_code;
location_chain ret = NULL;
int unmark_self = 0;
#ifdef ENABLE_CHECKING
static int mark_count;
#endif
if (!var)
return ret;
return NULL;
#ifdef ENABLE_CHECKING
gcc_assert (dv_onepart_p (var->dv));
#endif
if (!var->n_var_parts)
return ret;
return NULL;
#ifdef ENABLE_CHECKING
gcc_assert (var->var_part[0].offset == 0);
gcc_assert (loc != dv_as_opaque (var->dv));
#endif
loc_code = GET_CODE (loc);
for (node = var->var_part[0].loc_chain; node; node = node->next)
{
decl_or_value dv;
variable rvar;
if (GET_CODE (node->loc) != loc_code)
{
if (GET_CODE (node->loc) != VALUE)
continue;
}
else if (loc == node->loc)
{
ret = node;
break;
}
return node;
else if (loc_code != VALUE)
{
if (rtx_equal_p (loc, node->loc))
return node;
continue;
}
/* Since we're in star-canonical form, we don't need to visit
non-canonical nodes: one-part variables and non-canonical
values would only point back to the canonical node. */
if (dv_is_value_p (var->dv)
&& !canon_value_cmp (node->loc, dv_as_value (var->dv)))
{
/* Skip all subsequent VALUEs. */
while (node->next && GET_CODE (node->next->loc) == VALUE)
{
ret = node;
break;
node = node->next;
#ifdef ENABLE_CHECKING
gcc_assert (!canon_value_cmp (node->loc,
dv_as_value (var->dv)));
#endif
if (loc == node->loc)
return node;
}
continue;
}
if (!VALUE_RECURSED_INTO (node->loc))
{
decl_or_value dv = dv_from_value (node->loc);
variable rvar = (variable)
htab_find_with_hash (vars, dv, dv_htab_hash (dv));
if (rvar)
{
location_chain where;
if (!unmark_self)
{
if (dv_is_value_p (var->dv)
&& !VALUE_RECURSED_INTO (dv_as_value (var->dv)))
{
unmark_self = 1;
#ifdef ENABLE_CHECKING
mark_count++;
#endif
VALUE_RECURSED_INTO (dv_as_value (var->dv)) = true;
}
else
unmark_self = -1;
}
#ifdef ENABLE_CHECKING
mark_count++;
/* The recursion count is bounded because we're
searching in a star-canonicalized set, i.e., each
equivalence set of values is arranged so that the
canonical value has all locations and equivalent
values, whereas equivalent values only point back to
the canonical. So, if we start at the canonical
value, we'll recurse at most into each sibling, so
the recurse limit will be 2. If we start at a
non-canonical value, we'll recurse into the
canonical, and from there to other siblings, so
recurse limit will be 3. If we start at a one-part
variable, we add one level of recursion, but we don't
count it. */
gcc_assert (mark_count <= 3);
gcc_assert (node == var->var_part[0].loc_chain);
gcc_assert (!node->next);
#endif
VALUE_RECURSED_INTO (node->loc) = true;
if ((where = find_loc_in_1pdv (loc, rvar, vars)))
{
#ifdef ENABLE_CHECKING
mark_count--;
#endif
VALUE_RECURSED_INTO (node->loc) = false;
ret = where;
break;
}
VALUE_RECURSED_INTO (node->loc) = false;
#ifdef ENABLE_CHECKING
mark_count--;
#endif
}
}
dv = dv_from_value (node->loc);
rvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
return find_loc_in_1pdv (loc, rvar, vars);
}
if (unmark_self > 0)
{
VALUE_RECURSED_INTO (dv_as_value (var->dv)) = false;
#ifdef ENABLE_CHECKING
mark_count--;
gcc_assert (mark_count == 0);
#endif
}
return ret;
return NULL;
}
/* Hash table iteration argument passed to variable_merge. */
@ -4031,6 +3987,12 @@ variable_post_merge_perm_vals (void **pslot, void *info)
var = shared_hash_find (set->vars, dv);
if (var)
{
/* Although variable_post_merge_new_vals may have made decls
non-star-canonical, values that pre-existed in canonical form
remain canonical, and newly-created values reference a single
REG, so they are canonical as well. Since VAR has the
location list for a VALUE, using find_loc_in_1pdv for it is
fine, since VALUEs don't map back to DECLs. */
if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
return 1;
val_reset (set, dv);