https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92264
--- Comment #32 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Some incremental progress, but still ICEs... --- gcc/cselib.c 2020-03-20 17:42:02.333023994 +0100 +++ gcc/cselib.c 2020-03-20 19:23:33.506622424 +0100 @@ -58,6 +58,16 @@ static void cselib_invalidate_mem (rtx); static void cselib_record_set (rtx, cselib_val *, cselib_val *); static void cselib_record_sets (rtx_insn *); +static rtx autoinc_split (rtx, rtx *, machine_mode); + +#define PRESERVED_VALUE_P(RTX) \ + (RTL_FLAG_CHECK1 ("PRESERVED_VALUE_P", (RTX), VALUE)->unchanging) + +#define SP_BASED_VALUE_P(RTX) \ + (RTL_FLAG_CHECK1 ("SP_BASED_VALUE_P", (RTX), VALUE)->jump) + +#define SP_DERIVED_VALUE_P(RTX) \ + (RTL_FLAG_CHECK1 ("SP_DERIVED_VALUE_P", (RTX), VALUE)->call) struct expand_value_data { @@ -122,6 +132,13 @@ if (GET_CODE (x) == VALUE) return x == v->val_rtx; + if (SP_DERIVED_VALUE_P (v->val_rtx) && GET_MODE (x) == Pmode) + { + rtx xoff = NULL; + if (autoinc_split (x, &xoff, memmode) == v->val_rtx && xoff == NULL_RTX) + return true; + } + /* We don't guarantee that distinct rtx's have different hash values, so we need to do a comparison. */ for (l = v->locs; l; l = l->next) @@ -256,15 +273,6 @@ void (*cselib_record_sets_hook) (rtx_insn *insn, struct cselib_set *sets, int n_sets); -#define PRESERVED_VALUE_P(RTX) \ - (RTL_FLAG_CHECK1 ("PRESERVED_VALUE_P", (RTX), VALUE)->unchanging) - -#define SP_BASED_VALUE_P(RTX) \ - (RTL_FLAG_CHECK1 ("SP_BASED_VALUE_P", (RTX), VALUE)->jump) - -#define SP_DERIVED_VALUE_P(RTX) \ - (RTL_FLAG_CHECK1 ("SP_DERIVED_VALUE_P", (RTX), VALUE)->call) - /* Allocate a struct elt_list and fill in its two elements with the @@ -497,7 +505,7 @@ }; cselib_val **slot = cselib_preserved_hash_table->find_slot_with_hash (&lookup, - v->hash, INSERT); + v->hash, INSERT); gcc_assert (!*slot); *slot = v; } @@ -535,6 +543,28 @@ max_value_regs = hard_regno_nregs (regno, GET_MODE (cfa_base_preserved_val->locs->loc)); + + /* If cfa_base is sp + const_int, need to preserve also the + SP_DERIVED_VALUE_P value. */ + for (struct elt_loc_list *l = cfa_base_preserved_val->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))) + { + if (! invariant_or_equiv_p (CSELIB_VAL_PTR (XEXP (l->loc, 0)))) + { + rtx val = cfa_base_preserved_val->val_rtx; + rtx_insn *save_cselib_current_insn = cselib_current_insn; + cselib_current_insn = l->setting_insn; + new_elt_loc_list (CSELIB_VAL_PTR (XEXP (l->loc, 0)), + plus_constant (Pmode, val, + -UINTVAL (XEXP (l->loc, 1)))); + cselib_current_insn = save_cselib_current_insn; + } + break; + } } else { @@ -544,8 +574,7 @@ } if (cselib_preserve_constants) - cselib_hash_table->traverse <void *, preserve_constants_and_equivs> - (NULL); + cselib_hash_table->traverse <void *, preserve_constants_and_equivs> (NULL); else { cselib_hash_table->empty ();