[backport from gcc-4.8/trunk r188871 ] gcc/ 2012-06-21 Alexandre Oliva PR debug/53671 PR debug/49888 * var-tracking.c (vt_get_canonicalize_base): New. (vt_canonicalize_addr, vt_stack_offset_p): New. (vt_canon_true_dep): New. (drop_overlapping_mem_locs): Use vt_canon_true_dep. (clobber_overlaping_mems): Use vt_canonicalize_addr. --- gcc-4.7.1/gcc/var-tracking.c.~1~ 2012-08-12 13:15:52.000000000 +0200 +++ gcc-4.7.1/gcc/var-tracking.c 2012-08-12 13:17:14.000000000 +0200 @@ -1943,6 +1943,144 @@ var_regno_delete (dataflow_set *set, int *reg = NULL; } +/* Strip constant offsets and alignments off of LOC. Return the base + expression. */ + +static rtx +vt_get_canonicalize_base (rtx loc) +{ + while ((GET_CODE (loc) == PLUS + || GET_CODE (loc) == AND) + && GET_CODE (XEXP (loc, 1)) == CONST_INT + && (GET_CODE (loc) != AND + || INTVAL (XEXP (loc, 1)) < 0)) + loc = XEXP (loc, 0); + + return loc; +} + +/* Canonicalize LOC using equivalences from SET in addition to those + in the cselib static table. */ + +static rtx +vt_canonicalize_addr (dataflow_set *set, rtx oloc) +{ + HOST_WIDE_INT ofst = 0; + enum machine_mode mode = GET_MODE (oloc); + rtx loc = canon_rtx (get_addr (oloc)); + + /* Try to substitute a base VALUE for equivalent expressions as much + as possible. The goal here is to expand stack-related addresses + to one of the stack base registers, so that we can compare + addresses for overlaps. */ + while (GET_CODE (vt_get_canonicalize_base (loc)) == VALUE) + { + rtx x; + decl_or_value dv; + variable var; + location_chain l; + + while (GET_CODE (loc) == PLUS) + { + ofst += INTVAL (XEXP (loc, 1)); + loc = XEXP (loc, 0); + continue; + } + + /* Alignment operations can't normally be combined, so just + canonicalize the base and we're done. We'll normally have + only one stack alignment anyway. */ + if (GET_CODE (loc) == AND) + { + x = vt_canonicalize_addr (set, XEXP (loc, 0)); + if (x != XEXP (loc, 0)) + loc = gen_rtx_AND (mode, x, XEXP (loc, 1)); + loc = canon_rtx (get_addr (loc)); + break; + } + + x = canon_rtx (get_addr (loc)); + + /* We've made progress! Start over. */ + if (x != loc || GET_CODE (x) != VALUE) + { + loc = x; + continue; + } + + dv = dv_from_rtx (x); + var = (variable) htab_find_with_hash (shared_hash_htab (set->vars), + dv, dv_htab_hash (dv)); + if (!var) + break; + + /* Look for an improved equivalent expression. */ + for (l = var->var_part[0].loc_chain; l; l = l->next) + { + rtx base = vt_get_canonicalize_base (l->loc); + if (GET_CODE (base) == REG + || (GET_CODE (base) == VALUE + && canon_value_cmp (base, loc))) + { + loc = l->loc; + break; + } + } + + /* No luck with the dataflow set, so we're done. */ + if (!l) + break; + } + + /* Add OFST back in. */ + if (ofst) + { + /* Don't build new RTL if we can help it. */ + if (GET_CODE (oloc) == PLUS + && XEXP (oloc, 0) == loc + && INTVAL (XEXP (oloc, 1)) == ofst) + return oloc; + + loc = plus_constant (loc, ofst); + } + + return loc; +} + +/* Return true iff ADDR has a stack register as the base address. */ + +static inline bool +vt_stack_offset_p (rtx addr) +{ + rtx base = vt_get_canonicalize_base (addr); + + if (GET_CODE (base) != REG) + return false; + + return REGNO_PTR_FRAME_P (REGNO (base)); +} + +/* Return true iff there's a true dependence between MLOC and LOC. + MADDR must be a canonicalized version of MLOC's address. */ + +static inline bool +vt_canon_true_dep (dataflow_set *set, rtx mloc, rtx maddr, rtx loc) +{ + if (GET_CODE (loc) != MEM) + return false; + + if (!canon_true_dependence (mloc, GET_MODE (mloc), maddr, loc, NULL)) + return false; + + if (!MEM_EXPR (loc) && vt_stack_offset_p (maddr)) + { + rtx addr = vt_canonicalize_addr (set, XEXP (loc, 0)); + return canon_true_dependence (mloc, GET_MODE (mloc), maddr, loc, addr); + } + + return true; +} + /* Hold parameters for the hashtab traversal function drop_overlapping_mem_locs, see below. */ @@ -1976,9 +2114,7 @@ drop_overlapping_mem_locs (void **slot, 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 - && canon_true_dependence (mloc, GET_MODE (mloc), addr, - loc->loc, NULL)) + if (vt_canon_true_dep (set, mloc, addr, loc->loc)) break; if (!loc) @@ -1997,9 +2133,7 @@ drop_overlapping_mem_locs (void **slot, for (locp = &var->var_part[0].loc_chain, loc = *locp; loc; loc = *locp) { - if (GET_CODE (loc->loc) != MEM - || !canon_true_dependence (mloc, GET_MODE (mloc), addr, - loc->loc, NULL)) + if (!vt_canon_true_dep (set, mloc, addr, loc->loc)) { locp = &loc->next; continue; @@ -2040,7 +2174,7 @@ clobber_overlapping_mems (dataflow_set * coms.set = set; coms.loc = canon_rtx (loc); - coms.addr = canon_rtx (get_addr (XEXP (loc, 0))); + coms.addr = vt_canonicalize_addr (set, XEXP (loc, 0)); set->traversed_vars = set->vars; htab_traverse (shared_hash_htab (set->vars),