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)) return false;
&& 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;
}
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,40 +383,14 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, ...@@ -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 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))) if (!bitmap_set_bit (sp_bytes, byte - min_sp_off))
{ gcc_unreachable ();
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 ();
}
} }
/* Walk backwards, looking for argument stores. The search stops /* 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, ...@@ -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,61 +410,17 @@ find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, ...@@ -432,61 +410,17 @@ 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 break;
&& 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;
}
HOST_WIDE_INT size; HOST_WIDE_INT size;
if (!MEM_SIZE_KNOWN_P (mem) if (!MEM_SIZE_KNOWN_P (mem)
......
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