diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2007-11-19 15:46:41 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2007-11-19 15:46:41 +0000 |
commit | 4d82f261af84b65eb92526d8f9c90fd358880c29 (patch) | |
tree | cd4b55c7c35130b7fef9f78514d4c0bb2f730205 /gcc/config/bfin | |
parent | 60f1711a6d52865b59bc5320d3d0595bf398db12 (diff) | |
download | gcc-4d82f261af84b65eb92526d8f9c90fd358880c29.zip gcc-4d82f261af84b65eb92526d8f9c90fd358880c29.tar.gz gcc-4d82f261af84b65eb92526d8f9c90fd358880c29.tar.bz2 |
bfin.c (must_save_p): New function, mostly broken out of n_dregs_to_save and n_pregs_to_save.
* config/bfin/bfin.c (must_save_p): New function, mostly broken out of
n_dregs_to_save and n_pregs_to_save.
(n_pregs_to_save, n_dregs_to_save): Use it. New argument CONSECUTIVE;
all callers changed.
(expand_prologue_reg_save, expand_epilogue_reg_restore): Enhance to be
able to save single D/P registers that aren't saved by the push/pop
multiple insns.
From-SVN: r130292
Diffstat (limited to 'gcc/config/bfin')
-rw-r--r-- | gcc/config/bfin/bfin.c | 271 |
1 files changed, 175 insertions, 96 deletions
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index c3b5988..e5f867b 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -340,22 +340,15 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg) /* Stack frame layout. */ -/* Compute the number of DREGS to save with a push_multiple operation. - This could include registers that aren't modified in the function, - since push_multiple only takes a range of registers. - If IS_INTHANDLER, then everything that is live must be saved, even - if normally call-clobbered. */ - -static int -n_dregs_to_save (bool is_inthandler) +/* For a given REGNO, determine whether it must be saved in the function + prologue. IS_INTHANDLER specifies whether we're generating a normal + prologue or an interrupt/exception one. */ +static bool +must_save_p (bool is_inthandler, unsigned regno) { - unsigned i; - - for (i = REG_R0; i <= REG_R7; i++) + if (D_REGNO_P (regno)) { - if (df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i])) - return REG_R7 - i + 1; - + bool is_eh_return_reg = false; if (current_function_calls_eh_return) { unsigned j; @@ -364,30 +357,71 @@ n_dregs_to_save (bool is_inthandler) unsigned test = EH_RETURN_DATA_REGNO (j); if (test == INVALID_REGNUM) break; - if (test == i) - return REG_R7 - i + 1; + if (test == regno) + is_eh_return_reg = true; } } + return (is_eh_return_reg + || (df_regs_ever_live_p (regno) + && !fixed_regs[regno] + && (is_inthandler || !call_used_regs[regno]))); } - return 0; + else if (P_REGNO_P (regno)) + { + return ((df_regs_ever_live_p (regno) + && !fixed_regs[regno] + && (is_inthandler || !call_used_regs[regno])) + || (!TARGET_FDPIC + && regno == PIC_OFFSET_TABLE_REGNUM + && (current_function_uses_pic_offset_table + || (TARGET_ID_SHARED_LIBRARY && !current_function_is_leaf)))); + } + else + return ((is_inthandler || !call_used_regs[regno]) + && (df_regs_ever_live_p (regno) + || (!leaf_function_p () && call_used_regs[regno]))); + +} + +/* Compute the number of DREGS to save with a push_multiple operation. + This could include registers that aren't modified in the function, + since push_multiple only takes a range of registers. + If IS_INTHANDLER, then everything that is live must be saved, even + if normally call-clobbered. + If CONSECUTIVE, return the number of registers we can save in one + instruction with a push/pop multiple instruction. */ + +static int +n_dregs_to_save (bool is_inthandler, bool consecutive) +{ + int count = 0; + unsigned i; + + for (i = REG_R7 + 1; i-- != REG_R0;) + { + if (must_save_p (is_inthandler, i)) + count++; + else if (consecutive) + return count; + } + return count; } /* Like n_dregs_to_save, but compute number of PREGS to save. */ static int -n_pregs_to_save (bool is_inthandler) +n_pregs_to_save (bool is_inthandler, bool consecutive) { + int count = 0; unsigned i; - for (i = REG_P0; i <= REG_P5; i++) - if ((df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i])) - || (!TARGET_FDPIC - && i == PIC_OFFSET_TABLE_REGNUM - && (current_function_uses_pic_offset_table - || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf)))) - return REG_P5 - i + 1; - return 0; + for (i = REG_P5 + 1; i-- != REG_P0;) + if (must_save_p (is_inthandler, i)) + count++; + else if (consecutive) + return count; + return count; } /* Determine if we are going to save the frame pointer in the prologue. */ @@ -418,61 +452,85 @@ expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler) { rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg); rtx predec = gen_rtx_MEM (SImode, predec1); - int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler); - int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler); - int dregno = REG_R7 + 1 - ndregs; - int pregno = REG_P5 + 1 - npregs; - int total = ndregs + npregs; - int i; - rtx pat, insn, val; + int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false); + int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false); + int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true); + int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true); + int dregno, pregno; + int total_consec = ndregs_consec + npregs_consec; + int i, d_to_save; if (saveall || is_inthandler) { - insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT)); + rtx insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT)); RTX_FRAME_RELATED_P (insn) = 1; } - if (total == 0 && !saveall) - return; + if (total_consec != 0) + { + rtx insn; + rtx val = GEN_INT (-total_consec * 4); + rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2)); + + XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val), + UNSPEC_PUSH_MULTIPLE); + XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg, + gen_rtx_PLUS (Pmode, + spreg, + val)); + RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1; + d_to_save = ndregs_consec; + dregno = REG_R7 + 1 - ndregs_consec; + pregno = REG_P5 + 1 - npregs_consec; + for (i = 0; i < total_consec; i++) + { + rtx memref = gen_rtx_MEM (word_mode, + gen_rtx_PLUS (Pmode, spreg, + GEN_INT (- i * 4 - 4))); + rtx subpat; + if (d_to_save > 0) + { + subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, + dregno++)); + d_to_save--; + } + else + { + subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, + pregno++)); + } + XVECEXP (pat, 0, i + 1) = subpat; + RTX_FRAME_RELATED_P (subpat) = 1; + } + insn = emit_insn (pat); + RTX_FRAME_RELATED_P (insn) = 1; + } - val = GEN_INT (-total * 4); - pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2)); - XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val), - UNSPEC_PUSH_MULTIPLE); - XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg, - gen_rtx_PLUS (Pmode, spreg, - val)); - RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1; - for (i = 0; i < total; i++) - { - rtx memref = gen_rtx_MEM (word_mode, - gen_rtx_PLUS (Pmode, spreg, - GEN_INT (- i * 4 - 4))); - rtx subpat; - if (ndregs > 0) + for (dregno = REG_R0; ndregs != ndregs_consec; dregno++) + { + if (must_save_p (is_inthandler, dregno)) { - subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, - dregno++)); + rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, dregno)); + RTX_FRAME_RELATED_P (insn) = 1; ndregs--; } - else + } + for (pregno = REG_P0; npregs != npregs_consec; pregno++) + { + if (must_save_p (is_inthandler, pregno)) { - subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, - pregno++)); - npregs++; + rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, pregno)); + RTX_FRAME_RELATED_P (insn) = 1; + npregs--; } - XVECEXP (pat, 0, i + 1) = subpat; - RTX_FRAME_RELATED_P (subpat) = 1; } - insn = emit_insn (pat); - RTX_FRAME_RELATED_P (insn) = 1; - for (i = REG_P7 + 1; i < REG_CC; i++) if (saveall || (is_inthandler && (df_regs_ever_live_p (i) || (!leaf_function_p () && call_used_regs[i])))) { + rtx insn; if (i == REG_A0 || i == REG_A1) insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1), gen_rtx_REG (PDImode, i)); @@ -493,11 +551,13 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler) rtx postinc1 = gen_rtx_POST_INC (SImode, spreg); rtx postinc = gen_rtx_MEM (SImode, postinc1); - int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler); - int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler); - int total = ndregs + npregs; + int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false); + int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false); + int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true); + int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true); + int total_consec = ndregs_consec + npregs_consec; int i, regno; - rtx pat, insn; + rtx insn; /* A slightly crude technique to stop flow from trying to delete "dead" insns. */ @@ -519,40 +579,59 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler) emit_move_insn (gen_rtx_REG (SImode, i), postinc); } - if (total == 0) - return; - - pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1)); - XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg, - gen_rtx_PLUS (Pmode, spreg, - GEN_INT (total * 4))); - - if (npregs > 0) - regno = REG_P5 + 1; - else - regno = REG_R7 + 1; - - for (i = 0; i < total; i++) + regno = REG_P5 - npregs_consec; + for (; npregs != npregs_consec; regno--) { - rtx addr = (i > 0 - ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4)) - : spreg); - rtx memref = gen_rtx_MEM (word_mode, addr); - - regno--; - XVECEXP (pat, 0, i + 1) - = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref); - - if (npregs > 0) + if (must_save_p (is_inthandler, regno)) + { + emit_move_insn (gen_rtx_REG (word_mode, regno), postinc); + npregs--; + } + } + regno = REG_R7 - ndregs_consec; + for (; ndregs != ndregs_consec; regno--) + { + if (must_save_p (is_inthandler, regno)) { - if (--npregs == 0) - regno = REG_R7 + 1; + emit_move_insn (gen_rtx_REG (word_mode, regno), postinc); + ndregs--; } } - insn = emit_insn (pat); - RTX_FRAME_RELATED_P (insn) = 1; + if (total_consec != 0) + { + rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1)); + XVECEXP (pat, 0, 0) + = gen_rtx_SET (VOIDmode, spreg, + gen_rtx_PLUS (Pmode, spreg, + GEN_INT (total_consec * 4))); + + if (npregs_consec > 0) + regno = REG_P5 + 1; + else + regno = REG_R7 + 1; + for (i = 0; i < total_consec; i++) + { + rtx addr = (i > 0 + ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4)) + : spreg); + rtx memref = gen_rtx_MEM (word_mode, addr); + + regno--; + XVECEXP (pat, 0, i + 1) + = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref); + + if (npregs_consec > 0) + { + if (--npregs_consec == 0) + regno = REG_R7 + 1; + } + } + + insn = emit_insn (pat); + RTX_FRAME_RELATED_P (insn) = 1; + } if (saveall || is_inthandler) emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc); } @@ -636,8 +715,8 @@ n_regs_saved_by_prologue (void) tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE || (is_inthandler && !current_function_is_leaf)); - int ndregs = all ? 8 : n_dregs_to_save (is_inthandler); - int npregs = all ? 6 : n_pregs_to_save (is_inthandler); + int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false); + int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false); int n = ndregs + npregs; int i; |