for gcc/ChangeLog from Alexandre Oliva PR debug/53671 PR debug/49888 * var-tracking.c (attrs_list_by_loc_eq): New. (track_stack_pointer): New. (dataflow_set_merge): Use it. (vt_initialize): Record the initial stack pointer in the dataflow set. Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c.orig 2012-06-26 17:33:12.991323578 -0300 +++ gcc/var-tracking.c 2012-06-26 17:51:55.316453808 -0300 @@ -1462,6 +1462,17 @@ attrs_list_member (attrs list, decl_or_v return NULL; } +/* Return the entry whose LOC field equals LOC. */ + +static attrs +attrs_list_by_loc_eq (attrs list, rtx loc) +{ + for (; list; list = list->next) + if (list->loc == loc) + return list; + return NULL; +} + /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */ static void @@ -4028,6 +4039,86 @@ variable_merge_over_src (variable s2var, return 1; } +/* Add to DST any needed binding for the canonicalization of the stack + pointer to yield the same expression as in SRC1 and SRC2, if they + both yield the same expression. + + Return TRUE iff we found an equivalence. + + ??? The return value, that was useful during testing, ended up + unused, but this single-use static function will be inlined, and + then the return value computation will be optimized out, so I'm + leaving it in. + + ??? We use this kludge to avoid accidental aliasing between + incoming arguments and register-saving or outgoing-args pushes. We + shouldn't have to add explicit stack pointer tracking for that: + intersect_loc_chains ought to be able to take information from the + static cselib table and recognize additional equivalences, but we + don't have a sufficiently efficient algorithm to do that yet. */ + +static bool +track_stack_pointer (dataflow_set *dst, dataflow_set *src1, dataflow_set *src2) +{ + attrs dattr, s1attr, s2attr; + rtx daddr, s1addr, s2addr; + decl_or_value dv; + + for (dattr = dst->regs[STACK_POINTER_REGNUM]; + (dattr = attrs_list_by_loc_eq (dattr, stack_pointer_rtx)) + && (dattr->offset || !dv_is_value_p (dattr->dv)); + dattr = dattr->next) + ; + + for (s1attr = src1->regs[STACK_POINTER_REGNUM]; + (s1attr = attrs_list_by_loc_eq (s1attr, stack_pointer_rtx)) + && (s1attr->offset || !dv_is_value_p (s1attr->dv)); + s1attr = s1attr->next) + ; + if (!s1attr) + return false; + + for (s2attr = src2->regs[STACK_POINTER_REGNUM]; + (s2attr = attrs_list_by_loc_eq (s2attr, stack_pointer_rtx)) + && (s2attr->offset || !dv_is_value_p (s2attr->dv)); + s2attr = s2attr->next) + ; + if (!s2attr) + return false; + + if (dattr) + daddr = vt_canonicalize_addr (dst, dv_as_value (dattr->dv)); + else + daddr = NULL; + s1addr = vt_canonicalize_addr (src1, dv_as_value (s1attr->dv)); + s2addr = vt_canonicalize_addr (src2, dv_as_value (s2attr->dv)); + + if (!rtx_equal_p (s1addr, s2addr)) + return false; + + if (daddr && rtx_equal_p (daddr, s1addr)) + return true; + + dst_can_be_shared = false; + if (daddr) + dv = dattr->dv; + else if (vt_get_canonicalize_base (s1addr) + != (cfa_base_rtx ? cfa_base_rtx : arg_pointer_rtx)) + return false; + else + { + cselib_val *val = cselib_lookup (s1addr, GET_MODE (s1addr), 1, VOIDmode); + cselib_preserve_value (val); + dv = dv_from_value (val->val_rtx); + } + + var_reg_decl_set (dst, stack_pointer_rtx, + VAR_INIT_STATUS_INITIALIZED, + dv, 0, NULL_RTX, INSERT); + + return true; +} + /* Combine dataflow set information from SRC2 into DST, using PDST to carry over information across passes. */ @@ -4066,6 +4157,8 @@ dataflow_set_merge (dataflow_set *dst, d FOR_EACH_HTAB_ELEMENT (shared_hash_htab (dsm.cur->vars), var, variable, hi) variable_merge_over_cur (var, &dsm); + track_stack_pointer (dst, src1, src2); + if (dsm.src_onepart_cnt) dst_can_be_shared = false; @@ -9682,6 +9775,18 @@ vt_initialize (void) expr = plus_constant (GET_MODE (reg), reg, ofst); cselib_add_permanent_equiv (val, expr, get_insns ()); } + + /* VAL below will generally be the one set within the + conditional block, but if OFST happens to be zero, we'll be + happy to use the one corresponding to REG. + + ??? We shouldn't need this any more once dataflow merges + start using equivalences from the cselib table in addition to + those in dataflow sets. */ + var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, + stack_pointer_rtx, VAR_INIT_STATUS_INITIALIZED, + dv_from_value (val->val_rtx), 0, NULL_RTX, + INSERT); } /* In order to factor out the adjustments made to the stack pointer or to