*** empty log message ***
authorTom Wood <wood@gnu.org>
Mon, 29 Jun 1992 16:04:35 +0000 (16:04 +0000)
committerTom Wood <wood@gnu.org>
Mon, 29 Jun 1992 16:04:35 +0000 (16:04 +0000)
From-SVN: r1336

gcc/final.c
gcc/function.c
gcc/reorg.c
gcc/rtl.c
gcc/rtl.h
gcc/sched.c
gcc/toplev.c

index 57ac44b2bf3c2389269e2378c7f8dcbc7e17336e..c58d03bbfd652b599ebba0d466222622a0fa89bd 100644 (file)
@@ -49,6 +49,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "rtl.h"
 #include "regs.h"
 #include "insn-config.h"
+#include "insn-flags.h"
 #include "insn-attr.h"
 #include "insn-codes.h"
 #include "recog.h"
@@ -111,6 +112,7 @@ void output_addr_const ();
 static void output_source_line ();
 rtx final_scan_insn ();
 void profile_function ();
+static void profile_after_prologue ();
 
 #ifdef HAVE_ATTR_length
 static int asm_insn_count ();
@@ -689,6 +691,20 @@ final_start_function (first, file, optimize)
     next_block_index = 1;
 #endif
 
+  /* If the machine represents the prologue as RTL, the profiling code must
+     be emitted when NOTE_INSN_PROLOGUE_END is scanned.  */
+#ifdef HAVE_prologue
+  if (! HAVE_prologue)
+#endif
+    profile_after_prologue (file);
+
+  profile_label_no++;
+}
+
+static void
+profile_after_prologue (file)
+     FILE *file;
+{
 #ifdef FUNCTION_BLOCK_PROFILER
   if (profile_block_flag)
     {
@@ -700,8 +716,6 @@ final_start_function (first, file, optimize)
   if (profile_flag)
     profile_function (file);
 #endif /* not PROFILE_BEFORE_PROLOGUE */
-
-  profile_label_no++;
 }
 
 void
@@ -926,6 +940,23 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
        break;
 
+      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
+       {
+#ifdef FUNCTION_END_PROLOGUE
+         FUNCTION_END_PROLOGUE (file);
+#endif
+         profile_after_prologue (file);
+         break;
+       }
+
+#ifdef FUNCTION_BEGIN_EPILOGUE
+      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
+       {
+         FUNCTION_BEGIN_EPILOGUE (file);
+         break;
+       }
+#endif
+
       if (write_symbols == NO_DEBUG)
        break;
       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
@@ -1061,7 +1092,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
 
     case BARRIER:
 #ifdef ASM_OUTPUT_ALIGN_CODE
-      ASM_OUTPUT_ALIGN_CODE (file);
+      /* Don't litter the assembler output with needless alignments.  A
+        BARRIER will be placed at the end of every function if HAVE_epilogue
+        is true.  */    
+      if (NEXT_INSN (insn))
+       ASM_OUTPUT_ALIGN_CODE (file);
 #endif
       break;
 
index fd69b1823e1abf24c9f3175bd4c53fae68a0afab..17d30ab659ec1bd8472a4347fb8b5cd3bb9e54e2 100644 (file)
@@ -53,6 +53,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "insn-config.h"
 #include "recog.h"
 #include "output.h"
+#include "basic-block.h"
 
 /* Round a value to the lowest integer less than it that is a multiple of
    the required alignment.  Avoid using division in case the value is
@@ -4076,3 +4077,209 @@ expand_function_end (filename, line)
      then you will lose.  */
   fixup_gotos (0, 0, 0, get_insns (), 0);
 }
