mips.c (epilogue_reg_mentioned_p): Delete unused function.

* mips.c (epilogue_reg_mentioned_p): Delete unused function.
        (mips_epilogue_delay_slots): Likewise.
        (function_epilogue): Greatly simplify.
        (mips_expand_epilogue): If we have a null prologue/epilogue,
        then use a normal return insn.  Emit blockage insns before
        stack pointer adjustments.
        (mips_can_use_return_insn): Renamed from simple_epilogue_p.  All
        callers changed.  Do not use return insns if $31 is live in the
        function or if generating profiling information.
        * mips.h (DELAY_SLOTS_FOR_EPILOGUE): Delete.
        (ELIGIBLE_FOR_EPILOGUE_DELAY): Likewise.
        * mips.md (return): Remove expander and change the pattern to
        look like a standard "return" insn.
        (return_internal): Show use of $31 explictly.
        (epilogue expander): Enable.

From-SVN: r14412
This commit is contained in:
Jeff Law 1997-07-11 09:48:51 -06:00
parent 7a49a4fd7b
commit 1f2d8f510f
3 changed files with 44 additions and 322 deletions

View File

@ -4729,71 +4729,6 @@ mips_output_float (stream, value)
#endif
}
/* Return TRUE if any register used in the epilogue is used. This to insure
any insn put into the epilogue delay slots is safe. */
int
epilogue_reg_mentioned_p (insn)
rtx insn;
{
register char *fmt;
register int i;
register enum rtx_code code;
register int regno;
if (insn == (rtx)0)
return 0;
if (GET_CODE (insn) == LABEL_REF)
return 0;
code = GET_CODE (insn);
switch (code)
{
case REG:
regno = REGNO (insn);
if (regno == STACK_POINTER_REGNUM)
return 1;
if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
return 1;
if (!call_used_regs[regno])
return 1;
if (regno != MIPS_TEMP1_REGNUM && regno != MIPS_TEMP2_REGNUM)
return 0;
if (!current_frame_info.initialized)
compute_frame_size (get_frame_size ());
return (current_frame_info.total_size >= 32768);
case SCRATCH:
case CC0:
case PC:
case CONST_INT:
case CONST_DOUBLE:
return 0;
}
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'E')
{
register int j;
for (j = XVECLEN (insn, i) - 1; j >= 0; j--)
if (epilogue_reg_mentioned_p (XVECEXP (insn, i, j)))
return 1;
}
else if (fmt[i] == 'e' && epilogue_reg_mentioned_p (XEXP (insn, i)))
return 1;
}
return 0;
}
/* Return the bytes needed to compute the frame pointer from the current
stack pointer.
@ -5525,170 +5460,6 @@ function_epilogue (file, size)
int size;
{
char *fnname;
long tsize;
char *sp_str = reg_names[STACK_POINTER_REGNUM];
char *t1_str = reg_names[MIPS_TEMP1_REGNUM];
rtx epilogue_delay = current_function_epilogue_delay_list;
int noreorder = (epilogue_delay != 0);
int noepilogue = FALSE;
int load_nop = FALSE;
int load_only_r31;
rtx tmp_rtx = (rtx)0;
rtx restore_rtx;
int i;
/* The epilogue does not depend on any registers, but the stack
registers, so we assume that if we have 1 pending nop, it can be
ignored, and 2 it must be filled (2 nops occur for integer
multiply and divide). */
if (dslots_number_nops > 0)
{
if (dslots_number_nops == 1)
{
dslots_number_nops = 0;
dslots_load_filled++;
}
else
{
while (--dslots_number_nops > 0)
fputs ("\t#nop\n", asm_out_file);
}
}
if (set_noat != 0)
{
set_noat = 0;
fputs ("\t.set\tat\n", file);
error ("internal gcc error: .set noat left on in epilogue");
}
if (set_nomacro != 0)
{
set_nomacro = 0;
fputs ("\t.set\tmacro\n", file);
error ("internal gcc error: .set nomacro left on in epilogue");
}
if (set_noreorder != 0)
{
set_noreorder = 0;
fputs ("\t.set\treorder\n", file);
error ("internal gcc error: .set noreorder left on in epilogue");
}
if (set_volatile != 0)
{
set_volatile = 0;
fprintf (file, "\t%s.set\tnovolatile\n", (TARGET_MIPS_AS) ? "" : "#");
error ("internal gcc error: .set volatile left on in epilogue");
}
size = MIPS_STACK_ALIGN (size);
tsize = (!current_frame_info.initialized)
? compute_frame_size (size)
: current_frame_info.total_size;
if (tsize == 0 && epilogue_delay == 0)
{
rtx insn = get_last_insn ();
/* If the last insn was a BARRIER, we don't have to write any code
because a jump (aka return) was put there. */
if (GET_CODE (insn) == NOTE)
insn = prev_nonnote_insn (insn);
if (insn && GET_CODE (insn) == BARRIER)
noepilogue = TRUE;
noreorder = FALSE;
}
if (!noepilogue)
{
/* In the reload sequence, we don't need to fill the load delay
slots for most of the loads, also see if we can fill the final
delay slot if not otherwise filled by the reload sequence. */
if (noreorder)
fprintf (file, "\t.set\tnoreorder\n");
if (tsize > 32767)
{
fprintf (file, "\tli\t%s,0x%.08lx\t# %ld\n", t1_str, (long)tsize, (long)tsize);
tmp_rtx = gen_rtx (REG, Pmode, MIPS_TEMP1_REGNUM);
}
if (frame_pointer_needed)
fprintf (file, "\tmove\t%s,%s\t\t\t# sp not trusted here\n",
sp_str, reg_names[FRAME_POINTER_REGNUM]);
save_restore_insns (FALSE, tmp_rtx, tsize, file);
load_only_r31 = (((current_frame_info.mask
& ~ (TARGET_ABICALLS && mips_abi == ABI_32
? PIC_OFFSET_TABLE_MASK : 0))
== RA_MASK)
&& current_frame_info.fmask == 0);
if (noreorder)
{
/* If the only register saved is the return address, we need a
nop, unless we have an instruction to put into it. Otherwise
we don't since reloading multiple registers doesn't reference
the register being loaded. */
if (load_only_r31)
{
if (epilogue_delay)
final_scan_insn (XEXP (epilogue_delay, 0),
file,
1, /* optimize */
-2, /* prescan */
1); /* nopeepholes */
else
{
fprintf (file, "\tnop\n");
load_nop = TRUE;
}
}
fprintf (file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 31]);
if (tsize > 32767)
fprintf (file, "\t%s\t%s,%s,%s\n",
TARGET_LONG64 ? "daddu" : "addu",
sp_str, sp_str, t1_str);
else if (tsize > 0)
fprintf (file, "\t%s\t%s,%s,%d\n",
TARGET_LONG64 ? "daddu" : "addu",
sp_str, sp_str, tsize);
else if (!load_only_r31 && epilogue_delay != 0)
final_scan_insn (XEXP (epilogue_delay, 0),
file,
1, /* optimize */
-2, /* prescan */
1); /* nopeepholes */
fprintf (file, "\t.set\treorder\n");
}
else
{
if (tsize > 32767)
fprintf (file, "\t%s\t%s,%s,%s\n",
TARGET_LONG64 ? "daddu" : "addu",
sp_str, sp_str, t1_str);
else if (tsize > 0)
fprintf (file, "\t%s\t%s,%s,%d\n",
TARGET_LONG64 ? "daddu" : "addu",
sp_str, sp_str, tsize);
fprintf (file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 31]);
}
}
#ifndef FUNCTION_NAME_ALREADY_DECLARED
/* Get the function name the same way that toplev.c does before calling
@ -5713,23 +5484,6 @@ function_epilogue (file, size)
dslots_load_total += num_regs;
if (!noepilogue)
dslots_jump_total++;
if (noreorder)
{
dslots_load_filled += num_regs;
/* If the only register saved is the return register, we
can't fill this register's delay slot. */
if (load_only_r31 && epilogue_delay == 0)
dslots_load_filled--;
if (tsize > 0 || (!load_only_r31 && epilogue_delay != 0))
dslots_jump_filled++;
}
fprintf (stderr,
"%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3ld reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d",
name,
@ -5791,6 +5545,12 @@ mips_expand_epilogue ()
rtx tsize_rtx = GEN_INT (tsize);
rtx tmp_rtx = (rtx)0;
if (mips_can_use_return_insn ())
{
emit_insn (gen_return ());
return;
}
if (tsize > 32767)
{
tmp_rtx = gen_rtx (REG, Pmode, MIPS_TEMP1_REGNUM);
@ -5802,6 +5562,7 @@ mips_expand_epilogue ()
{
if (frame_pointer_needed)
{
emit_insn (gen_blockage ());
if (TARGET_LONG64)
emit_insn (gen_movdi (stack_pointer_rtx, frame_pointer_rtx));
else
@ -5810,6 +5571,7 @@ mips_expand_epilogue ()
save_restore_insns (FALSE, tmp_rtx, tsize, (FILE *)0);
emit_insn (gen_blockage ());
if (TARGET_LONG64)
emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
tsize_rtx));
@ -5818,28 +5580,7 @@ mips_expand_epilogue ()
tsize_rtx));
}
emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, GP_REG_FIRST+31)));
}
/* Define the number of delay slots needed for the function epilogue.
On the mips, we need a slot if either no stack has been allocated,
or the only register saved is the return register. */
int
mips_epilogue_delay_slots ()
{
if (!current_frame_info.initialized)
(void) compute_frame_size (get_frame_size ());
if (current_frame_info.total_size == 0)
return 1;
if (current_frame_info.mask == RA_MASK && current_frame_info.fmask == 0)
return 1;
return 0;
emit_jump_insn (gen_return_internal ());
}
@ -5848,11 +5589,14 @@ mips_epilogue_delay_slots ()
was created. */
int
simple_epilogue_p ()
mips_can_use_return_insn ()
{
if (!reload_completed)
return 0;
if (regs_ever_live[31] || profile_flag)
return 0;
if (current_frame_info.initialized)
return current_frame_info.total_size == 0;

View File

@ -2241,22 +2241,6 @@ typedef struct mips_args {
#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue(FILE, SIZE)
/* Define the number of delay slots needed for the function epilogue.
On the mips, we need a slot if either no stack has been allocated,
or the only register saved is the return register. */
#define DELAY_SLOTS_FOR_EPILOGUE mips_epilogue_delay_slots ()
/* Define whether INSN can be placed in delay slot N for the epilogue.
No references to the stack must be made, since on the MIPS, the
delay slot is done after the stack has been cleaned up. */
#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN,N) \
(get_attr_dslot (INSN) == DSLOT_NO \
&& get_attr_length (INSN) == 1 \
&& ! epilogue_reg_mentioned_p (PATTERN (INSN)))
/* Tell prologue and epilogue if register REGNO should be saved / restored. */
#define MUST_SAVE_REGISTER(regno) \

View File

@ -6315,29 +6315,6 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "1")])
;; Function return, only allow after optimization, so that we can
;; eliminate jumps to jumps if no stack space is used.
;; (define_expand "return"
;; [(set (pc) (reg:SI 31))]
;; "simple_epilogue_p ()"
;; "")
(define_expand "return"
[(parallel [(return)
(use (reg:SI 31))])]
"simple_epilogue_p ()"
"")
(define_insn "return_internal"
[(parallel [(return)
(use (match_operand:SI 0 "register_operand" "d"))])]
""
"%*j\\t%0"
[(set_attr "type" "jump")
(set_attr "mode" "none")
(set_attr "length" "1")])
;; Implement a switch statement when generating embedded PIC code.
;; Switches are implemented by `tablejump' when not using -membedded-pic.
@ -6448,21 +6425,38 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "0")])
;; At present, don't expand the epilogue, reorg.c will clobber the
;; return register in compiling gen_lowpart (emit-rtl.c).
;;
;; (define_expand "epilogue"
;; [(const_int 2)]
;; ""
;; "
;; {
;; if (mips_isa >= 0) /* avoid unused code warnings */
;; {
;; mips_expand_epilogue ();
;; DONE;
;; }
;; }")
(define_expand "epilogue"
[(const_int 2)]
""
"
{
if (mips_isa >= 0) /* avoid unused code warnings */
{
mips_expand_epilogue ();
DONE;
}
}")
;; Trivial return. Make it look like a normal return insn as that
;; allows jump optimizations to work better .
(define_insn "return"
[(return)]
"mips_can_use_return_insn ()"
"%*j\\t$31"
[(set_attr "type" "jump")
(set_attr "mode" "none")
(set_attr "length" "1")])
;; Normal return.
(define_insn "return_internal"
[(use (reg:SI 31))
(return)]
""
"%*j\\t$31"
[(set_attr "type" "jump")
(set_attr "mode" "none")
(set_attr "length" "1")])
;; When generating embedded PIC code we need to get the address of the
;; current function. This specialized instruction does just that.