Hi! This patch attempts to fix a regression caused by the http://gcc.gnu.org/r208220 change. In particular, because cselib_reset_table called immediately after cselib_preserve_only_values removes VALUEs with zero locs and thus clears n_useless_values, if we don't remove_useless_values right away (as was done before the patch), we might not call discard_useless_locs at all). The problem with that is var-tracking relies on preserved values not referencing non-preserved values without any locs. The patch ensures we discard_useless_locs at least sometimes during vt_initialize (if the cumulative number of dropped and useless VALUEs goes over certain amount) and ensures we do it at least once at the end of vt_initialize.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2014-03-04 Jakub Jelinek <ja...@redhat.com> PR middle-end/60381 * cselib.h (cselib_remove_useless_values): New prototype. * var-tracking.c (vt_initialize): Call it at the end. * cselib.c (n_dropped_useless_values): New counter. (cselib_reset_table): Accumulate n_useless_values into n_dropped_useless_values. (remove_useless_values): Revert 2014-02-28 change. Clear n_dropped_useless_values. (cselib_preserve_only_values): Don't call remove_useless_values, just do traversal with discard_useless_locs conditionally on n_dropped_useless_values + n_useless_values being big enough. (cselib_remove_useless_values): New function. (cselib_process_insn): Revert 2014-02-28 change. (cselib_finish): Clear n_dropped_useless_values. --- gcc/cselib.h.jj 2014-01-03 11:40:57.000000000 +0100 +++ gcc/cselib.h 2014-03-03 19:23:48.633335911 +0100 @@ -95,6 +95,7 @@ extern unsigned int cselib_get_next_uid extern void cselib_preserve_value (cselib_val *); extern bool cselib_preserved_value_p (cselib_val *); extern void cselib_preserve_only_values (void); +extern void cselib_remove_useless_values (vec<rtx>); extern void cselib_preserve_cfa_base_value (cselib_val *, unsigned int); extern void cselib_add_permanent_equiv (cselib_val *, rtx, rtx); extern bool cselib_have_permanent_equivalences (void); --- gcc/var-tracking.c.jj 2014-03-03 18:28:18.000000000 +0100 +++ gcc/var-tracking.c 2014-03-03 19:27:07.518208397 +0100 @@ -10149,6 +10149,8 @@ vt_initialize (void) } } + if (MAY_HAVE_DEBUG_INSNS) + cselib_remove_useless_values (preserved_values); hard_frame_pointer_adjustment = -1; VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->flooded = true; cfa_base_rtx = NULL_RTX; --- gcc/cselib.c.jj 2014-03-03 18:28:18.000000000 +0100 +++ gcc/cselib.c 2014-03-03 19:28:19.832782951 +0100 @@ -200,6 +200,7 @@ static unsigned int cselib_nregs; values. */ static int n_useless_values; static int n_useless_debug_values; +static int n_dropped_useless_values; /* Count values whose locs have been taken exclusively from debug insns for the entire life of the value. */ @@ -546,7 +547,11 @@ cselib_reset_table (unsigned int num) } if (cselib_preserve_constants) - cselib_hash_table.traverse <void *, preserve_constants_and_equivs> (NULL); + { + n_dropped_useless_values += n_useless_values; + cselib_hash_table.traverse <void *, + preserve_constants_and_equivs> (NULL); + } else { cselib_hash_table.empty (); @@ -681,14 +686,6 @@ remove_useless_values (void) { cselib_val **p, *v; - if (n_useless_values <= MAX_USELESS_VALUES - /* remove_useless_values is linear in the hash table size. Avoid - quadratic behavior for very large hashtables with very few - useless elements. */ - || ((unsigned int)n_useless_values - <= (cselib_hash_table.elements () - n_debug_values) / 4)) - return; - /* First pass: eliminate locations that reference the value. That in turn can make more values useless. */ do @@ -712,6 +709,7 @@ remove_useless_values (void) n_useless_values += n_useless_debug_values; n_debug_values -= n_useless_debug_values; n_useless_debug_values = 0; + n_dropped_useless_values = 0; cselib_hash_table.traverse <void *, discard_useless_values> (NULL); @@ -763,11 +761,43 @@ cselib_preserve_only_values (void) cselib_invalidate_mem (callmem); - remove_useless_values (); + if ((n_dropped_useless_values + n_useless_values) > MAX_USELESS_VALUES + /* Traversal with discard_useless_locs is linear in the hash table + size. Avoid quadratic behavior for very large hashtables with + very few useless elements. */ + && ((unsigned int) (n_dropped_useless_values + n_useless_values) + > (cselib_hash_table.elements () - n_debug_values) / 4)) + { + /* Eliminate locations that reference the value. That in + turn can make more values useless. */ + do + { + values_became_useless = 0; + cselib_hash_table.traverse <void *, discard_useless_locs> (NULL); + } + while (values_became_useless); + n_dropped_useless_values = 0; + } gcc_assert (first_containing_mem == &dummy_val); } +/* Clean out useless values (i.e. those which no longer have locations + associated with them) from both hash tables. */ + +void +cselib_remove_useless_values (vec<rtx> values) +{ + unsigned int i; + rtx val; + + if (n_dropped_useless_values) + remove_useless_values (); + cselib_preserved_hash_table.traverse <void *, discard_useless_locs> (NULL); + FOR_EACH_VEC_ELT (values, i, val) + discard_useless_locs (&CSELIB_VAL_PTR (val), NULL); +} + /* Arrange for a value to be marked as based on stack pointer for find_base_term purposes. */ @@ -2720,7 +2750,13 @@ cselib_process_insn (rtx insn) cselib_current_insn = NULL_RTX; - remove_useless_values (); + if (n_useless_values > MAX_USELESS_VALUES + /* remove_useless_values is linear in the hash table size. Avoid + quadratic behavior for very large hashtables with very few + useless elements. */ + && ((unsigned int)n_useless_values + > (cselib_hash_table.elements () - n_debug_values) / 4)) + remove_useless_values (); } /* Initialize cselib for one pass. The caller must also call @@ -2790,6 +2826,7 @@ cselib_finish (void) n_useless_values = 0; n_useless_debug_values = 0; n_debug_values = 0; + n_dropped_useless_values = 0; next_uid = 0; } Jakub