+\f
+/* These arrays record the INSN_UIDs of the prologue and epilogue insns.  */
+
+static int *prologue;
+static int *epilogue;
+
+/* Create an array that records the INSN_UIDs of INSNS (either a sequence
+   or a single insn).  */
+
+static int *
+record_insns (insns)
+     rtx insns;
+{
+  int *vec;
+
+  if (GET_CODE (insns) == SEQUENCE)
+    {
+      int len = XVECLEN (insns, 0);
+      vec = (int *) oballoc ((len + 1) * sizeof (int));
+      vec[len] = 0;
+      while (--len >= 0)
+       vec[len] = INSN_UID (XVECEXP (insns, 0, len));
+    }
+  else
+    {
+      vec = (int *) oballoc (2 * sizeof (int));
+      vec[0] = INSN_UID (insns);
+      vec[1] = 0;
+    }
+  return vec;
+}
+
+/* Determine whether INSN is in the array of INSN_UIDs VEC.  */
+
+static rtx
+contains (insn, vec)
+     rtx insn;
+     int *vec;
+{
+  register int i, j;
+
+  if (GET_CODE (insn) == INSN
+      && GET_CODE (PATTERN (insn)) == SEQUENCE)
+    {
+      for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+       for (j = 0; vec[j]; j++)
+         if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == vec[j])
+           return XVECEXP (PATTERN (insn), 0, i);
+    }
+  else
+    {
+      for (j = 0; vec[j]; j++)
+       if (INSN_UID (insn) == vec[j])
+         return insn;
+    }
+  return 0;
+}
+
+/* Generate the prologe and epilogue RTL if the machine supports it.  Thread
+   this into place with notes indicating where the prologue ends and where
+   the epilogue begins.  Update the basic block information when possible.  */
+
+void
+thread_prologue_and_epilogue_insns (f)
+     rtx f;
+{
+#ifdef HAVE_prologue
+  if (HAVE_prologue)
+    {
+      rtx head, seq, insn;
+
+      /* The first insn (a NOTE_INSN_DELETED) is followed by zero or more
+        prologue insns and a NOTE_INSN_PROLOGUE_END.  */
+      emit_note_after (NOTE_INSN_PROLOGUE_END, f);
+      seq = gen_prologue ();
+      head = emit_insn_after (seq, f);
+
+      /* Include the new prologue insns in the first block.  Ignore them
+        if they form a basic block unto themselves.  */
+      if (basic_block_head && n_basic_blocks
+         && GET_CODE (basic_block_head[0]) != CODE_LABEL)
+       basic_block_head[0] = NEXT_INSN (f);
+
+      /* Retain a map of the prologue insns.  */
+      prologue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : head);
+    }
+  else
+#endif
+    prologue = 0;
+
+#ifdef HAVE_epilogue
+  if (HAVE_epilogue)
+    {
+      rtx insn = get_last_insn ();
+      rtx prev = prev_nonnote_insn (insn);
+
+      /* If we end with a BARRIER, we don't need an epilogue.  */
+      if (! (prev && GET_CODE (prev) == BARRIER))
+       {
+         rtx tail, seq;
+
+         /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG,
+            the epilogue insns (this must include the jump insn that
+            returns), USE insns ad the end of a function, and a BARRIER.  */
+
+         emit_barrier_after (insn);
+
+         /* Place the epilogue before the USE insns at the end of a
+            function.  */
+         while (prev
+                && GET_CODE (prev) == INSN
+                && GET_CODE (PATTERN (prev)) == USE)
+           {
+             insn = PREV_INSN (prev);
+             prev = prev_nonnote_insn (prev);
+           }
+
+         seq = gen_epilogue ();
+         tail = emit_jump_insn_after (seq, insn);
+         emit_note_after (NOTE_INSN_EPILOGUE_BEG, insn);
+
+         /* Include the new epilogue insns in the last block.  Ignore
+            them if they form a basic block unto themselves.  */
+         if (basic_block_end && n_basic_blocks
+             && GET_CODE (basic_block_end[n_basic_blocks - 1]) != JUMP_INSN)
+           basic_block_end[n_basic_blocks - 1] = tail;
+
+         /* Retain a map of the epilogue insns.  */
+         epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
+         return;
+       }
+    }
+#endif
+  epilogue = 0;
+}
+
+/* Reposition the prologue-end and epilogue-begin notes after instruction
+   scheduling and delayed branch scheduling.  */
+
+void
+reposition_prologue_and_epilogue_notes (f)
+     rtx f;
+{
+#if defined (HAVE_prologue) || defined (HAVE_epilogue)
+  /* Reposition the prologue and epilogue notes.  */
+  if (n_basic_blocks)
+    {
+      rtx next, prev;
+
+      if (prologue)
+       {
+         register rtx insn, end_prologue;
+
+         /* From the end of the first basic block, search backward for a
+            prologue insn.  */
+         for (insn = NEXT_INSN (PREV_INSN (basic_block_end[0]));
+              insn; insn = prev_nonnote_insn (insn))
+           if (contains (insn, prologue))
+             {
+               end_prologue = insn;
+               /* Find the prologue-end note and move it to just after the
+                  last prologue insn.  */
+               for (insn = f; insn; insn = NEXT_INSN (insn))
+                 if (GET_CODE (insn) == NOTE
+                     && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
+                   break;
+               next = NEXT_INSN (insn);
+               prev = PREV_INSN (insn);
+               if (prev)
+                 NEXT_INSN (prev) = next;
+               if (next)
+                 PREV_INSN (next) = prev;
+               add_insn_after (insn, end_prologue);
+               break;
+             }
+       }
+
+      if (epilogue)
+       {
+         register rtx insn, beg_epilogue;
+
+         /* From the start of the last basic block, search forward for an
+            epilogue insn.  */
+         for (insn = PREV_INSN (NEXT_INSN (basic_block_head[n_basic_blocks - 1]));
+              insn; insn = next_nonnote_insn (insn))
+           if (beg_epilogue = contains (insn, epilogue))
+             {
+               /* Find the epilogue-begin note and move it to just before
+                  the first epilogue insn.  */
+               for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+                 if (GET_CODE (insn) == NOTE
+                     && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
+                   break;
+               next = NEXT_INSN (insn);
+               prev = PREV_INSN (insn);
+               if (prev)
+                 NEXT_INSN (prev) = next;
+               if (next)
+                 PREV_INSN (next) = prev;
+               add_insn_after (insn, PREV_INSN (beg_epilogue));
+               break;
+             }
+       }
+    }
+#endif /* HAVE_prologue or HAVE_epilogue */
+}
index afdbb098063f80b6bc5f2b980f9fbe25242741d8..50c97c374037f7f4808204b6ec26794f4bac111a 100644 (file)
@@ -3592,6 +3592,10 @@ dbr_schedule (first, file)
   /* It is not clear why the line below is needed, but it does seem to be.  */
   unfilled_firstobj = (rtx *) obstack_alloc (&unfilled_slots_obstack, 0);
 
+  /* Reposition the prologue and epilogue notes in case we moved the
+     prologue/epilogue insns.  */
+  reposition_prologue_and_epilogue_notes (first);
+
   if (file)
     {
       register int i, j, need_comma;
index c3f03575aeed091cae3ef96918f0f10e84a62191..8a4e98339cd211348555834ab8ce2ead50aa9b02 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -169,7 +169,8 @@ char *note_insn_name[] = { "NOTE_INSN_FUNCTION_BEG", "NOTE_INSN_DELETED",
                           "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
                           "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
                           "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
-                          "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP" };
+                          "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
+                          "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG" };
 
 char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
                          "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
index 923786f9942203613ae5335826aa00cc5ea4d915..f1a1a7fa8a26d0304f2024f0adfe570b46cc7103 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -336,6 +336,10 @@ extern char *reg_note_name[];
 #define NOTE_INSN_LOOP_CONT -8
 /* Generated at the start of a duplicated exit test.  */
 #define NOTE_INSN_LOOP_VTOP -9
+/* This marks the point immediately after the last prologue insn.  */
+#define NOTE_INSN_PROLOGUE_END -10
+/* This marks the point immediately prior to the first epilogue insn.  */
+#define NOTE_INSN_EPILOGUE_BEG -11
 /* Don't forget to change note_insn_name in rtl.c.  */
 
 #define NOTE_DECL_NAME(INSN) ((INSN)->fld[3].rtstr)
index 819008a7d9355f4c94181c37a2ed55305bb09445..937d9e3a8ecf9e46a31c4e0eab1a08cbddbbbf43 100644 (file)
@@ -3949,6 +3949,11 @@ schedule_insns (dump_file)
 #endif
     }
 
+  /* Reposition the prologue and epilogue notes in case we moved the
+     prologue/epilogue insns.  */
+  if (reload_completed)
+    reposition_prologue_and_epilogue_notes (get_insns ());
+
   if (write_symbols != NO_DEBUG)
     {
       rtx line = 0;
index 5c6dae117790aa176752b8744ba1549723767385..4614d1bc678567d5abe82265b89adf248e2c6cad 100644 (file)
@@ -2368,6 +2368,13 @@ rest_of_compilation (decl)
 
   reload_completed = 1;
 
+  /* On some machines, the prologue and epilogue code, or parts thereof,
+     can be represented as RTL.  Doing so lets us schedule insns between
+     it and the rest of the code and also allows delayed branch
+     scheduling to operate in the epilogue.  */
+
+  thread_prologue_and_epilogue_insns (insns);
+
   if (optimize > 0 && flag_schedule_insns_after_reload)
     {
       if (sched2_dump)