From 1f2d8f510f4e516803427373e1625991756d4d91 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 11 Jul 1997 09:48:51 -0600 Subject: [PATCH] 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 --- gcc/config/mips/mips.c | 282 ++-------------------------------------- gcc/config/mips/mips.h | 16 --- gcc/config/mips/mips.md | 68 +++++----- 3 files changed, 44 insertions(+), 322 deletions(-) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 584de95a084..7ebb5083648 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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; diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 6aa3402c22c..74068d4497b 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -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) \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 36f97910ffd..770a91c97a3 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -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.