Allow try_split to split RTX_FRAME_RELATED_P insns
authorSenthil Kumar Selvaraj <saaadhu@gcc.gnu.org>
Thu, 13 Aug 2020 07:49:26 +0000 (13:19 +0530)
committerSenthil Kumar Selvaraj <saaadhu@gcc.gnu.org>
Fri, 21 Aug 2020 12:29:40 +0000 (17:59 +0530)
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.

gcc/emit-rtl.c
gcc/recog.c
gcc/recog.h

index f9b0e9714d9e5c8b11a0d16a81d1d9609aba90eb..3706f0a03fd8ccba7625e51012807333df69d99f 100644 (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);
index 25f19b1b1cf3f440047fbe56587aa0a9e066b5a1..ce83b7f52183c503a015c06dcfb9d189cf22871c 100644 (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
index 3e4b55bdf3f00618e846431b926ce49082a18b8c..ae3675f5c82168791b6dbafc62d0296c281b8b03 100644 (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.