From: Jakub Jelinek Date: Thu, 11 Apr 2019 09:02:47 +0000 (+0200) Subject: re PR rtl-optimization/89965 (wrong code with -O -mtune=nano-x2 -fcaller-saves -fexpe... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1b4d15e8557be0a396e166f98c7f26397f3e1618;p=gcc.git re PR rtl-optimization/89965 (wrong code with -O -mtune=nano-x2 -fcaller-saves -fexpensive-optimizations -fno-tree-dce -fno-tree-ter) PR rtl-optimization/89965 * dce.c (sp_based_mem_offset): New function. (find_call_stack_args): Use sp_based_mem_offset. From-SVN: r270278 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 019fb3242f4..6c26bf76832 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-04-11 Jakub Jelinek + + PR rtl-optimization/89965 + * dce.c (sp_based_mem_offset): New function. + (find_call_stack_args): Use sp_based_mem_offset. + 2019-04-11 Jonathan Wakely * doc/invoke.texi (Optimize Options): Clarify -flive-patching docs. diff --git a/gcc/dce.c b/gcc/dce.c index 8fb109c7388..98063dc44ac 100644 --- a/gcc/dce.c +++ b/gcc/dce.c @@ -272,6 +272,58 @@ check_argument_store (HOST_WIDE_INT size, HOST_WIDE_INT off, 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 *call_insn, bool do_mark, bool fast, 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,40 +383,14 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, 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 @@ -418,9 +399,6 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, 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 +410,17 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, 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)