diff options
author | Senthil Kumar Selvaraj <saaadhu@gcc.gnu.org> | 2020-08-13 13:19:26 +0530 |
---|---|---|
committer | Senthil Kumar Selvaraj <saaadhu@gcc.gnu.org> | 2020-08-21 17:59:40 +0530 |
commit | e7d55c6b81733335d81e35f7c0116bbdffccb682 (patch) | |
tree | 6e580a14c242d86acc268077652207657f7dcf5a | |
parent | 988fb2f597d67cdf3603654372c020c28448441f (diff) | |
download | gcc-e7d55c6b81733335d81e35f7c0116bbdffccb682.zip gcc-e7d55c6b81733335d81e35f7c0116bbdffccb682.tar.gz gcc-e7d55c6b81733335d81e35f7c0116bbdffccb682.tar.bz2 |
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.
-rw-r--r-- | gcc/emit-rtl.c | 19 | ||||
-rw-r--r-- | gcc/recog.c | 134 | ||||
-rw-r--r-- | gcc/recog.h | 2 |
3 files changed, 90 insertions, 65 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index f9b0e97..3706f0a 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -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); diff --git a/gcc/recog.c b/gcc/recog.c index 25f19b1..ce83b7f 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -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 diff --git a/gcc/recog.h b/gcc/recog.h index 3e4b55b..ae3675f 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -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. |