Commit 1b4d15e8 by Jakub Jelinek Committed by Jakub Jelinek

re PR rtl-optimization/89965 (wrong code with -O -mtune=nano-x2 -fcaller-saves…

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
parent ecb3e9a4
2019-04-11 Jakub Jelinek <jakub@redhat.com>
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 <jwakely@redhat.com> 2019-04-11 Jonathan Wakely <jwakely@redhat.com>
* doc/invoke.texi (Optimize Options): Clarify -flive-patching docs. * doc/invoke.texi (Optimize Options): Clarify -flive-patching docs.
......
...@@ -272,6 +272,58 @@ check_argument_store (HOST_WIDE_INT size, HOST_WIDE_INT off, ...@@ -272,6 +272,58 @@ check_argument_store (HOST_WIDE_INT size, HOST_WIDE_INT off,
return true; 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 /* Try to find all stack stores of CALL_INSN arguments if
ACCUMULATE_OUTGOING_ARGS. If all stack stores have been found 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, ...@@ -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 if (GET_CODE (XEXP (p, 0)) == USE
&& MEM_P (XEXP (XEXP (p, 0), 0))) && MEM_P (XEXP (XEXP (p, 0), 0)))
{ {
rtx mem = XEXP (XEXP (p, 0), 0), addr; rtx mem = XEXP (XEXP (p, 0), 0);
HOST_WIDE_INT off = 0, size; HOST_WIDE_INT size;
if (!MEM_SIZE_KNOWN_P (mem) || !MEM_SIZE (mem).is_constant (&size)) if (!MEM_SIZE_KNOWN_P (mem) || !MEM_SIZE (mem).is_constant (&size))
return false; return false;
addr = XEXP (mem, 0); HOST_WIDE_INT off = sp_based_mem_offset (call_insn, mem, fast);
if (GET_CODE (addr) == PLUS if (off == INTTYPE_MINIMUM (HOST_WIDE_INT))
&& 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; 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;
}
min_sp_off = MIN (min_sp_off, off); min_sp_off = MIN (min_sp_off, off);
max_sp_off = MAX (max_sp_off, off + size); max_sp_off = MAX (max_sp_off, off + size);
} }
...@@ -376,41 +383,15 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, ...@@ -376,41 +383,15 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
if (GET_CODE (XEXP (p, 0)) == USE if (GET_CODE (XEXP (p, 0)) == USE
&& MEM_P (XEXP (XEXP (p, 0), 0))) && MEM_P (XEXP (XEXP (p, 0), 0)))
{ {
rtx mem = XEXP (XEXP (p, 0), 0), addr; rtx mem = XEXP (XEXP (p, 0), 0);
HOST_WIDE_INT off = 0, byte, size;
/* Checked in the previous iteration. */ /* Checked in the previous iteration. */
size = MEM_SIZE (mem).to_constant (); HOST_WIDE_INT size = MEM_SIZE (mem).to_constant ();
addr = XEXP (mem, 0); HOST_WIDE_INT off = sp_based_mem_offset (call_insn, mem, fast);
if (GET_CODE (addr) == PLUS gcc_checking_assert (off != INTTYPE_MINIMUM (HOST_WIDE_INT));
&& REG_P (XEXP (addr, 0)) for (HOST_WIDE_INT byte = off; byte < off + size; byte++)
&& 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)) if (!bitmap_set_bit (sp_bytes, byte - min_sp_off))
gcc_unreachable (); gcc_unreachable ();
} }
}
/* Walk backwards, looking for argument stores. The search stops /* Walk backwards, looking for argument stores. The search stops
when seeing another call, sp adjustment or memory store other than when seeing another call, sp adjustment or memory store other than
...@@ -418,9 +399,6 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, ...@@ -418,9 +399,6 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
ret = false; ret = false;
for (insn = PREV_INSN (call_insn); insn; insn = prev_insn) 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))) if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn)))
prev_insn = NULL; prev_insn = NULL;
else else
...@@ -432,62 +410,18 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, ...@@ -432,62 +410,18 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
if (!NONDEBUG_INSN_P (insn)) if (!NONDEBUG_INSN_P (insn))
continue; continue;
set = single_set (insn); rtx set = single_set (insn);
if (!set || SET_DEST (set) == stack_pointer_rtx) if (!set || SET_DEST (set) == stack_pointer_rtx)
break; break;
if (!MEM_P (SET_DEST (set))) if (!MEM_P (SET_DEST (set)))
continue; continue;
mem = SET_DEST (set); rtx mem = SET_DEST (set);
addr = XEXP (mem, 0); HOST_WIDE_INT off = sp_based_mem_offset (call_insn, mem, fast);
off = 0; if (off == INTTYPE_MINIMUM (HOST_WIDE_INT))
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; 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;
}
HOST_WIDE_INT size; HOST_WIDE_INT size;
if (!MEM_SIZE_KNOWN_P (mem) if (!MEM_SIZE_KNOWN_P (mem)
|| !MEM_SIZE (mem).is_constant (&size) || !MEM_SIZE (mem).is_constant (&size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment