for gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
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.
===================================================================
@@ -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