aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Wood <wood@gnu.org>1992-06-29 16:04:35 +0000
committerTom Wood <wood@gnu.org>1992-06-29 16:04:35 +0000
commitbdac5f5848fbb6646b1beee01bb045a778195e73 (patch)
tree4d0ad94f4fb5359e4c5330300091d0cd90282f55
parent8194c19cbe07371c2505a4719986209b7d403650 (diff)
downloadgcc-bdac5f5848fbb6646b1beee01bb045a778195e73.zip
gcc-bdac5f5848fbb6646b1beee01bb045a778195e73.tar.gz
gcc-bdac5f5848fbb6646b1beee01bb045a778195e73.tar.bz2
*** empty log message ***
From-SVN: r1336
-rw-r--r--gcc/final.c41
-rw-r--r--gcc/function.c207
-rw-r--r--gcc/reorg.c4
-rw-r--r--gcc/rtl.c3
-rw-r--r--gcc/rtl.h4
-rw-r--r--gcc/sched.c5
-rw-r--r--gcc/toplev.c7
7 files changed, 267 insertions, 4 deletions
diff --git a/gcc/final.c b/gcc/final.c
index 57ac44b..c58d03b 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -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;
diff --git a/gcc/function.c b/gcc/function.c
index fd69b18..17d30ab 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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);
}
+
+/* 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 */
+}
diff --git a/gcc/reorg.c b/gcc/reorg.c
index afdbb09..50c97c3 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -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;
diff --git a/gcc/rtl.c b/gcc/rtl.c
index c3f0357..8a4e983 100644
--- 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",
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 923786f..f1a1a7f 100644
--- 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)
diff --git a/gcc/sched.c b/gcc/sched.c
index 819008a..937d9e3 100644
--- a/gcc/sched.c
+++ b/gcc/sched.c
@@ -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;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 5c6dae1..4614d1b 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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)