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:
parent
0c179631b2
commit
b933b33a18
@ -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>
|
2010-06-10 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR boostrap/44470
|
PR boostrap/44470
|
||||||
|
@ -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
|
/* 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
|
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
|
static location_chain
|
||||||
find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
|
find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
|
||||||
{
|
{
|
||||||
location_chain node;
|
location_chain node;
|
||||||
enum rtx_code loc_code;
|
enum rtx_code loc_code;
|
||||||
location_chain ret = NULL;
|
|
||||||
int unmark_self = 0;
|
|
||||||
#ifdef ENABLE_CHECKING
|
|
||||||
static int mark_count;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!var)
|
if (!var)
|
||||||
return ret;
|
return NULL;
|
||||||
|
|
||||||
#ifdef ENABLE_CHECKING
|
#ifdef ENABLE_CHECKING
|
||||||
gcc_assert (dv_onepart_p (var->dv));
|
gcc_assert (dv_onepart_p (var->dv));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!var->n_var_parts)
|
if (!var->n_var_parts)
|
||||||
return ret;
|
return NULL;
|
||||||
|
|
||||||
#ifdef ENABLE_CHECKING
|
#ifdef ENABLE_CHECKING
|
||||||
gcc_assert (var->var_part[0].offset == 0);
|
gcc_assert (var->var_part[0].offset == 0);
|
||||||
|
gcc_assert (loc != dv_as_opaque (var->dv));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
loc_code = GET_CODE (loc);
|
loc_code = GET_CODE (loc);
|
||||||
for (node = var->var_part[0].loc_chain; node; node = node->next)
|
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) != loc_code)
|
||||||
{
|
{
|
||||||
if (GET_CODE (node->loc) != VALUE)
|
if (GET_CODE (node->loc) != VALUE)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (loc == node->loc)
|
else if (loc == node->loc)
|
||||||
{
|
return node;
|
||||||
ret = node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (loc_code != VALUE)
|
else if (loc_code != VALUE)
|
||||||
{
|
{
|
||||||
if (rtx_equal_p (loc, node->loc))
|
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;
|
node = node->next;
|
||||||
break;
|
#ifdef ENABLE_CHECKING
|
||||||
|
gcc_assert (!canon_value_cmp (node->loc,
|
||||||
|
dv_as_value (var->dv)));
|
||||||
|
#endif
|
||||||
|
if (loc == node->loc)
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
continue;
|
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
|
#ifdef ENABLE_CHECKING
|
||||||
mark_count++;
|
gcc_assert (node == var->var_part[0].loc_chain);
|
||||||
/* The recursion count is bounded because we're
|
gcc_assert (!node->next);
|
||||||
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);
|
|
||||||
#endif
|
#endif
|
||||||
VALUE_RECURSED_INTO (node->loc) = true;
|
|
||||||
if ((where = find_loc_in_1pdv (loc, rvar, vars)))
|
dv = dv_from_value (node->loc);
|
||||||
{
|
rvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
|
||||||
#ifdef ENABLE_CHECKING
|
return find_loc_in_1pdv (loc, rvar, vars);
|
||||||
mark_count--;
|
|
||||||
#endif
|
|
||||||
VALUE_RECURSED_INTO (node->loc) = false;
|
|
||||||
ret = where;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
VALUE_RECURSED_INTO (node->loc) = false;
|
|
||||||
#ifdef ENABLE_CHECKING
|
|
||||||
mark_count--;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unmark_self > 0)
|
return NULL;
|
||||||
{
|
|
||||||
VALUE_RECURSED_INTO (dv_as_value (var->dv)) = false;
|
|
||||||
#ifdef ENABLE_CHECKING
|
|
||||||
mark_count--;
|
|
||||||
gcc_assert (mark_count == 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hash table iteration argument passed to variable_merge. */
|
/* 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);
|
var = shared_hash_find (set->vars, dv);
|
||||||
if (var)
|
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)))
|
if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
|
||||||
return 1;
|
return 1;
|
||||||
val_reset (set, dv);
|
val_reset (set, dv);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user