summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/bfin/bfin-protos.h2
-rw-r--r--gcc/config/bfin/bfin.c70
-rw-r--r--gcc/config/bfin/bfin.md6
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))