diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 725a52d6b9c..685a346211a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2010-06-10 Alexandre Oliva + + 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 PR boostrap/44470 diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index eb6144fa3e5..57405583e58 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -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);