diff options
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/config/bfin/bfin-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.c | 70 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.md | 6 |
4 files changed, 77 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a53783538ee..1bddf0f77a6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2007-05-08 Jie Zhang <jie.zhang@analog.com> + + * config/bfin/bfin-protos.h (bfin_expand_epilogue): Add a third + argument of type bool. + * config/bfin/bfin.c (add_to_reg): Add epilogue_p as a fourth + argument. Safely select temporary P register according to it. + (do_link): Change call site of add_to_reg accordingly. + (do_unlink): Add epilogue_p as a fourth argument and pass it + to add_to_reg. + (expand_interrupt_handler_epilogue): Change call of do_unlink + accordingly. + (bfin_expand_prologue): Add a third argument sibcall_p. + * config/bfin/bfin.md (epilogue): Change call of + bfin_expand_epilogue accordingly. + (sibcall_epilogue): Likewise. + (eh_return_internal): Likewise. + 2007-05-08 Uros Bizjak <ubizjak@gmail.com> PR target/31854 diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h index 99151fa9bfd..2062f77d388 100644 --- a/gcc/config/bfin/bfin-protos.h +++ b/gcc/config/bfin/bfin-protos.h @@ -89,7 +89,7 @@ extern bool bfin_legitimate_address_p (Mmode, rtx, int); extern rtx bfin_va_arg (tree, tree); extern void bfin_expand_prologue (void); -extern void bfin_expand_epilogue (int, int); +extern void bfin_expand_epilogue (int, int, bool); extern int push_multiple_operation (rtx, Mmode); extern int pop_multiple_operation (rtx, Mmode); extern void output_push_multiple (rtx, rtx *); diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 727f2ca9b81..89931df7c7d 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -569,12 +569,14 @@ frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related) RTX_FRAME_RELATED_P (insn) = 1; } -/* Generate efficient code to add a value to a P register. We can use - P1 as a scratch register. Set RTX_FRAME_RELATED_P on the generated - insns if FRAME is nonzero. */ +/* Generate efficient code to add a value to a P register. + Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero. + EPILOGUE_P is zero if this function is called for prologue, + otherwise it's nonzero. And it's less than zero if this is for + sibcall epilogue. */ static void -add_to_reg (rtx reg, HOST_WIDE_INT value, int frame) +add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p) { if (value == 0) return; @@ -584,9 +586,41 @@ add_to_reg (rtx reg, HOST_WIDE_INT value, int frame) in one instruction. */ if (value > 120 || value < -120) { - rtx tmpreg = gen_rtx_REG (SImode, REG_P1); + rtx tmpreg; + rtx tmpreg2; rtx insn; + tmpreg2 = NULL_RTX; + + /* For prologue or normal epilogue, P1 can be safely used + as the temporary register. For sibcall epilogue, we try to find + a call used P register, which will be restored in epilogue. + If we cannot find such a P register, we have to use one I register + to help us. */ + + if (epilogue_p >= 0) + tmpreg = gen_rtx_REG (SImode, REG_P1); + else + { + int i; + for (i = REG_P0; i <= REG_P5; i++) + if ((regs_ever_live[i] && ! 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)))) + break; + if (i <= REG_P5) + tmpreg = gen_rtx_REG (SImode, i); + else + { + tmpreg = gen_rtx_REG (SImode, REG_P1); + tmpreg2 = gen_rtx_REG (SImode, REG_I0); + emit_move_insn (tmpreg2, tmpreg); + } + } + if (frame) frame_related_constant_load (tmpreg, value, TRUE); else @@ -595,6 +629,9 @@ add_to_reg (rtx reg, HOST_WIDE_INT value, int frame) insn = emit_insn (gen_addsi3 (reg, reg, tmpreg)); if (frame) RTX_FRAME_RELATED_P (insn) = 1; + + if (tmpreg2 != NULL_RTX) + emit_move_insn (tmpreg, tmpreg2); } else do @@ -702,14 +739,17 @@ do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all) rtx insn = emit_insn (pat); RTX_FRAME_RELATED_P (insn) = 1; } - add_to_reg (spreg, -frame_size, 1); + add_to_reg (spreg, -frame_size, 1, 0); } } -/* Like do_link, but used for epilogues to deallocate the stack frame. */ +/* Like do_link, but used for epilogues to deallocate the stack frame. + EPILOGUE_P is zero if this function is called for prologue, + otherwise it's nonzero. And it's less than zero if this is for + sibcall epilogue. */ static void -do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all) +do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p) { frame_size += arg_area_size (); @@ -719,7 +759,7 @@ do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all) { rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg)); - add_to_reg (spreg, frame_size, 0); + add_to_reg (spreg, frame_size, 0, epilogue_p); if (must_save_fp_p ()) { rtx fpreg = gen_rtx_REG (Pmode, REG_FP); @@ -842,7 +882,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind) insns. */ MEM_VOLATILE_P (postinc) = 1; - do_unlink (spreg, get_frame_size (), all); + do_unlink (spreg, get_frame_size (), all, 1); if (lookup_attribute ("nesting", attrs)) { @@ -968,7 +1008,7 @@ bfin_expand_prologue (void) { if (lim != p2reg) emit_move_insn (p2reg, lim); - add_to_reg (p2reg, offset, 0); + add_to_reg (p2reg, offset, 0, 0); lim = p2reg; } emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim)); @@ -987,13 +1027,15 @@ bfin_expand_prologue (void) /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero if this is for a sibcall. EH_RETURN is nonzero if we're expanding an - eh_return pattern. */ + eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue, + false otherwise. */ void -bfin_expand_epilogue (int need_return, int eh_return) +bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p) { rtx spreg = gen_rtx_REG (Pmode, REG_SP); e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); + int e = sibcall_p ? -1 : 1; if (fkind != SUBROUTINE) { @@ -1001,7 +1043,7 @@ bfin_expand_epilogue (int need_return, int eh_return) return; } - do_unlink (spreg, get_frame_size (), false); + do_unlink (spreg, get_frame_size (), false, e); expand_epilogue_reg_restore (spreg, false, false); diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 7b238c64982..630694a0f9c 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -2668,12 +2668,12 @@ (define_expand "epilogue" [(const_int 1)] "" - "bfin_expand_epilogue (1, 0); DONE;") + "bfin_expand_epilogue (1, 0, 0); DONE;") (define_expand "sibcall_epilogue" [(const_int 1)] "" - "bfin_expand_epilogue (0, 0); DONE;") + "bfin_expand_epilogue (0, 0, 1); DONE;") (define_expand "eh_return" [(unspec_volatile [(match_operand:SI 0 "register_operand" "")] @@ -2693,7 +2693,7 @@ "#" "reload_completed" [(const_int 1)] - "bfin_expand_epilogue (1, 1); DONE;") + "bfin_expand_epilogue (1, 1, 0); DONE;") (define_insn "link" [(set (mem:SI (plus:SI (reg:SI REG_SP) (const_int -4))) (reg:SI REG_RETS)) |