From bdac5f5848fbb6646b1beee01bb045a778195e73 Mon Sep 17 00:00:00 2001 From: Tom Wood Date: Mon, 29 Jun 1992 16:04:35 +0000 Subject: [PATCH] *** empty log message *** From-SVN: r1336 --- gcc/final.c | 41 +++++++++- gcc/function.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/reorg.c | 4 + gcc/rtl.c | 3 +- gcc/rtl.h | 4 + gcc/sched.c | 5 ++ gcc/toplev.c | 7 ++ 7 files changed, 267 insertions(+), 4 deletions(-) diff --git a/gcc/final.c b/gcc/final.c index 57ac44b2bf3..c58d03bbfd6 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 fd69b1823e1..17d30ab659e 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 afdbb098063..50c97c37403 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 c3f03575aee..8a4e98339cd 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 923786f9942..f1a1a7fa8a2 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 819008a7d93..937d9e3a8ec 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 5c6dae11779..4614d1bc678 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) -- 2.30.2