diff options
-rw-r--r-- | gcc/ChangeLog | 81 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/cselib.c | 40 | ||||
-rw-r--r-- | gcc/cselib.h | 4 | ||||
-rw-r--r-- | gcc/var-tracking.c | 626 |
5 files changed, 560 insertions, 193 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 25c0efdf8dc..c495c34377a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,84 @@ +2010-03-07 Jakub Jelinek <jakub@redhat.com> + + PR debug/43176 + * Makefile.in (var-tracking.o): Depend on pointer-set.h. + * cselib.c (struct expand_value_data): Add dummy field. + (cselib_expand_value_rtx, cselib_expand_value_rtx_cb): Initialize + dummy to false. + (cselib_dummy_expand_value_rtx_cb): New function. + (cselib_expand_value_rtx_1): If evd->dummy is true, don't allocate + any rtl. + * cselib.h (cselib_dummy_expand_value_rtx_cb): New prototype. + * var-tracking.c: Include pointer-set.h. + (variable): Change n_var_parts to char from int. Add + cur_loc_changed and in_changed_variables fields. + (variable_canonicalize): Remove. + (shared_var_p): New inline function. + (unshare_variable): Maintain cur_loc_changed and + in_changed_variables fields. If var was in changed_variables, + replace it there with new_var. Just copy cur_loc instead of + resetting it to something else. + (variable_union): Don't recompute cur_loc. Use shared_var_p. + (dataflow_set_union): Don't call variable_canonicalize. + (loc_cmp): If both x and y are DEBUG_EXPRs, compare uids + of their DEBUG_EXPR_TREE_DECLs. + (canonicalize_loc_order_check): Verify that cur_loc is NULL + and in_changed_variables and cur_loc_changed is false. + (variable_merge_over_cur): Clear cur_loc, in_changed_variables + and cur_loc_changed. Don't update cur_loc here. + (variable_merge_over_src): Don't call variable_canonicalize. + (dataflow_set_preserve_mem_locs): Use shared_var_p. When + removing loc that is equal to cur_loc, clear cur_loc, + set cur_loc_changed and ensure variable_was_changed is called. + (dataflow_set_remove_mem_locs): Use shared_var_p. Only + compare pointers in cur_loc check, if it is equal to loc, + clear cur_loc and set cur_loc_changed. Don't recompute cur_loc here. + (variable_different_p): Remove compare_current_location argument, + don't compare cur_loc. + (dataflow_set_different_1): Adjust variable_different_p caller. + (variable_was_changed): If dv had some var in changed_variables + already, reset in_changed_variables flag for it and propagate + cur_loc_changed over to the new variable. On empty var + always set cur_loc_changed. Set in_changed_variables on whatever + var is added to changed_variables. + (set_slot_part): Clear cur_loc_changed and in_changed_variables. + Use shared_var_p. When removing loc that is equal to cur_loc, + clear cur_loc and set cur_loc_changed. If cur_loc is NULL at the + end, don't set it to something else, just call variable_was_changed. + (delete_slot_part): Use shared_var_p. When cur_loc equals to + loc being removed, clear cur_loc and set cur_loc_changed. + Set cur_loc_changed if all locations have been removed. + (struct expand_loc_callback_data): New type. + (vt_expand_loc_callback): Add dummy mode in which no rtxes are + allocated. Always create SUBREGs if simplify_subreg failed. + Prefer to use cur_loc, when that fails and still in + changed_variables (and seen first time) recompute it. Set + cur_loc_changed of variables which had to change cur_loc and + compute elcd->cur_loc_changed if any of the subexpressions used + had to change cur_loc. + (vt_expand_loc): Adjust to pass arguments in + expand_loc_callback_data structure. + (vt_expand_loc_dummy): New function. + (emitted_notes): New variable. + (emit_note_insn_var_location): For VALUEs and DEBUG_EXPR_DECLs + that weren't used for any other decl in current + emit_notes_for_changes call call vt_expand_loc_dummy to update + cur_loc. For -fno-var-tracking-assignments, set cur_loc to + first loc_chain location if NULL before. Always use just + cur_loc instead of first loc_chain location. When cur_loc_changed + is false, when not --enable-checking=rtl just don't emit any note. + When rtl checking, compute the note and assert it is the same + as previous note. Clear cur_loc_changed and in_changed_variables + at the end before removing from changed_variables. + (check_changed_vars_3): New function. + (emit_notes_for_changes): Traverse changed_vars to call + check_changed_vars_3 on each changed var. + (emit_notes_for_differences_1): Clear cur_loc_changed and + in_changed_variables. Recompute cur_loc of new_var. + (emit_notes_for_differences_2): Clear cur_loc if new variable + appears. + (vt_emit_notes): Initialize and destroy emitted_notes. + 2010-03-07 Bernd Schmidt <bernd.schmidt@analog.com> PR rtl-optimization/42220 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index bea6cf2b8cc..20ab71ff786 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3031,7 +3031,7 @@ var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \ $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \ $(REGS_H) $(EXPR_H) $(TIMEVAR_H) $(TREE_PASS_H) $(TREE_FLOW_H) \ - cselib.h $(TARGET_H) $(TOPLEV_H) $(PARAMS_H) $(DIAGNOSTIC_H) + cselib.h $(TARGET_H) $(TOPLEV_H) $(PARAMS_H) $(DIAGNOSTIC_H) pointer-set.h profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) $(FUNCTION_H) \ $(TOPLEV_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h \ diff --git a/gcc/cselib.c b/gcc/cselib.c index deac835f933..515fc328463 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -69,6 +69,7 @@ struct expand_value_data bitmap regs_active; cselib_expand_callback callback; void *callback_arg; + bool dummy; }; static rtx cselib_expand_value_rtx_1 (rtx, struct expand_value_data *, int); @@ -1069,6 +1070,7 @@ cselib_expand_value_rtx (rtx orig, bitmap regs_active, int max_depth) evd.regs_active = regs_active; evd.callback = NULL; evd.callback_arg = NULL; + evd.dummy = false; return cselib_expand_value_rtx_1 (orig, &evd, max_depth); } @@ -1088,10 +1090,29 @@ cselib_expand_value_rtx_cb (rtx orig, bitmap regs_active, int max_depth, evd.regs_active = regs_active; evd.callback = cb; evd.callback_arg = data; + evd.dummy = false; return cselib_expand_value_rtx_1 (orig, &evd, max_depth); } +/* Similar to cselib_expand_value_rtx_cb, but no rtxs are actually copied + or simplified. Useful to find out whether cselib_expand_value_rtx_cb + would return NULL or non-NULL, without allocating new rtx. */ + +bool +cselib_dummy_expand_value_rtx_cb (rtx orig, bitmap regs_active, int max_depth, + cselib_expand_callback cb, void *data) +{ + struct expand_value_data evd; + + evd.regs_active = regs_active; + evd.callback = cb; + evd.callback_arg = data; + evd.dummy = true; + + return cselib_expand_value_rtx_1 (orig, &evd, max_depth) != NULL; +} + /* Internal implementation of cselib_expand_value_rtx and cselib_expand_value_rtx_cb. */ @@ -1249,7 +1270,10 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd, that all fields need copying, and then clear the fields that should not be copied. That is the sensible default behavior, and forces us to explicitly document why we are *not* copying a flag. */ - copy = shallow_copy_rtx (orig); + if (evd->dummy) + copy = NULL; + else + copy = shallow_copy_rtx (orig); format_ptr = GET_RTX_FORMAT (code); @@ -1263,7 +1287,8 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd, max_depth - 1); if (!result) return NULL; - XEXP (copy, i) = result; + if (copy) + XEXP (copy, i) = result; } break; @@ -1271,14 +1296,16 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd, case 'V': if (XVEC (orig, i) != NULL) { - XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); - for (j = 0; j < XVECLEN (copy, i); j++) + if (copy) + XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); + for (j = 0; j < XVECLEN (orig, i); j++) { rtx result = cselib_expand_value_rtx_1 (XVECEXP (orig, i, j), evd, max_depth - 1); if (!result) return NULL; - XVECEXP (copy, i, j) = result; + if (copy) + XVECEXP (copy, i, j) = result; } } break; @@ -1299,6 +1326,9 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd, gcc_unreachable (); } + if (evd->dummy) + return orig; + mode = GET_MODE (copy); /* If an operand has been simplified into CONST_INT, which doesn't have a mode and the mode isn't derivable from whole rtx's mode, diff --git a/gcc/cselib.h b/gcc/cselib.h index 75ff457bf2d..2cdf6ade10b 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -81,7 +81,9 @@ extern int references_value_p (const_rtx, int); extern rtx cselib_expand_value_rtx (rtx, bitmap, int); typedef rtx (*cselib_expand_callback)(rtx, bitmap, int, void *); extern rtx cselib_expand_value_rtx_cb (rtx, bitmap, int, - cselib_expand_callback, void*); + cselib_expand_callback, void *); +extern bool cselib_dummy_expand_value_rtx_cb (rtx, bitmap, int, + cselib_expand_callback, void *); extern rtx cselib_subst_to_values (rtx); extern void cselib_invalidate_rtx (rtx); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 8cc7675c38d..1878e90c1ef 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -112,6 +112,7 @@ #include "toplev.h" #include "params.h" #include "diagnostic.h" +#include "pointer-set.h" /* var-tracking.c assumes that tree code with the same value as VALUE rtx code has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl. @@ -324,7 +325,16 @@ typedef struct variable_def int refcount; /* Number of variable parts. */ - int n_var_parts; + char n_var_parts; + + /* True if this variable changed (any of its) cur_loc fields + during the current emit_notes_for_changes resp. + emit_notes_for_differences call. */ + bool cur_loc_changed; + + /* True if this variable_def struct is currently in the + changed_variables hash table. */ + bool in_changed_variables; /* The variable parts. */ variable_part var_part[1]; @@ -429,14 +439,13 @@ static void dataflow_set_clear (dataflow_set *); static void dataflow_set_copy (dataflow_set *, dataflow_set *); static int variable_union_info_cmp_pos (const void *, const void *); 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); static bool canon_value_cmp (rtx, rtx); static int loc_cmp (rtx, rtx); static bool variable_part_different_p (variable_part *, variable_part *); static bool onepart_variable_different_p (variable, variable); -static bool variable_different_p (variable, variable, bool); +static bool variable_different_p (variable, variable); static int dataflow_set_different_1 (void **, void *); static bool dataflow_set_different (dataflow_set *, dataflow_set *); static void dataflow_set_destroy (dataflow_set *); @@ -1056,6 +1065,16 @@ shared_hash_htab (shared_hash vars) return vars->htab; } +/* Return true if VAR is shared, or maybe because VARS is shared. */ + +static inline bool +shared_var_p (variable var, shared_hash vars) +{ + /* Don't count an entry in the changed_variables table as a duplicate. */ + return ((var->refcount > 1 + (int) var->in_changed_variables) + || shared_hash_shared (vars)); +} + /* Copy variables into a new hash table. */ static shared_hash @@ -1195,6 +1214,9 @@ unshare_variable (dataflow_set *set, void **slot, variable var, new_var->refcount = 1; var->refcount--; new_var->n_var_parts = var->n_var_parts; + new_var->cur_loc_changed = var->cur_loc_changed; + var->cur_loc_changed = false; + new_var->in_changed_variables = false; if (! flag_var_tracking_uninit) initialized = VAR_INIT_STATUS_INITIALIZED; @@ -1226,12 +1248,7 @@ unshare_variable (dataflow_set *set, void **slot, variable var, nextp = &new_lc->next; } - /* We are at the basic block boundary when copying variable description - so set the CUR_LOC to be the first element of the chain. */ - if (new_var->var_part[i].loc_chain) - new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc; - else - new_var->var_part[i].cur_loc = NULL; + new_var->var_part[i].cur_loc = var->var_part[i].cur_loc; } dst_can_be_shared = false; @@ -1240,6 +1257,17 @@ unshare_variable (dataflow_set *set, void **slot, variable var, else if (set->traversed_vars && set->vars != set->traversed_vars) slot = shared_hash_find_slot_noinsert (set->vars, var->dv); *slot = new_var; + if (var->in_changed_variables) + { + void **cslot + = htab_find_slot_with_hash (changed_variables, var->dv, + dv_htab_hash (var->dv), NO_INSERT); + gcc_assert (*cslot == (void *) var); + var->in_changed_variables = false; + variable_htab_free (var); + *cslot = new_var; + new_var->in_changed_variables = true; + } return slot; } @@ -1791,23 +1819,6 @@ variable_union (void **slot, void *data) *dstp = src; - /* If CUR_LOC of some variable part is not the first element of - the location chain we are going to change it so we have to make - a copy of the variable. */ - for (k = 0; k < src->n_var_parts; k++) - { - gcc_assert (!src->var_part[k].loc_chain - == !src->var_part[k].cur_loc); - if (src->var_part[k].loc_chain) - { - gcc_assert (src->var_part[k].cur_loc); - if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc) - break; - } - } - if (k < src->n_var_parts) - dstp = unshare_variable (set, dstp, src, VAR_INIT_STATUS_UNKNOWN); - /* Continue traversing the hash table. */ return 1; } @@ -1841,7 +1852,7 @@ variable_union (void **slot, void *data) { location_chain nnode; - if (dst->refcount != 1 || shared_hash_shared (set->vars)) + if (shared_var_p (dst, set->vars)) { dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_INITIALIZED); @@ -1871,8 +1882,6 @@ variable_union (void **slot, void *data) dnode = *nodep; } - dst->var_part[0].cur_loc = dst->var_part[0].loc_chain->loc; - return 1; } @@ -1897,8 +1906,7 @@ variable_union (void **slot, void *data) thus there are at most MAX_VAR_PARTS different offsets. */ gcc_assert (dv_onepart_p (dst->dv) ? k == 1 : k <= MAX_VAR_PARTS); - if ((dst->refcount > 1 || shared_hash_shared (set->vars)) - && dst->n_var_parts != k) + if (dst->n_var_parts != k && shared_var_p (dst, set->vars)) { dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN); dst = (variable)*dstp; @@ -1925,7 +1933,7 @@ variable_union (void **slot, void *data) /* If DST is shared compare the location chains. If they are different we will modify the chain in DST with high probability so make a copy of DST. */ - if (dst->refcount > 1 || shared_hash_shared (set->vars)) + if (shared_var_p (dst, set->vars)) { for (node = src->var_part[i].loc_chain, node2 = dst->var_part[j].loc_chain; node && node2; @@ -2139,13 +2147,7 @@ variable_union (void **slot, void *data) dst->var_part[k].offset = src->var_part[i].offset; i--; } - - /* We are at the basic block boundary when computing union - so set the CUR_LOC to be the first element of the chain. */ - if (dst->var_part[k].loc_chain) - dst->var_part[k].cur_loc = dst->var_part[k].loc_chain->loc; - else - dst->var_part[k].cur_loc = NULL; + dst->var_part[k].cur_loc = NULL; } if (flag_var_tracking_uninit) @@ -2165,39 +2167,6 @@ variable_union (void **slot, void *data) return 1; } -/* Like variable_union, but only used when doing dataflow_set_union - into an empty hashtab. To allow sharing, dst is initially shared - with src (so all variables are "copied" from src to dst hashtab), - so only unshare_variable for variables that need canonicalization - are needed. */ - -static int -variable_canonicalize (void **slot, void *data) -{ - variable src; - dataflow_set *set = (dataflow_set *) data; - int k; - - src = *(variable *) slot; - - /* If CUR_LOC of some variable part is not the first element of - the location chain we are going to change it so we have to make - a copy of the variable. */ - for (k = 0; k < src->n_var_parts; k++) - { - gcc_assert (!src->var_part[k].loc_chain == !src->var_part[k].cur_loc); - if (src->var_part[k].loc_chain) - { - gcc_assert (src->var_part[k].cur_loc); - if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc) - break; - } - } - if (k < src->n_var_parts) - slot = unshare_variable (set, slot, src, VAR_INIT_STATUS_UNKNOWN); - return 1; -} - /* Compute union of dataflow sets SRC and DST and store it to DST. */ static void @@ -2212,9 +2181,6 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src) { shared_hash_destroy (dst->vars); dst->vars = shared_hash_copy (src->vars); - dst->traversed_vars = dst->vars; - htab_traverse (shared_hash_htab (dst->vars), variable_canonicalize, dst); - dst->traversed_vars = NULL; } else htab_traverse (shared_hash_htab (src->vars), variable_union, dst); @@ -2479,6 +2445,18 @@ loc_cmp (rtx x, rtx y) gcc_assert (GET_MODE (x) == GET_MODE (y)); + if (GET_CODE (x) == DEBUG_EXPR) + { + if (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)) + < DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y))) + return -1; +#ifdef ENABLE_CHECKING + gcc_assert (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)) + > DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y))); +#endif + return 1; + } + fmt = GET_RTX_FORMAT (code); for (i = 0; i < GET_RTX_LENGTH (code); i++) switch (fmt[i]) @@ -2718,6 +2696,13 @@ canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED) decl_or_value dv = var->dv; location_chain node, next; +#ifdef ENABLE_RTL_CHECKING + int i; + for (i = 0; i < var->n_var_parts; i++) + gcc_assert (var->var_part[0].cur_loc == NULL); + gcc_assert (!var->cur_loc_changed && !var->in_changed_variables); +#endif + if (!dv_onepart_p (dv)) return 1; @@ -3080,9 +3065,11 @@ variable_merge_over_cur (void **s1slot, void *data) dvar->dv = dv; dvar->refcount = 1; dvar->n_var_parts = 1; + dvar->cur_loc_changed = false; + dvar->in_changed_variables = false; dvar->var_part[0].offset = 0; dvar->var_part[0].loc_chain = node; - dvar->var_part[0].cur_loc = node->loc; + dvar->var_part[0].cur_loc = NULL; dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash, @@ -3212,6 +3199,8 @@ variable_merge_over_cur (void **s1slot, void *data) var->dv = dv; var->refcount = 1; var->n_var_parts = 1; + var->cur_loc_changed = false; + var->in_changed_variables = false; var->var_part[0].offset = 0; var->var_part[0].loc_chain = NULL; var->var_part[0].cur_loc = NULL; @@ -3248,11 +3237,7 @@ variable_merge_over_cur (void **s1slot, void *data) dst_can_be_shared = false; } else - { - if (dvar->refcount == 1) - dvar->var_part[0].cur_loc = dvar->var_part[0].loc_chain->loc; - dst_can_be_shared = false; - } + dst_can_be_shared = false; return 1; } @@ -3276,7 +3261,7 @@ variable_merge_over_src (void **s2slot, void *data) void **dstp = shared_hash_find_slot (dst->vars, dv); *dstp = s2var; s2var->refcount++; - return variable_canonicalize (dstp, dst); + return 1; } dsm->src_onepart_cnt++; @@ -3746,13 +3731,14 @@ dataflow_set_preserve_mem_locs (void **slot, void *data) { tree decl = dv_as_decl (var->dv); location_chain loc, *locp; + bool changed = false; if (!var->n_var_parts) return 1; gcc_assert (var->n_var_parts == 1); - if (var->refcount > 1 || shared_hash_shared (set->vars)) + if (shared_var_p (var, set->vars)) { for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) { @@ -3809,6 +3795,12 @@ dataflow_set_preserve_mem_locs (void **slot, void *data) { if (old_loc != loc->loc && emit_notes) { + if (old_loc == var->var_part[0].cur_loc) + { + changed = true; + var->var_part[0].cur_loc = NULL; + var->cur_loc_changed = true; + } add_value_chains (var->dv, loc->loc); remove_value_chains (var->dv, old_loc); } @@ -3817,7 +3809,15 @@ dataflow_set_preserve_mem_locs (void **slot, void *data) } if (emit_notes) - remove_value_chains (var->dv, old_loc); + { + remove_value_chains (var->dv, old_loc); + if (old_loc == var->var_part[0].cur_loc) + { + changed = true; + var->var_part[0].cur_loc = NULL; + var->cur_loc_changed = true; + } + } *locp = loc->next; pool_free (loc_chain_pool, loc); } @@ -3827,8 +3827,10 @@ dataflow_set_preserve_mem_locs (void **slot, void *data) var->n_var_parts--; if (emit_notes && dv_is_value_p (var->dv)) remove_cselib_value_chains (var->dv); - variable_was_changed (var, set); + changed = true; } + if (changed) + variable_was_changed (var, set); } return 1; @@ -3850,7 +3852,7 @@ dataflow_set_remove_mem_locs (void **slot, void *data) gcc_assert (var->n_var_parts == 1); - if (var->refcount > 1 || shared_hash_shared (set->vars)) + if (shared_var_p (var, set->vars)) { for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) if (GET_CODE (loc->loc) == MEM @@ -3881,9 +3883,12 @@ dataflow_set_remove_mem_locs (void **slot, void *data) /* If we have deleted the location which was last emitted we have to emit new location so add the variable to set of changed variables. */ - if (var->var_part[0].cur_loc - && rtx_equal_p (loc->loc, var->var_part[0].cur_loc)) - changed = true; + if (var->var_part[0].cur_loc == loc->loc) + { + changed = true; + var->var_part[0].cur_loc = NULL; + var->cur_loc_changed = true; + } pool_free (loc_chain_pool, loc); } @@ -3892,14 +3897,10 @@ dataflow_set_remove_mem_locs (void **slot, void *data) var->n_var_parts--; if (emit_notes && dv_is_value_p (var->dv)) remove_cselib_value_chains (var->dv); - gcc_assert (changed); + changed = true; } 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); - } + variable_was_changed (var, set); } return 1; @@ -3987,13 +3988,10 @@ onepart_variable_different_p (variable var1, variable var2) return lc1 != lc2; } -/* Return true if variables VAR1 and VAR2 are different. - If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each - variable part. */ +/* Return true if variables VAR1 and VAR2 are different. */ static bool -variable_different_p (variable var1, variable var2, - bool compare_current_location) +variable_different_p (variable var1, variable var2) { int i; @@ -4007,16 +4005,6 @@ variable_different_p (variable var1, variable var2, { if (var1->var_part[i].offset != var2->var_part[i].offset) return true; - if (compare_current_location) - { - if (!((REG_P (var1->var_part[i].cur_loc) - && REG_P (var2->var_part[i].cur_loc) - && (REGNO (var1->var_part[i].cur_loc) - == REGNO (var2->var_part[i].cur_loc))) - || rtx_equal_p (var1->var_part[i].cur_loc, - var2->var_part[i].cur_loc))) - return true; - } /* One-part values have locations in a canonical order. */ if (i == 0 && var1->var_part[i].offset == 0 && dv_onepart_p (var1->dv)) { @@ -4058,7 +4046,7 @@ dataflow_set_different_1 (void **slot, void *data) return 0; } - if (variable_different_p (var1, var2, false)) + if (variable_different_p (var1, var2)) { dataflow_set_different_value = true; @@ -5978,6 +5966,7 @@ variable_was_changed (variable var, dataflow_set *set) if (emit_notes) { void **slot; + bool old_cur_loc_changed = false; /* Remember this decl or VALUE has been added to changed_variables. */ set_dv_changed (var->dv, true); @@ -5986,6 +5975,14 @@ variable_was_changed (variable var, dataflow_set *set) var->dv, hash, INSERT); + if (*slot) + { + variable old_var = (variable) *slot; + gcc_assert (old_var->in_changed_variables); + old_var->in_changed_variables = false; + old_cur_loc_changed = old_var->cur_loc_changed; + variable_htab_free (*slot); + } if (set && var->n_var_parts == 0) { variable empty_var; @@ -5994,12 +5991,19 @@ variable_was_changed (variable var, dataflow_set *set) empty_var->dv = var->dv; empty_var->refcount = 1; empty_var->n_var_parts = 0; + empty_var->cur_loc_changed = true; + empty_var->in_changed_variables = true; *slot = empty_var; goto drop_var; } else { var->refcount++; + var->in_changed_variables = true; + /* If within processing one uop a variable is deleted + and then readded, we need to assume it has changed. */ + if (old_cur_loc_changed) + var->cur_loc_changed = true; *slot = var; } } @@ -6082,6 +6086,8 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, var->dv = dv; var->refcount = 1; var->n_var_parts = 1; + var->cur_loc_changed = false; + var->in_changed_variables = false; var->var_part[0].offset = offset; var->var_part[0].loc_chain = NULL; var->var_part[0].cur_loc = NULL; @@ -6179,7 +6185,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, if (r == 0) return slot; - if (var->refcount > 1 || shared_hash_shared (set->vars)) + if (shared_var_p (var, set->vars)) { slot = unshare_variable (set, slot, var, initialized); var = (variable)*slot; @@ -6218,7 +6224,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, else { /* We have to make a copy of a shared variable. */ - if (var->refcount > 1 || shared_hash_shared (set->vars)) + if (shared_var_p (var, set->vars)) { slot = unshare_variable (set, slot, var, initialized); var = (variable)*slot; @@ -6230,7 +6236,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, /* We have not found the location part, new one will be created. */ /* We have to make a copy of the shared variable. */ - if (var->refcount > 1 || shared_hash_shared (set->vars)) + if (shared_var_p (var, set->vars)) { slot = unshare_variable (set, slot, var, initialized); var = (variable)*slot; @@ -6267,6 +6273,11 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, initialized = node->init; if (node->set_src != NULL && set_src == NULL) set_src = node->set_src; + if (var->var_part[pos].cur_loc == node->loc) + { + var->var_part[pos].cur_loc = NULL; + var->cur_loc_changed = true; + } pool_free (loc_chain_pool, node); *nextp = next; break; @@ -6291,10 +6302,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, /* If no location was emitted do so. */ if (var->var_part[pos].cur_loc == NULL) - { - var->var_part[pos].cur_loc = loc; - variable_was_changed (var, set); - } + variable_was_changed (var, set); return slot; } @@ -6422,7 +6430,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot, location_chain *nextp; bool changed; - if (var->refcount > 1 || shared_hash_shared (set->vars)) + if (shared_var_p (var, set->vars)) { /* If the variable contains the location part we have to make a copy of the variable. */ @@ -6442,6 +6450,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot, } /* Delete the location part. */ + changed = false; nextp = &var->var_part[pos].loc_chain; for (node = *nextp; node; node = next) { @@ -6452,6 +6461,15 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot, { if (emit_notes && pos == 0 && dv_onepart_p (var->dv)) remove_value_chains (var->dv, node->loc); + /* If we have deleted the location which was last emitted + we have to emit new location so add the variable to set + of changed variables. */ + if (var->var_part[pos].cur_loc == node->loc) + { + changed = true; + var->var_part[pos].cur_loc = NULL; + var->cur_loc_changed = true; + } pool_free (loc_chain_pool, node); *nextp = next; break; @@ -6460,28 +6478,16 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot, nextp = &node->next; } - /* If we have deleted the location which was last emitted - we have to emit new location so add the variable to set - of changed variables. */ - if (var->var_part[pos].cur_loc - && ((REG_P (loc) - && REG_P (var->var_part[pos].cur_loc) - && REGNO (loc) == REGNO (var->var_part[pos].cur_loc)) - || rtx_equal_p (loc, var->var_part[pos].cur_loc))) - { - changed = true; - if (var->var_part[pos].loc_chain) - var->var_part[pos].cur_loc = var->var_part[pos].loc_chain->loc; - } - else - changed = false; - if (var->var_part[pos].loc_chain == NULL) { - gcc_assert (changed); + changed = true; var->n_var_parts--; - if (emit_notes && var->n_var_parts == 0 && dv_is_value_p (var->dv)) - remove_cselib_value_chains (var->dv); + if (emit_notes) + { + var->cur_loc_changed = true; + if (var->n_var_parts == 0 && dv_is_value_p (var->dv)) + remove_cselib_value_chains (var->dv); + } while (pos < var->n_var_parts) { var->var_part[pos] = var->var_part[pos + 1]; @@ -6510,6 +6516,27 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv, slot = delete_slot_part (set, loc, slot, offset); } +/* Structure for passing some other parameters to function + vt_expand_loc_callback. */ +struct expand_loc_callback_data +{ + /* The variables and values active at this point. */ + htab_t vars; + + /* True in vt_expand_loc_dummy calls, no rtl should be allocated. + Non-NULL should be returned if vt_expand_loc would return + non-NULL in that case, NULL otherwise. cur_loc_changed should be + computed and cur_loc recomputed when possible (but just once + per emit_notes_for_changes call). */ + bool dummy; + + /* True if expansion of subexpressions had to recompute some + VALUE/DEBUG_EXPR_DECL's cur_loc or used a VALUE/DEBUG_EXPR_DECL + whose cur_loc has been already recomputed during current + emit_notes_for_changes call. */ + bool cur_loc_changed; +}; + /* Callback for cselib_expand_value, that looks for expressions holding the value in the var-tracking hash tables. Return X for standard processing, anything else is to be used as-is. */ @@ -6517,7 +6544,10 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv, static rtx vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data) { - htab_t vars = (htab_t)data; + struct expand_loc_callback_data *elcd + = (struct expand_loc_callback_data *) data; + bool dummy = elcd->dummy; + bool cur_loc_changed = elcd->cur_loc_changed; decl_or_value dv; variable var; location_chain loc; @@ -6526,11 +6556,6 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data) switch (GET_CODE (x)) { case SUBREG: - subreg = SUBREG_REG (x); - - if (GET_CODE (SUBREG_REG (x)) != VALUE) - return x; - subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs, max_depth - 1, vt_expand_loc_callback, data); @@ -6538,13 +6563,16 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data) if (!subreg) return NULL; + if (dummy) + return pc_rtx; + result = simplify_gen_subreg (GET_MODE (x), subreg, GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x)); /* Invalid SUBREGs are ok in debug info. ??? We could try alternate expansions for the VALUE as well. */ - if (!result && (REG_P (subreg) || MEM_P (subreg))) + if (!result) result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x)); return result; @@ -6566,25 +6594,78 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data) if (VALUE_RECURSED_INTO (x)) return NULL; - var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv)); + var = (variable) htab_find_with_hash (elcd->vars, dv, dv_htab_hash (dv)); if (!var) - return xret; + { + if (dummy && dv_changed_p (dv)) + elcd->cur_loc_changed = true; + return xret; + } if (var->n_var_parts == 0) - return xret; + { + if (dummy) + elcd->cur_loc_changed = true; + return xret; + } gcc_assert (var->n_var_parts == 1); VALUE_RECURSED_INTO (x) = true; result = NULL; - for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) + if (var->var_part[0].cur_loc) { - result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth, - vt_expand_loc_callback, vars); + if (dummy) + { + if (cselib_dummy_expand_value_rtx_cb (var->var_part[0].cur_loc, regs, + max_depth, + vt_expand_loc_callback, data)) + result = pc_rtx; + } + else + result = cselib_expand_value_rtx_cb (var->var_part[0].cur_loc, regs, + max_depth, + vt_expand_loc_callback, data); if (result) - break; + set_dv_changed (dv, false); + } + if (!result && dv_changed_p (dv)) + { + set_dv_changed (dv, false); + for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) + if (loc->loc == var->var_part[0].cur_loc) + continue; + else if (dummy) + { + elcd->cur_loc_changed = cur_loc_changed; + if (cselib_dummy_expand_value_rtx_cb (loc->loc, regs, max_depth, + vt_expand_loc_callback, + data)) + { + result = pc_rtx; + break; + } + else + { + result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth, + vt_expand_loc_callback, + data); + if (result) + break; + } + } + if (dummy && (result || var->var_part[0].cur_loc)) + var->cur_loc_changed = true; + var->var_part[0].cur_loc = loc ? loc->loc : NULL_RTX; + } + if (dummy) + { + if (var->cur_loc_changed) + elcd->cur_loc_changed = true; + else if (!result && var->var_part[0].cur_loc == NULL_RTX) + elcd->cur_loc_changed = cur_loc_changed; } VALUE_RECURSED_INTO (x) = false; @@ -6600,18 +6681,46 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data) static rtx vt_expand_loc (rtx loc, htab_t vars) { + struct expand_loc_callback_data data; + if (!MAY_HAVE_DEBUG_INSNS) return loc; + data.vars = vars; + data.dummy = false; + data.cur_loc_changed = false; loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 5, - vt_expand_loc_callback, vars); + vt_expand_loc_callback, &data); if (loc && MEM_P (loc)) loc = targetm.delegitimize_address (loc); - return loc; } +/* Like vt_expand_loc, but only return true/false (whether vt_expand_loc + would succeed or not, without actually allocating new rtxes. */ + +static bool +vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed) +{ + struct expand_loc_callback_data data; + bool ret; + + gcc_assert (MAY_HAVE_DEBUG_INSNS); + data.vars = vars; + data.dummy = true; + data.cur_loc_changed = false; + ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, 5, + vt_expand_loc_callback, &data); + *pcur_loc_changed = data.cur_loc_changed; + return ret; +} + +#ifdef ENABLE_RTL_CHECKING +/* Used to verify that cur_loc_changed updating is safe. */ +static struct pointer_map_t *emitted_notes; +#endif + /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains additional parameters: WHERE specifies whether the note shall be emitted before or after instruction INSN. */ @@ -6623,7 +6732,7 @@ emit_note_insn_var_location (void **varp, void *data) rtx insn = ((emit_note_data *)data)->insn; enum emit_note_where where = ((emit_note_data *)data)->where; htab_t vars = ((emit_note_data *)data)->vars; - rtx note; + rtx note, note_vl; int i, j, n_var_parts; bool complete; enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED; @@ -6632,20 +6741,34 @@ emit_note_insn_var_location (void **varp, void *data) HOST_WIDE_INT offsets[MAX_VAR_PARTS]; rtx loc[MAX_VAR_PARTS]; tree decl; + location_chain lc; if (dv_is_value_p (var->dv)) - goto clear; + goto value_or_debug_decl; decl = dv_as_decl (var->dv); if (TREE_CODE (decl) == DEBUG_EXPR_DECL) - goto clear; - - gcc_assert (decl); + goto value_or_debug_decl; complete = true; last_limit = 0; n_var_parts = 0; + if (!MAY_HAVE_DEBUG_STMTS) + { + for (i = 0; i < var->n_var_parts; i++) + if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain) + { + var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc; + var->cur_loc_changed = true; + } + if (var->n_var_parts == 0) + var->cur_loc_changed = true; + } +#ifndef ENABLE_RTL_CHECKING + if (!var->cur_loc_changed) + goto clear; +#endif for (i = 0; i < var->n_var_parts; i++) { enum machine_mode mode, wider_mode; @@ -6659,15 +6782,26 @@ emit_note_insn_var_location (void **varp, void *data) else if (last_limit > var->var_part[i].offset) continue; offsets[n_var_parts] = var->var_part[i].offset; - loc2 = vt_expand_loc (var->var_part[i].loc_chain->loc, vars); + if (!var->var_part[i].cur_loc) + { + complete = false; + continue; + } + loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars); if (!loc2) { complete = false; continue; } loc[n_var_parts] = loc2; - mode = GET_MODE (var->var_part[i].loc_chain->loc); - initialized = var->var_part[i].loc_chain->init; + mode = GET_MODE (var->var_part[i].cur_loc); + for (lc = var->var_part[i].loc_chain; lc; lc = lc->next) + if (var->var_part[i].cur_loc == lc->loc) + { + initialized = lc->init; + break; + } + gcc_assert (lc); last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); /* Attempt to merge adjacent registers or memory. */ @@ -6677,11 +6811,12 @@ emit_note_insn_var_location (void **varp, void *data) break; if (j < var->n_var_parts && wider_mode != VOIDmode - && mode == GET_MODE (var->var_part[j].loc_chain->loc) + && var->var_part[j].cur_loc + && mode == GET_MODE (var->var_part[j].cur_loc) && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts])) - && (loc2 = vt_expand_loc (var->var_part[j].loc_chain->loc, vars)) - && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2) - && last_limit == var->var_part[j].offset) + && last_limit == var->var_part[j].offset + && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars)) + && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2)) { rtx new_loc = NULL; @@ -6740,31 +6875,20 @@ emit_note_insn_var_location (void **varp, void *data) if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit)) complete = false; - if (where != EMIT_NOTE_BEFORE_INSN) - { - note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn); - if (where == EMIT_NOTE_AFTER_CALL_INSN) - NOTE_DURING_CALL_P (note) = true; - } - else - note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn); - if (! flag_var_tracking_uninit) initialized = VAR_INIT_STATUS_INITIALIZED; + note_vl = NULL_RTX; if (!complete) - { - NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, decl, - NULL_RTX, (int) initialized); - } + note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX, + (int) initialized); else if (n_var_parts == 1) { rtx expr_list = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0])); - NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, decl, - expr_list, - (int) initialized); + note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list, + (int) initialized); } else if (n_var_parts) { @@ -6776,17 +6900,64 @@ emit_note_insn_var_location (void **varp, void *data) parallel = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (n_var_parts, loc)); - NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, decl, - parallel, - (int) initialized); + note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, + parallel, (int) initialized); } +#ifdef ENABLE_RTL_CHECKING + if (note_vl) + { + void **note_slot = pointer_map_insert (emitted_notes, decl); + rtx pnote = (rtx) *note_slot; + if (!var->cur_loc_changed && (pnote || PAT_VAR_LOCATION_LOC (note_vl))) + { + gcc_assert (pnote); + gcc_assert (rtx_equal_p (PAT_VAR_LOCATION_LOC (pnote), + PAT_VAR_LOCATION_LOC (note_vl))); + } + *note_slot = (void *) note_vl; + } + if (!var->cur_loc_changed) + goto clear; +#endif + + if (where != EMIT_NOTE_BEFORE_INSN) + { + note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn); + if (where == EMIT_NOTE_AFTER_CALL_INSN) + NOTE_DURING_CALL_P (note) = true; + } + else + note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn); + NOTE_VAR_LOCATION (note) = note_vl; + clear: set_dv_changed (var->dv, false); + var->cur_loc_changed = false; + gcc_assert (var->in_changed_variables); + var->in_changed_variables = false; htab_clear_slot (changed_variables, varp); /* Continue traversing the hash table. */ return 1; + + value_or_debug_decl: + if (dv_changed_p (var->dv) && var->n_var_parts) + { + location_chain lc; + bool cur_loc_changed; + + if (var->var_part[0].cur_loc + && vt_expand_loc_dummy (var->var_part[0].cur_loc, vars, + &cur_loc_changed)) + goto clear; + for (lc = var->var_part[0].loc_chain; lc; lc = lc->next) + if (lc->loc != var->var_part[0].cur_loc + && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed)) + break; + var->var_part[0].cur_loc = lc ? lc->loc : NULL_RTX; + } + goto clear; } DEF_VEC_P (variable); @@ -6858,6 +7029,48 @@ check_changed_vars_2 (variable var, htab_t htab) } } +/* For each changed decl (except DEBUG_EXPR_DECLs) recompute + cur_loc if needed (and cur_loc of all VALUEs and DEBUG_EXPR_DECLs + it needs and are also in changed variables) and track whether + cur_loc (or anything it uses to compute location) had to change + during the current emit_notes_for_changes call. */ + +static int +check_changed_vars_3 (void **slot, void *data) +{ + variable var = (variable) *slot; + htab_t vars = (htab_t) data; + int i; + location_chain lc; + bool cur_loc_changed; + + if (dv_is_value_p (var->dv) + || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL) + return 1; + + for (i = 0; i < var->n_var_parts; i++) + { + if (var->var_part[i].cur_loc + && vt_expand_loc_dummy (var->var_part[i].cur_loc, vars, + &cur_loc_changed)) + { + if (cur_loc_changed) + var->cur_loc_changed = true; + continue; + } + for (lc = var->var_part[i].loc_chain; lc; lc = lc->next) + if (lc->loc != var->var_part[i].cur_loc + && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed)) + break; + if (lc || var->var_part[i].cur_loc) + var->cur_loc_changed = true; + var->var_part[i].cur_loc = lc ? lc->loc : NULL_RTX; + } + if (var->n_var_parts == 0) + var->cur_loc_changed = true; + return 1; +} + /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes shall be emitted before of after instruction INSN. */ @@ -6881,6 +7094,7 @@ emit_notes_for_changes (rtx insn, enum emit_note_where where, while (VEC_length (variable, changed_variables_stack) > 0) check_changed_vars_2 (VEC_pop (variable, changed_variables_stack), htab); + htab_traverse (changed_variables, check_changed_vars_3, htab); } data.insn = insn; @@ -6912,6 +7126,8 @@ emit_notes_for_differences_1 (void **slot, void *data) empty_var->dv = old_var->dv; empty_var->refcount = 0; empty_var->n_var_parts = 0; + empty_var->cur_loc_changed = false; + empty_var->in_changed_variables = false; if (dv_onepart_p (old_var->dv)) { location_chain lc; @@ -6923,8 +7139,10 @@ emit_notes_for_differences_1 (void **slot, void *data) remove_cselib_value_chains (old_var->dv); } variable_was_changed (empty_var, NULL); + /* Continue traversing the hash table. */ + return 1; } - else if (variable_different_p (old_var, new_var, true)) + if (variable_different_p (old_var, new_var)) { if (dv_onepart_p (old_var->dv)) { @@ -6949,6 +7167,33 @@ emit_notes_for_differences_1 (void **slot, void *data) } variable_was_changed (new_var, NULL); } + /* Update cur_loc. */ + if (old_var != new_var) + { + int i; + for (i = 0; i < new_var->n_var_parts; i++) + { + new_var->var_part[i].cur_loc = NULL; + if (old_var->n_var_parts != new_var->n_var_parts + || old_var->var_part[i].offset != new_var->var_part[i].offset) + new_var->cur_loc_changed = true; + else if (old_var->var_part[i].cur_loc != NULL) + { + location_chain lc; + rtx cur_loc = old_var->var_part[i].cur_loc; + + for (lc = new_var->var_part[i].loc_chain; lc; lc = lc->next) + if (lc->loc == cur_loc + || rtx_equal_p (cur_loc, lc->loc)) + { + new_var->var_part[i].cur_loc = lc->loc; + break; + } + if (lc == NULL) + new_var->cur_loc_changed = true; + } + } + } /* Continue traversing the hash table. */ return 1; @@ -6968,6 +7213,7 @@ emit_notes_for_differences_2 (void **slot, void *data) dv_htab_hash (new_var->dv)); if (!old_var) { + int i; /* Variable has appeared. */ if (dv_onepart_p (new_var->dv)) { @@ -6979,6 +7225,8 @@ emit_notes_for_differences_2 (void **slot, void *data) if (dv_is_value_p (new_var->dv)) add_cselib_value_chains (new_var->dv); } + for (i = 0; i < new_var->n_var_parts; i++) + new_var->var_part[i].cur_loc = NULL; variable_was_changed (new_var, NULL); } @@ -7283,6 +7531,9 @@ vt_emit_notes (void) basic_block bb; dataflow_set cur; +#ifdef ENABLE_RTL_CHECKING + emitted_notes = pointer_map_create (); +#endif gcc_assert (!htab_elements (changed_variables)); /* Free memory occupied by the out hash tables, as they aren't used @@ -7324,6 +7575,9 @@ vt_emit_notes (void) if (MAY_HAVE_DEBUG_INSNS) VEC_free (variable, heap, changed_variables_stack); +#ifdef ENABLE_RTL_CHECKING + pointer_map_destroy (emitted_notes); +#endif emit_notes = false; } |