[PATCH] emit-rtl.c: Allow splitting of RTX_FRAME_RELATED_P insns?
Senthil Kumar
senthil.thecoder@gmail.com
Fri Aug 7 09:00:26 GMT 2020
Hi,
I'm working on converting the AVR backend to MODE_CC, following
the steps described for case #2 in the CC0 transition wiki page,
and I've implemented the first three bullet
points (https://github.com/saaadhu/gcc-avr-cc0/tree/avr-cc0-squashed). With
the below patch, there are zero regressions (for mega and xmega
subarchs) compared to the current mainline, as of yesterday.
The wiki suggests using post-reload splitters, so that's the
direction I took, but I ran into an issue where split_insn
bails out early if RTX_FRAME_RELATED_P is true - this means
that splits for REG_CC clobbering insns with
RTX_FRAME_RELATED_P will never execute, resulting in a
could-not-split insn ICE in the final stage.
I see that the recog.c:peep2_attempt allows splitting of a
RTX_FRAME_RELATED_P insn, provided the result of the split is a
single insn. Would it be ok to modify try_split also to
allow those kinds of insns (tentative patch attached, code
copied over from peep2_attempt, only setting old and new_insn)? Or is there
a different approach to fix this?
Regards
Senthil
gcc/ChangeLog:
* emit-rtl.c (try_split): Allow splitting
certain RTX_FRAME_RELATED_P insns.
diff --git gcc/emit-rtl.c gcc/emit-rtl.c
index f9b0e9714d9..7cf5704cf14 100644
--- gcc/emit-rtl.c
+++ 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,87 @@ 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 results in more than one insn */
+ if (RTX_FRAME_RELATED_P (trial))
+ {
+ if (split_insn_count != 1)
+ return trial;
+
+ // Copy from recog.c:peep2_attempt
+ bool any_note = false;
+ rtx note;
+ rtx_insn *new_insn = seq;
+ rtx_insn *old_insn = trial;
+
+ /* 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);
+ }
+
+
/* 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);
More information about the Gcc-patches
mailing list