diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1066146b2e5..e5e2290ab1a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2020-04-09 Jakub Jelinek + + PR debug/94495 + * cselib.h (cselib_record_sp_cfa_base_equiv, + cselib_sp_derived_value_p): Declare. + * cselib.c (cselib_record_sp_cfa_base_equiv, + cselib_sp_derived_value_p): New functions. + * var-tracking.c (add_stores): Don't record MO_VAL_SET for + cselib_sp_derived_value_p values. + (vt_initialize): Call cselib_record_sp_cfa_base_equiv at the + start of extended basic blocks other than the first one + for !frame_pointer_needed functions. + 2020-04-09 Richard Sandiford * doc/sourcebuild.texi (aarch64_sve_hw, aarch64_sve128_hw) diff --git a/gcc/cselib.c b/gcc/cselib.c index 0de683617d1..3692feb13a2 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -2665,6 +2665,64 @@ cselib_have_permanent_equivalences (void) return cselib_any_perm_equivs; } +/* Record stack_pointer_rtx to be equal to + (plus:P cfa_base_preserved_val offset). Used by var-tracking + at the start of basic blocks for !frame_pointer_needed functions. */ + +void +cselib_record_sp_cfa_base_equiv (HOST_WIDE_INT offset, rtx_insn *insn) +{ + rtx sp_derived_value = NULL_RTX; + for (struct elt_loc_list *l = cfa_base_preserved_val->locs; l; l = l->next) + if (GET_CODE (l->loc) == VALUE + && SP_DERIVED_VALUE_P (l->loc)) + { + sp_derived_value = l->loc; + break; + } + else if (GET_CODE (l->loc) == PLUS + && GET_CODE (XEXP (l->loc, 0)) == VALUE + && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) + && CONST_INT_P (XEXP (l->loc, 1))) + { + sp_derived_value = XEXP (l->loc, 0); + offset = offset + UINTVAL (XEXP (l->loc, 1)); + break; + } + if (sp_derived_value == NULL_RTX) + return; + cselib_val *val + = cselib_lookup_from_insn (plus_constant (Pmode, sp_derived_value, offset), + Pmode, 1, VOIDmode, insn); + if (val != NULL) + cselib_record_set (stack_pointer_rtx, val, NULL); +} + +/* Return true if V is SP_DERIVED_VALUE_P (or SP_DERIVED_VALUE_P + CONST_INT) + that can be expressed using cfa_base_preserved_val + CONST_INT. */ + +bool +cselib_sp_derived_value_p (cselib_val *v) +{ + if (!SP_DERIVED_VALUE_P (v->val_rtx)) + for (struct elt_loc_list *l = v->locs; l; l = l->next) + if (GET_CODE (l->loc) == PLUS + && GET_CODE (XEXP (l->loc, 0)) == VALUE + && SP_DERIVED_VALUE_P (XEXP (l->loc, 0)) + && CONST_INT_P (XEXP (l->loc, 1))) + v = CSELIB_VAL_PTR (XEXP (l->loc, 0)); + if (!SP_DERIVED_VALUE_P (v->val_rtx)) + return false; + for (struct elt_loc_list *l = v->locs; l; l = l->next) + if (l->loc == cfa_base_preserved_val->val_rtx) + return true; + else if (GET_CODE (l->loc) == PLUS + && XEXP (l->loc, 0) == cfa_base_preserved_val->val_rtx + && CONST_INT_P (XEXP (l->loc, 1))) + return true; + return false; +} + /* There is no good way to determine how many elements there can be in a PARALLEL. Since it's fairly cheap, use a really large number. */ #define MAX_SETS (FIRST_PSEUDO_REGISTER * 2) diff --git a/gcc/cselib.h b/gcc/cselib.h index 1628e135fdb..adc6cc0b1bc 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -104,6 +104,8 @@ extern void cselib_add_permanent_equiv (cselib_val *, rtx, rtx_insn *); extern bool cselib_have_permanent_equivalences (void); extern void cselib_set_value_sp_based (cselib_val *); extern bool cselib_sp_based_value_p (cselib_val *); +extern void cselib_record_sp_cfa_base_equiv (HOST_WIDE_INT, rtx_insn *); +extern bool cselib_sp_derived_value_p (cselib_val *); extern void dump_cselib_table (FILE *); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 8274df98741..0d39326aa63 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -6117,6 +6117,19 @@ add_stores (rtx loc, const_rtx expr, void *cuip) && preserve) cselib_set_value_sp_based (v); + /* Don't record MO_VAL_SET for VALUEs that can be described using + cfa_base_rtx or cfa_base_rtx + CONST_INT, cselib already knows + all the needed equivalences and they shouldn't change depending + on which register holds that VALUE in some instruction. */ + if (!frame_pointer_needed + && cfa_base_rtx + && cselib_sp_derived_value_p (v)) + { + if (preserve) + preserve_value (v); + return; + } + nloc = replace_expr_with_values (oloc); if (nloc) oloc = nloc; @@ -10154,6 +10167,7 @@ vt_initialize (void) vt_add_function_parameters (); + bool record_sp_value = false; FOR_EACH_BB_FN (bb, cfun) { rtx_insn *insn; @@ -10168,6 +10182,15 @@ vt_initialize (void) cselib_get_next_uid ()); } + if (MAY_HAVE_DEBUG_BIND_INSNS + && cfa_base_rtx + && !frame_pointer_needed + && record_sp_value) + cselib_record_sp_cfa_base_equiv (-cfa_base_offset + - VTI (bb)->in.stack_adjust, + BB_HEAD (bb)); + record_sp_value = true; + first_bb = bb; for (;;) {