Allow try_split to split RTX_FRAME_RELATED_P insns

Instead of rejecting RTX_FRAME_RELATED_P insns, allow try_split to split
such insns, provided the split is after reload, and the result of the split
is a single insn.

recog.c:peep2_attempt already splits an RTX_FRAME_RELATED_P insn splitting
to a single insn. This patch refactors existing code copying frame related
info to a separate function (copy_frame_info_to_split_insn) and calls it
from both peep2_attempt and try_split.

2020-08-21  Senthil Kumar Selvaraj  <saaadhu@gcc.gnu.org>

gcc/ChangeLog:

	* emit-rtl.c (try_split): Call copy_frame_info_to_split_insn
	to split certain RTX_FRAME_RELATED_P insns.
	* recog.c (copy_frame_info_to_split_insn): New function.
	(peep2_attempt): Split copying of frame related info of
	RTX_FRAME_RELATED_P insns into above function and call it.
	* recog.h (copy_frame_info_to_split_insn): Declare it.
This commit is contained in:
Senthil Kumar Selvaraj 2020-08-13 13:19:26 +05:30
parent 988fb2f597
commit e7d55c6b81
3 changed files with 90 additions and 65 deletions

View File

@ -3822,10 +3822,6 @@ try_split (rtx pat, rtx_insn *trial, int last)
int njumps = 0;
rtx_insn *call_insn = NULL;
/* We're not good at redistributing frame information. */
if (RTX_FRAME_RELATED_P (trial))
return trial;
if (any_condjump_p (trial)
&& (note = find_reg_note (trial, REG_BR_PROB, 0)))
split_branch_probability
@ -3842,6 +3838,7 @@ try_split (rtx pat, rtx_insn *trial, int last)
if (!seq)
return trial;
int split_insn_count = 0;
/* Avoid infinite loop if any insn of the result matches
the original pattern. */
insn_last = seq;
@ -3850,11 +3847,25 @@ try_split (rtx pat, rtx_insn *trial, int last)
if (INSN_P (insn_last)
&& rtx_equal_p (PATTERN (insn_last), pat))
return trial;
split_insn_count++;
if (!NEXT_INSN (insn_last))
break;
insn_last = NEXT_INSN (insn_last);
}
/* We're not good at redistributing frame information if
the split occurs before reload or if it results in more
than one insn. */
if (RTX_FRAME_RELATED_P (trial))
{
if (!reload_completed || split_insn_count != 1)
return trial;
rtx_insn *new_insn = seq;
rtx_insn *old_insn = trial;
copy_frame_info_to_split_insn (old_insn, new_insn);
}
/* We will be adding the new sequence to the function. The splitters
may have introduced invalid RTL sharing, so unshare the sequence now. */
unshare_all_rtl_in_chain (seq);

View File

