parent
8194c19cbe
commit
bdac5f5848
41
gcc/final.c
41
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;
|
||||
|
||||
|
|
207
gcc/function.c
207
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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue