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:
parent
988fb2f597
commit
e7d55c6b81
@ -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);
|
||||
|
72
gcc/recog.c
72
gcc/recog.c
@ -3277,42 +3277,18 @@ peep2_reinit_state (regset live)
|
||||
COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
|
||||
}
|
||||
|
||||
/* 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
|
||||
if the replacement is rejected. */
|
||||
/* Copies frame related info of an insn (OLD_INSN) to the single
|
||||
insn (NEW_INSN) that was obtained by splitting OLD_INSN. */
|
||||
|
||||
static rtx_insn *
|
||||
peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
|
||||
{
|
||||
int i;
|
||||
rtx_insn *last, *before_try, *x;
|
||||
rtx eh_note, as_note;
|
||||
rtx_insn *old_insn;
|
||||
rtx_insn *new_insn;
|
||||
bool was_call = false;
|
||||
|
||||
/* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to
|
||||
match more than one insn, or to be split into more than one insn. */
|
||||
old_insn = peep2_insn_data[peep2_current].insn;
|
||||
if (RTX_FRAME_RELATED_P (old_insn))
|
||||
void
|
||||
copy_frame_info_to_split_insn (rtx_insn *old_insn, rtx_insn *new_insn)
|
||||
{
|
||||
bool any_note = false;
|
||||
rtx note;
|
||||
|
||||
if (match_len != 0)
|
||||
return NULL;
|
||||
if (!RTX_FRAME_RELATED_P (old_insn))
|
||||
return;
|
||||
|
||||
/* Look for one "active" insn. I.e. ignore any "clobber" insns that
|
||||
may be in the stream for the purpose of register allocation. */
|
||||
if (active_insn_p (attempt))
|
||||
new_insn = attempt;
|
||||
else
|
||||
new_insn = next_active_insn (attempt);
|
||||
if (next_active_insn (new_insn))
|
||||
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. */
|
||||
@ -3373,6 +3349,42 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
|
||||
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
|
||||
if the replacement is rejected. */
|
||||
|
||||
static rtx_insn *
|
||||
peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
|
||||
{
|
||||
int i;
|
||||
rtx_insn *last, *before_try, *x;
|
||||
rtx eh_note, as_note;
|
||||
rtx_insn *old_insn;
|
||||
rtx_insn *new_insn;
|
||||
bool was_call = false;
|
||||
|
||||
/* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to
|
||||
match more than one insn, or to be split into more than one insn. */
|
||||
old_insn = peep2_insn_data[peep2_current].insn;
|
||||
if (RTX_FRAME_RELATED_P (old_insn))
|
||||
{
|
||||
if (match_len != 0)
|
||||
return NULL;
|
||||
|
||||
/* Look for one "active" insn. I.e. ignore any "clobber" insns that
|
||||
may be in the stream for the purpose of register allocation. */
|
||||
if (active_insn_p (attempt))
|
||||
new_insn = attempt;
|
||||
else
|
||||
new_insn = next_active_insn (attempt);
|
||||
if (next_active_insn (new_insn))
|
||||
return NULL;
|
||||
|
||||
/* We have a 1-1 replacement. Copy over any frame-related info. */
|
||||
copy_frame_info_to_split_insn (old_insn, new_insn);
|
||||
}
|
||||
|
||||
/* If we are splitting a CALL_INSN, look for the CALL_INSN
|
||||
in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
|
||||
cfg-related call notes. */
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user