@ -3277,6 +3277,78 @@ peep2_reinit_state (regset live)
COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
}
/* Copies frame related info of an insn (OLD_INSN) to the single
insn (NEW_INSN) that was obtained by splitting OLD_INSN. */
void
copy_frame_info_to_split_insn (rtx_insn *old_insn, rtx_insn *new_insn)
{
bool any_note = false;
rtx note;
if (!RTX_FRAME_RELATED_P (old_insn))
return;
RTX_FRAME_RELATED_P (new_insn) = 1;
/* Allow the backend to fill in a note during the split. */
for (note = REG_NOTES (new_insn); note ; note = XEXP (note, 1))
switch (REG_NOTE_KIND (note))
{
case REG_FRAME_RELATED_EXPR:
case REG_CFA_DEF_CFA:
case REG_CFA_ADJUST_CFA:
case REG_CFA_OFFSET:
case REG_CFA_REGISTER:
case REG_CFA_EXPRESSION:
case REG_CFA_RESTORE:
case REG_CFA_SET_VDRAP:
any_note = true;
break;
default:
break;
}
/* If the backend didn't supply a note, copy one over. */
if (!any_note)
for (note = REG_NOTES (old_insn); note ; note = XEXP (note, 1))
switch (REG_NOTE_KIND (note))
{
case REG_FRAME_RELATED_EXPR:
case REG_CFA_DEF_CFA:
case REG_CFA_ADJUST_CFA:
case REG_CFA_OFFSET:
case REG_CFA_REGISTER:
case REG_CFA_EXPRESSION:
case REG_CFA_RESTORE:
case REG_CFA_SET_VDRAP:
add_reg_note (new_insn, REG_NOTE_KIND (note), XEXP (note, 0));
any_note = true;
break;
default:
break;
}
/* If there still isn't a note, make sure the unwind info sees the
same expression as before the split. */
if (!any_note)
{
rtx old_set, new_set;
/* The old insn had better have been simple, or annotated. */
old_set = single_set (old_insn);
gcc_assert (old_set != NULL);
new_set = single_set (new_insn);
if (!new_set || !rtx_equal_p (new_set, old_set))
add_reg_note (new_insn, REG_FRAME_RELATED_EXPR, old_set);
}
/* Copy prologue/epilogue status. This is required in order to keep
proper placement of EPILOGUE_BEG and the DW_CFA_remember_state. */
maybe_copy_prologue_epilogue_insn (old_insn, new_insn);
}
/* While scanning basic block BB, we found a match of length MATCH_LEN,
starting at INSN. Perform the replacement, removing the old insns and
replacing them with ATTEMPT. Returns the last insn emitted, or NULL
@ -3297,9 +3369,6 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
old_insn = peep2_insn_data[peep2_current].insn;
if (RTX_FRAME_RELATED_P (old_insn))
{
bool any_note = false;
rtx note;
if (match_len != 0)
return NULL;
@ -3313,64 +3382,7 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
return NULL;
/* We have a 1-1 replacement. Copy over any frame-related info. */
RTX_FRAME_RELATED_P (new_insn) = 1;
/* Allow the backend to fill in a note during the split. */
for (note = REG_NOTES (new_insn); note ; note = XEXP (note, 1))
switch (REG_NOTE_KIND (note))
{
case REG_FRAME_RELATED_EXPR:
case REG_CFA_DEF_CFA:
case REG_CFA_ADJUST_CFA:
case REG_CFA_OFFSET:
case REG_CFA_REGISTER:
case REG_CFA_EXPRESSION:
case REG_CFA_RESTORE:
case REG_CFA_SET_VDRAP:
any_note = true;
break;
default:
break;
}
/* If the backend didn't supply a note, copy one over. */
if (!any_note)
for (note = REG_NOTES (old_insn); note ; note = XEXP (note, 1))
switch (REG_NOTE_KIND (note))
{
case REG_FRAME_RELATED_EXPR:
case REG_CFA_DEF_CFA:
case REG_CFA_ADJUST_CFA:
case REG_CFA_OFFSET:
case REG_CFA_REGISTER:
case REG_CFA_EXPRESSION:
case REG_CFA_RESTORE:
case REG_CFA_SET_VDRAP:
add_reg_note (new_insn, REG_NOTE_KIND (note), XEXP (note, 0));
any_note = true;
break;
default:
break;
}
/* If there still isn't a note, make sure the unwind info sees the
same expression as before the split. */
if (!any_note)
{
rtx old_set, new_set;
/* The old insn had better have been simple, or annotated. */
old_set = single_set (old_insn);
gcc_assert (old_set != NULL);
new_set = single_set (new_insn);
if (!new_set || !rtx_equal_p (new_set, old_set))
add_reg_note (new_insn, REG_FRAME_RELATED_EXPR, old_set);
}
/* Copy prologue/epilogue status. This is required in order to keep
proper placement of EPILOGUE_BEG and the DW_CFA_remember_state. */
maybe_copy_prologue_epilogue_insn (old_insn, new_insn);
copy_frame_info_to_split_insn (old_insn, new_insn);
}
/* If we are splitting a CALL_INSN, look for the CALL_INSN

View File

@ -150,6 +150,8 @@ extern rtx_insn *peephole2_insns (rtx, rtx_insn *, int *);
extern int store_data_bypass_p (rtx_insn *, rtx_insn *);
extern int if_test_bypass_p (rtx_insn *, rtx_insn *);
extern void copy_frame_info_to_split_insn (rtx_insn *, rtx_insn *);
#ifndef GENERATOR_FILE
/* Try recognizing the instruction INSN,
and return the code number that results.