On Jun 16, 2012, "H.J. Lu" <hjl.to...@gmail.com> wrote: > If I understand it correctly, the new approach fails to handle push > properly.
It's actually cselib that didn't deal with push properly, so it thinks incoming stack arguments may be clobbered by them. But that's not the whole story, unfortunately. I still don't have a complete fix for the problem, but I have some patches that restore nearly all of the passes. The first one extends RTX alias analysis so that cselib can recognize that (mem:SI ARGP) and (mem:SI (plus (and (plus ARGP #-4) #-32) #-4)) don't alias. Before the patch, we'd go for infinite sized objects upon AND. The second introduces an entry-point equivalence between ARGP and SP, so that SP references in push and stack-align sequences can be canonicalized to ARGP-based. The third introduces address canonicalization that uses information in the dataflow variable set in addition to the static cselib table. This is the one I'm still working on, because some expressions still fail to canonicalize to ARGP although they could. The fourth removes a now-redundant equivalence from the dynamic table; the required information is always preserved in the static table. I've regstrapped (and checked results! :-) all of these on x86_64-linux-gnu and i686-linux-gnu. It fixes all visible regressions in x86_64-linux-gnu, and nearly all on i686-linux-gnu. May I check these in and keep on working to complete the fix, or should I revert the original patch and come back only with a patchset that fixes all debug info regressions?
for gcc/ChangeLog from Alexandre Oliva <aol...@redhat.com> PR debug/53671 PR debug/49888 * alias.c (memrefs_conflict_p): Improve handling of AND for alignment. Index: gcc/alias.c =================================================================== --- gcc/alias.c.orig 2012-06-17 22:52:27.551102225 -0300 +++ gcc/alias.c 2012-06-17 22:59:00.674994588 -0300 @@ -2103,17 +2103,31 @@ memrefs_conflict_p (int xsize, rtx x, in at least as large as the alignment, assume no other overlap. */ if (GET_CODE (x) == AND && CONST_INT_P (XEXP (x, 1))) { - if (GET_CODE (y) == AND || ysize < -INTVAL (XEXP (x, 1))) + HOST_WIDE_INT sc = INTVAL (XEXP (x, 1)); + unsigned HOST_WIDE_INT uc = sc; + if (xsize > 0 && sc < 0 && -uc == (uc & -uc)) + { + xsize -= sc + 1; + c -= sc; + } + else if (GET_CODE (y) == AND || ysize < -INTVAL (XEXP (x, 1))) xsize = -1; return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)), ysize, y, c); } if (GET_CODE (y) == AND && CONST_INT_P (XEXP (y, 1))) { + HOST_WIDE_INT sc = INTVAL (XEXP (y, 1)); + unsigned HOST_WIDE_INT uc = sc; + if (ysize > 0 && sc < 0 && -uc == (uc & -uc)) + { + ysize -= sc + 1; + c += sc; + } /* ??? If we are indexing far enough into the array/structure, we may yet be able to determine that we can not overlap. But we also need to that we are far enough from the end not to overlap a following reference, so we do nothing with that for now. */ - if (GET_CODE (x) == AND || xsize < -INTVAL (XEXP (y, 1))) + else if (GET_CODE (x) == AND || xsize < -INTVAL (XEXP (y, 1))) ysize = -1; return memrefs_conflict_p (xsize, x, ysize, canon_rtx (XEXP (y, 0)), c); }
for gcc/ChangeLog from Alexandre Oliva <aol...@redhat.com> PR debug/53671 PR debug/49888 * var-tracking.c (vt_initialize): Record initial offset between arg pointer and stack pointer. Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c.orig 2012-06-17 23:00:45.793675979 -0300 +++ gcc/var-tracking.c 2012-06-17 23:01:02.525351931 -0300 @@ -9507,6 +9507,41 @@ vt_initialize (void) valvar_pool = NULL; } + if (MAY_HAVE_DEBUG_INSNS) + { + rtx reg, expr; + int ofst; + cselib_val *val; + +#ifdef FRAME_POINTER_CFA_OFFSET + reg = frame_pointer_rtx; + ofst = FRAME_POINTER_CFA_OFFSET (current_function_decl); +#else + reg = arg_pointer_rtx; + ofst = ARG_POINTER_CFA_OFFSET (current_function_decl); +#endif + + ofst -= INCOMING_FRAME_SP_OFFSET; + + val = cselib_lookup_from_insn (reg, GET_MODE (reg), 1, + VOIDmode, get_insns ()); + preserve_value (val); + cselib_preserve_cfa_base_value (val, REGNO (reg)); + expr = plus_constant (GET_MODE (stack_pointer_rtx), + stack_pointer_rtx, -ofst); + cselib_add_permanent_equiv (val, expr, get_insns ()); + + if (ofst) + { + val = cselib_lookup_from_insn (stack_pointer_rtx, + GET_MODE (stack_pointer_rtx), 1, + VOIDmode, get_insns ()); + preserve_value (val); + expr = plus_constant (GET_MODE (reg), reg, ofst); + cselib_add_permanent_equiv (val, expr, get_insns ()); + } + } + /* In order to factor out the adjustments made to the stack pointer or to the hard frame pointer and thus be able to use DW_OP_fbreg operations instead of individual location lists, we're going to rewrite MEMs based
for gcc/ChangeLog from Alexandre Oliva <aol...@redhat.com> 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. Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c.orig 2012-06-17 23:01:02.525351931 -0300 +++ gcc/var-tracking.c 2012-06-17 23:01:06.839010574 -0300 @@ -1955,6 +1955,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 (mode, 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. */ @@ -1988,9 +2126,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) @@ -2009,9 +2145,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; @@ -2052,7 +2186,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),
for gcc/ChangeLog from Alexandre Oliva <aol...@redhat.com> PR debug/53671 PR debug/49888 * var-tracking.c (vt_init_cfa_base): Drop redundant recording of CFA base. Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c.orig 2012-06-18 08:44:13.459569497 -0300 +++ gcc/var-tracking.c 2012-06-18 08:55:31.023984364 -0300 @@ -9582,9 +9582,6 @@ vt_init_cfa_base (void) VOIDmode, get_insns ()); preserve_value (val); cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx)); - var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, cfa_base_rtx, - VAR_INIT_STATUS_INITIALIZED, dv_from_value (val->val_rtx), - 0, NULL_RTX, INSERT); } /* Allocate and initialize the data structures for variable tracking
-- Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/ You must be the change you wish to see in the world. -- Gandhi Be Free! -- http://FSFLA.org/ FSF Latin America board member Free Software Evangelist Red Hat Brazil Compiler Engineer