On Thu, 11 Apr 2019, Jakub Jelinek wrote: > On Thu, Apr 11, 2019 at 09:54:24AM +0200, Richard Biener wrote: > > > The following patch just punts if we find loads from stack slots in > > > between > > > where they are pushed and the const/pure call. In addition to that, I've > > > outlined the same largish sequence that had 3 copies in the function > > > already > > > and I'd need to add 4th copy, so in the end the dce.c changes are removing > > > more than adding: > > > 1 file changed, 118 insertions(+), 135 deletions(-) > > > > The refactoring itself is probably OK (and if done separately > > makes reviewing easier). > > Here is just the refactoring, ok for trunk?
OK. Thanks, Richard. > 2019-04-11 Jakub Jelinek <ja...@redhat.com> > > PR rtl-optimization/89965 > * dce.c (sp_based_mem_offset): New function. > (find_call_stack_args): Use sp_based_mem_offset. > > --- gcc/dce.c.jj 2019-04-11 10:26:18.509365653 +0200 > +++ gcc/dce.c 2019-04-11 10:30:00.436705065 +0200 > @@ -272,6 +272,58 @@ check_argument_store (HOST_WIDE_INT size > return true; > } > > +/* If MEM has sp address, return 0, if it has sp + const address, > + return that const, if it has reg address where reg is set to sp + const > + and FAST is false, return const, otherwise return > + INTTYPE_MINUMUM (HOST_WIDE_INT). */ > + > +static HOST_WIDE_INT > +sp_based_mem_offset (rtx_call_insn *call_insn, const_rtx mem, bool fast) > +{ > + HOST_WIDE_INT off = 0; > + rtx addr = XEXP (mem, 0); > + if (GET_CODE (addr) == PLUS > + && REG_P (XEXP (addr, 0)) > + && CONST_INT_P (XEXP (addr, 1))) > + { > + off = INTVAL (XEXP (addr, 1)); > + addr = XEXP (addr, 0); > + } > + if (addr == stack_pointer_rtx) > + return off; > + > + if (!REG_P (addr) || fast) > + return INTTYPE_MINIMUM (HOST_WIDE_INT); > + > + /* If not fast, use chains to see if addr wasn't set to sp + offset. */ > + df_ref use; > + FOR_EACH_INSN_USE (use, call_insn) > + if (rtx_equal_p (addr, DF_REF_REG (use))) > + break; > + > + if (use == NULL) > + return INTTYPE_MINIMUM (HOST_WIDE_INT); > + > + struct df_link *defs; > + for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) > + if (! DF_REF_IS_ARTIFICIAL (defs->ref)) > + break; > + > + if (defs == NULL) > + return INTTYPE_MINIMUM (HOST_WIDE_INT); > + > + rtx set = single_set (DF_REF_INSN (defs->ref)); > + if (!set) > + return INTTYPE_MINIMUM (HOST_WIDE_INT); > + > + if (GET_CODE (SET_SRC (set)) != PLUS > + || XEXP (SET_SRC (set), 0) != stack_pointer_rtx > + || !CONST_INT_P (XEXP (SET_SRC (set), 1))) > + return INTTYPE_MINIMUM (HOST_WIDE_INT); > + > + off += INTVAL (XEXP (SET_SRC (set), 1)); > + return off; > +} > > /* Try to find all stack stores of CALL_INSN arguments if > ACCUMULATE_OUTGOING_ARGS. If all stack stores have been found > @@ -309,58 +361,13 @@ find_call_stack_args (rtx_call_insn *cal > if (GET_CODE (XEXP (p, 0)) == USE > && MEM_P (XEXP (XEXP (p, 0), 0))) > { > - rtx mem = XEXP (XEXP (p, 0), 0), addr; > - HOST_WIDE_INT off = 0, size; > + rtx mem = XEXP (XEXP (p, 0), 0); > + HOST_WIDE_INT size; > if (!MEM_SIZE_KNOWN_P (mem) || !MEM_SIZE (mem).is_constant (&size)) > return false; > - addr = XEXP (mem, 0); > - if (GET_CODE (addr) == PLUS > - && REG_P (XEXP (addr, 0)) > - && CONST_INT_P (XEXP (addr, 1))) > - { > - off = INTVAL (XEXP (addr, 1)); > - addr = XEXP (addr, 0); > - } > - if (addr != stack_pointer_rtx) > - { > - if (!REG_P (addr)) > - return false; > - /* If not fast, use chains to see if addr wasn't set to > - sp + offset. */ > - if (!fast) > - { > - df_ref use; > - struct df_link *defs; > - rtx set; > - > - FOR_EACH_INSN_USE (use, call_insn) > - if (rtx_equal_p (addr, DF_REF_REG (use))) > - break; > - > - if (use == NULL) > - return false; > - > - for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) > - if (! DF_REF_IS_ARTIFICIAL (defs->ref)) > - break; > - > - if (defs == NULL) > - return false; > - > - set = single_set (DF_REF_INSN (defs->ref)); > - if (!set) > - return false; > - > - if (GET_CODE (SET_SRC (set)) != PLUS > - || XEXP (SET_SRC (set), 0) != stack_pointer_rtx > - || !CONST_INT_P (XEXP (SET_SRC (set), 1))) > - return false; > - > - off += INTVAL (XEXP (SET_SRC (set), 1)); > - } > - else > - return false; > - } > + HOST_WIDE_INT off = sp_based_mem_offset (call_insn, mem, fast); > + if (off == INTTYPE_MINIMUM (HOST_WIDE_INT)) > + return false; > min_sp_off = MIN (min_sp_off, off); > max_sp_off = MAX (max_sp_off, off + size); > } > @@ -376,51 +383,19 @@ find_call_stack_args (rtx_call_insn *cal > if (GET_CODE (XEXP (p, 0)) == USE > && MEM_P (XEXP (XEXP (p, 0), 0))) > { > - rtx mem = XEXP (XEXP (p, 0), 0), addr; > - HOST_WIDE_INT off = 0, byte, size; > + rtx mem = XEXP (XEXP (p, 0), 0); > /* Checked in the previous iteration. */ > - size = MEM_SIZE (mem).to_constant (); > - addr = XEXP (mem, 0); > - if (GET_CODE (addr) == PLUS > - && REG_P (XEXP (addr, 0)) > - && CONST_INT_P (XEXP (addr, 1))) > - { > - off = INTVAL (XEXP (addr, 1)); > - addr = XEXP (addr, 0); > - } > - if (addr != stack_pointer_rtx) > - { > - df_ref use; > - struct df_link *defs; > - rtx set; > - > - FOR_EACH_INSN_USE (use, call_insn) > - if (rtx_equal_p (addr, DF_REF_REG (use))) > - break; > - > - for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) > - if (! DF_REF_IS_ARTIFICIAL (defs->ref)) > - break; > - > - set = single_set (DF_REF_INSN (defs->ref)); > - off += INTVAL (XEXP (SET_SRC (set), 1)); > - } > - for (byte = off; byte < off + size; byte++) > - { > - if (!bitmap_set_bit (sp_bytes, byte - min_sp_off)) > - gcc_unreachable (); > - } > + HOST_WIDE_INT size = MEM_SIZE (mem).to_constant (); > + HOST_WIDE_INT off = sp_based_mem_offset (call_insn, mem, fast); > + gcc_checking_assert (off != INTTYPE_MINIMUM (HOST_WIDE_INT)); > + for (HOST_WIDE_INT byte = off; byte < off + size; byte++) > + if (!bitmap_set_bit (sp_bytes, byte - min_sp_off)) > + gcc_unreachable (); > } > > - /* Walk backwards, looking for argument stores. The search stops > - when seeing another call, sp adjustment or memory store other than > - argument store. */ > ret = false; > for (insn = PREV_INSN (call_insn); insn; insn = prev_insn) > { > - rtx set, mem, addr; > - HOST_WIDE_INT off; > - > if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn))) > prev_insn = NULL; > else > @@ -432,61 +407,17 @@ find_call_stack_args (rtx_call_insn *cal > if (!NONDEBUG_INSN_P (insn)) > continue; > > - set = single_set (insn); > + rtx set = single_set (insn); > if (!set || SET_DEST (set) == stack_pointer_rtx) > break; > > if (!MEM_P (SET_DEST (set))) > continue; > > - mem = SET_DEST (set); > - addr = XEXP (mem, 0); > - off = 0; > - if (GET_CODE (addr) == PLUS > - && REG_P (XEXP (addr, 0)) > - && CONST_INT_P (XEXP (addr, 1))) > - { > - off = INTVAL (XEXP (addr, 1)); > - addr = XEXP (addr, 0); > - } > - if (addr != stack_pointer_rtx) > - { > - if (!REG_P (addr)) > - break; > - if (!fast) > - { > - df_ref use; > - struct df_link *defs; > - rtx set; > - > - FOR_EACH_INSN_USE (use, insn) > - if (rtx_equal_p (addr, DF_REF_REG (use))) > - break; > - > - if (use == NULL) > - break; > - > - for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) > - if (! DF_REF_IS_ARTIFICIAL (defs->ref)) > - break; > - > - if (defs == NULL) > - break; > - > - set = single_set (DF_REF_INSN (defs->ref)); > - if (!set) > - break; > - > - if (GET_CODE (SET_SRC (set)) != PLUS > - || XEXP (SET_SRC (set), 0) != stack_pointer_rtx > - || !CONST_INT_P (XEXP (SET_SRC (set), 1))) > - break; > - > - off += INTVAL (XEXP (SET_SRC (set), 1)); > - } > - else > - break; > - } > + rtx mem = SET_DEST (set); > + HOST_WIDE_INT off = sp_based_mem_offset (call_insn, mem, fast); > + if (off == INTTYPE_MINIMUM (HOST_WIDE_INT)) > + break; > > HOST_WIDE_INT size; > if (!MEM_SIZE_KNOWN_P (mem) > > > Jakub > -- Richard Biener <rguent...@suse.de> SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)