combine.c (struct insn_link): New field `regno'.

* combine.c (struct insn_link): New field `regno'.
	(alloc_insn_link): New parameter `regno'.  Use it.
	(find_single_use): Check the new field.
	(can_combine_def_p, can_combine_use_p): New functions.  Split
	off from ...
	(create_log_links): ... here.  Correct data type of `regno'.
	Adjust call to alloc_insn_link.
	(adjust_for_new_dest): Find regno, use it in call to
	alloc_insn_link.
	(try_combine): Check reg_used_between_p when combining a PARALLEL
	as earlier insn.  Adjust call to alloc_insn_link.
	(distribute_links): Check the new field.

From-SVN: r218241
This commit is contained in:
Segher Boessenkool 2014-12-01 19:26:20 +01:00 committed by Segher Boessenkool
parent eeafb31957
commit 66d4b01246
2 changed files with 104 additions and 55 deletions

View File

@ -1,3 +1,18 @@
2014-12-01 Segher Boessenkool <segher@kernel.crashing.org>
* combine.c (struct insn_link): New field `regno'.
(alloc_insn_link): New parameter `regno'. Use it.
(find_single_use): Check the new field.
(can_combine_def_p, can_combine_use_p): New functions. Split
off from ...
(create_log_links): ... here. Correct data type of `regno'.
Adjust call to alloc_insn_link.
(adjust_for_new_dest): Find regno, use it in call to
alloc_insn_link.
(try_combine): Check reg_used_between_p when combining a PARALLEL
as earlier insn. Adjust call to alloc_insn_link.
(distribute_links): Check the new field.
2014-12-01 David Malcolm <dmalcolm@redhat.com> 2014-12-01 David Malcolm <dmalcolm@redhat.com>
PR jit/63854 PR jit/63854

View File

@ -328,6 +328,7 @@ static int *uid_insn_cost;
struct insn_link { struct insn_link {
rtx_insn *insn; rtx_insn *insn;
unsigned int regno;
struct insn_link *next; struct insn_link *next;
}; };
@ -346,12 +347,13 @@ static struct obstack insn_link_obstack;
/* Allocate a link. */ /* Allocate a link. */
static inline struct insn_link * static inline struct insn_link *
alloc_insn_link (rtx_insn *insn, struct insn_link *next) alloc_insn_link (rtx_insn *insn, unsigned int regno, struct insn_link *next)
{ {
struct insn_link *l struct insn_link *l
= (struct insn_link *) obstack_alloc (&insn_link_obstack, = (struct insn_link *) obstack_alloc (&insn_link_obstack,
sizeof (struct insn_link)); sizeof (struct insn_link));
l->insn = insn; l->insn = insn;
l->regno = regno;
l->next = next; l->next = next;
return l; return l;
} }
@ -686,7 +688,7 @@ find_single_use (rtx dest, rtx_insn *insn, rtx_insn **ploc)
if (INSN_P (next) && dead_or_set_p (next, dest)) if (INSN_P (next) && dead_or_set_p (next, dest))
{ {
FOR_EACH_LOG_LINK (link, next) FOR_EACH_LOG_LINK (link, next)
if (link->insn == insn) if (link->insn == insn && link->regno == REGNO (dest))
break; break;
if (link) if (link)
@ -982,6 +984,43 @@ delete_noop_moves (void)
} }
/* Return false if we do not want to (or cannot) combine DEF. */
static bool
can_combine_def_p (df_ref def)
{
/* Do not consider if it is pre/post modification in MEM. */
if (DF_REF_FLAGS (def) & DF_REF_PRE_POST_MODIFY)
return false;
unsigned int regno = DF_REF_REGNO (def);
/* Do not combine frame pointer adjustments. */
if ((regno == FRAME_POINTER_REGNUM
&& (!reload_completed || frame_pointer_needed))
#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
|| (regno == HARD_FRAME_POINTER_REGNUM
&& (!reload_completed || frame_pointer_needed))
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
)
return false;
return true;
}
/* Return false if we do not want to (or cannot) combine USE. */
static bool
can_combine_use_p (df_ref use)
{
/* Do not consider the usage of the stack pointer by function call. */
if (DF_REF_FLAGS (use) & DF_REF_CALL_STACK_USAGE)
return false;
return true;
}
/* Fill in log links field for all insns. */ /* Fill in log links field for all insns. */
static void static void
@ -1015,32 +1054,21 @@ create_log_links (void)
FOR_EACH_INSN_DEF (def, insn) FOR_EACH_INSN_DEF (def, insn)
{ {
int regno = DF_REF_REGNO (def); unsigned int regno = DF_REF_REGNO (def);
rtx_insn *use_insn; rtx_insn *use_insn;
if (!next_use[regno]) if (!next_use[regno])
continue; continue;
/* Do not consider if it is pre/post modification in MEM. */ if (!can_combine_def_p (def))
if (DF_REF_FLAGS (def) & DF_REF_PRE_POST_MODIFY)
continue;
/* Do not make the log link for frame pointer. */
if ((regno == FRAME_POINTER_REGNUM
&& (! reload_completed || frame_pointer_needed))
#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
|| (regno == HARD_FRAME_POINTER_REGNUM
&& (! reload_completed || frame_pointer_needed))
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
)
continue; continue;
use_insn = next_use[regno]; use_insn = next_use[regno];
if (BLOCK_FOR_INSN (use_insn) == bb) next_use[regno] = NULL;
{
if (BLOCK_FOR_INSN (use_insn) != bb)
continue;
/* flow.c claimed: /* flow.c claimed:
We don't build a LOG_LINK for hard registers contained We don't build a LOG_LINK for hard registers contained
@ -1048,34 +1076,24 @@ create_log_links (void)
we might wind up changing the semantics of the insn, we might wind up changing the semantics of the insn,
even if reload can make what appear to be valid even if reload can make what appear to be valid
assignments later. */ assignments later. */
if (regno >= FIRST_PSEUDO_REGISTER if (regno < FIRST_PSEUDO_REGISTER
|| asm_noperands (PATTERN (use_insn)) < 0) && asm_noperands (PATTERN (use_insn)) >= 0)
{ continue;
/* Don't add duplicate links between instructions. */ /* Don't add duplicate links between instructions. */
struct insn_link *links; struct insn_link *links;
FOR_EACH_LOG_LINK (links, use_insn) FOR_EACH_LOG_LINK (links, use_insn)
if (insn == links->insn) if (insn == links->insn && regno == links->regno)
break; break;
if (!links) if (!links)
LOG_LINKS (use_insn) LOG_LINKS (use_insn)
= alloc_insn_link (insn, LOG_LINKS (use_insn)); = alloc_insn_link (insn, regno, LOG_LINKS (use_insn));
}
}
next_use[regno] = NULL;
} }
FOR_EACH_INSN_USE (use, insn) FOR_EACH_INSN_USE (use, insn)
{ if (can_combine_use_p (use))
int regno = DF_REF_REGNO (use); next_use[DF_REF_REGNO (use)] = insn;
/* Do not consider the usage of the stack pointer
by function call. */
if (DF_REF_FLAGS (use) & DF_REF_CALL_STACK_USAGE)
continue;
next_use[regno] = insn;
}
} }
} }
@ -2347,7 +2365,19 @@ adjust_for_new_dest (rtx_insn *insn)
/* The new insn will have a destination that was previously the destination /* The new insn will have a destination that was previously the destination
of an insn just above it. Call distribute_links to make a LOG_LINK from of an insn just above it. Call distribute_links to make a LOG_LINK from
the next use of that destination. */ the next use of that destination. */
distribute_links (alloc_insn_link (insn, NULL));
rtx set = single_set (insn);
gcc_assert (set);
rtx reg = SET_DEST (set);
while (GET_CODE (reg) == ZERO_EXTRACT
|| GET_CODE (reg) == STRICT_LOW_PART
|| GET_CODE (reg) == SUBREG)
reg = XEXP (reg, 0);
gcc_assert (REG_P (reg));
distribute_links (alloc_insn_link (insn, REGNO (reg), NULL));
df_insn_rescan (insn); df_insn_rescan (insn);
} }
@ -2759,7 +2789,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
&& GET_CODE (XVECEXP (PATTERN (i2), 0, 1)) == SET && GET_CODE (XVECEXP (PATTERN (i2), 0, 1)) == SET
&& REG_P (SET_DEST (XVECEXP (PATTERN (i2), 0, 1))) && REG_P (SET_DEST (XVECEXP (PATTERN (i2), 0, 1)))
&& rtx_equal_p (XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 0), && rtx_equal_p (XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 0),
SET_SRC (XVECEXP (PATTERN (i2), 0, 1)))) SET_SRC (XVECEXP (PATTERN (i2), 0, 1)))
&& !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)), i2, i3)
&& !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 1)), i2, i3))
{ {
for (i = XVECLEN (PATTERN (i2), 0) - 1; i >= 2; i--) for (i = XVECLEN (PATTERN (i2), 0) - 1; i >= 2; i--)
if (GET_CODE (XVECEXP (PATTERN (i2), 0, i)) != CLOBBER) if (GET_CODE (XVECEXP (PATTERN (i2), 0, i)) != CLOBBER)
@ -2780,7 +2812,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0)); SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
SUBST (XEXP (SET_SRC (PATTERN (i2)), 0), SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
SET_DEST (PATTERN (i1))); SET_DEST (PATTERN (i1)));
SUBST_LINK (LOG_LINKS (i2), alloc_insn_link (i1, LOG_LINKS (i2))); unsigned int regno = REGNO (SET_DEST (PATTERN (i1)));
SUBST_LINK (LOG_LINKS (i2),
alloc_insn_link (i1, regno, LOG_LINKS (i2)));
} }
} }
#endif #endif
@ -13841,7 +13875,7 @@ distribute_links (struct insn_link *links)
struct insn_link *link2; struct insn_link *link2;
FOR_EACH_LOG_LINK (link2, place) FOR_EACH_LOG_LINK (link2, place)
if (link2->insn == link->insn) if (link2->insn == link->insn && link2->regno == link->regno)
break; break;
if (link2 == NULL) if (link2 == NULL)