Commit 4d82f261 by Bernd Schmidt Committed by Bernd Schmidt

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
parent 60f1711a
2007-11-19 Bernd Schmidt <bernd.schmidt@analog.com>
* 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.
2007-11-19 Richard Guenther <rguenther@suse.de> 2007-11-19 Richard Guenther <rguenther@suse.de>
PR tree-optimization/34099 PR tree-optimization/34099
...@@ -340,22 +340,15 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg) ...@@ -340,22 +340,15 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
/* Stack frame layout. */ /* Stack frame layout. */
/* Compute the number of DREGS to save with a push_multiple operation. /* For a given REGNO, determine whether it must be saved in the function
This could include registers that aren't modified in the function, prologue. IS_INTHANDLER specifies whether we're generating a normal
since push_multiple only takes a range of registers. prologue or an interrupt/exception one. */
If IS_INTHANDLER, then everything that is live must be saved, even static bool
if normally call-clobbered. */ must_save_p (bool is_inthandler, unsigned regno)
static int
n_dregs_to_save (bool is_inthandler)
{ {
unsigned i; if (D_REGNO_P (regno))
for (i = REG_R0; i <= REG_R7; i++)
{ {
if (df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i])) bool is_eh_return_reg = false;
return REG_R7 - i + 1;
if (current_function_calls_eh_return) if (current_function_calls_eh_return)
{ {
unsigned j; unsigned j;
...@@ -364,30 +357,71 @@ n_dregs_to_save (bool is_inthandler) ...@@ -364,30 +357,71 @@ n_dregs_to_save (bool is_inthandler)
unsigned test = EH_RETURN_DATA_REGNO (j); unsigned test = EH_RETURN_DATA_REGNO (j);
if (test == INVALID_REGNUM) if (test == INVALID_REGNUM)
break; break;
if (test == i) if (test == regno)
return REG_R7 - i + 1; 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. */ /* Like n_dregs_to_save, but compute number of PREGS to save. */
static int static int
n_pregs_to_save (bool is_inthandler) n_pregs_to_save (bool is_inthandler, bool consecutive)
{ {
int count = 0;
unsigned i; unsigned i;
for (i = REG_P0; i <= REG_P5; i++) for (i = REG_P5 + 1; i-- != REG_P0;)
if ((df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i])) if (must_save_p (is_inthandler, i))
|| (!TARGET_FDPIC count++;
&& i == PIC_OFFSET_TABLE_REGNUM else if (consecutive)
&& (current_function_uses_pic_offset_table return count;
|| (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf)))) return count;
return REG_P5 - i + 1;
return 0;
} }
/* Determine if we are going to save the frame pointer in the prologue. */ /* 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) ...@@ -418,61 +452,85 @@ expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
{ {
rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg); rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
rtx predec = gen_rtx_MEM (SImode, predec1); rtx predec = gen_rtx_MEM (SImode, predec1);
int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler); int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler); int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
int dregno = REG_R7 + 1 - ndregs; int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
int pregno = REG_P5 + 1 - npregs; int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
int total = ndregs + npregs; int dregno, pregno;
int i; int total_consec = ndregs_consec + npregs_consec;
rtx pat, insn, val; int i, d_to_save;
if (saveall || is_inthandler) 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; RTX_FRAME_RELATED_P (insn) = 1;
} }
if (total == 0 && !saveall) if (total_consec != 0)
return; {
rtx insn;
rtx val = GEN_INT (-total_consec * 4);
rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
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), XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
UNSPEC_PUSH_MULTIPLE); UNSPEC_PUSH_MULTIPLE);
XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg, XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg,
gen_rtx_PLUS (Pmode, spreg, gen_rtx_PLUS (Pmode,
spreg,
val)); val));
RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1; RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
for (i = 0; i < total; i++) 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, rtx memref = gen_rtx_MEM (word_mode,
gen_rtx_PLUS (Pmode, spreg, gen_rtx_PLUS (Pmode, spreg,
GEN_INT (- i * 4 - 4))); GEN_INT (- i * 4 - 4)));
rtx subpat; rtx subpat;
if (ndregs > 0) if (d_to_save > 0)
{ {
subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
dregno++)); dregno++));
ndregs--; d_to_save--;
} }
else else
{ {
subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode, subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
pregno++)); pregno++));
npregs++;
} }
XVECEXP (pat, 0, i + 1) = subpat; XVECEXP (pat, 0, i + 1) = subpat;
RTX_FRAME_RELATED_P (subpat) = 1; RTX_FRAME_RELATED_P (subpat) = 1;
} }
insn = emit_insn (pat); insn = emit_insn (pat);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
}
for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
{
if (must_save_p (is_inthandler, dregno))
{
rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
RTX_FRAME_RELATED_P (insn) = 1;
ndregs--;
}
}
for (pregno = REG_P0; npregs != npregs_consec; pregno++)
{
if (must_save_p (is_inthandler, pregno))
{
rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
RTX_FRAME_RELATED_P (insn) = 1;
npregs--;
}
}
for (i = REG_P7 + 1; i < REG_CC; i++) for (i = REG_P7 + 1; i < REG_CC; i++)
if (saveall if (saveall
|| (is_inthandler || (is_inthandler
&& (df_regs_ever_live_p (i) && (df_regs_ever_live_p (i)
|| (!leaf_function_p () && call_used_regs[i])))) || (!leaf_function_p () && call_used_regs[i]))))
{ {
rtx insn;
if (i == REG_A0 || i == REG_A1) if (i == REG_A0 || i == REG_A1)
insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1), insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
gen_rtx_REG (PDImode, i)); gen_rtx_REG (PDImode, i));
...@@ -493,11 +551,13 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler) ...@@ -493,11 +551,13 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
rtx postinc1 = gen_rtx_POST_INC (SImode, spreg); rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
rtx postinc = gen_rtx_MEM (SImode, postinc1); rtx postinc = gen_rtx_MEM (SImode, postinc1);
int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler); int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler); int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
int total = ndregs + npregs; 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; int i, regno;
rtx pat, insn; rtx insn;
/* A slightly crude technique to stop flow from trying to delete "dead" /* A slightly crude technique to stop flow from trying to delete "dead"
insns. */ insns. */
...@@ -519,20 +579,39 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler) ...@@ -519,20 +579,39 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
emit_move_insn (gen_rtx_REG (SImode, i), postinc); emit_move_insn (gen_rtx_REG (SImode, i), postinc);
} }
if (total == 0) regno = REG_P5 - npregs_consec;
return; for (; npregs != npregs_consec; regno--)
{
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))
{
emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
ndregs--;
}
}
pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1)); if (total_consec != 0)
XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg, {
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_rtx_PLUS (Pmode, spreg,
GEN_INT (total * 4))); GEN_INT (total_consec * 4)));
if (npregs > 0) if (npregs_consec > 0)
regno = REG_P5 + 1; regno = REG_P5 + 1;
else else
regno = REG_R7 + 1; regno = REG_R7 + 1;
for (i = 0; i < total; i++) for (i = 0; i < total_consec; i++)
{ {
rtx addr = (i > 0 rtx addr = (i > 0
? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4)) ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
...@@ -543,16 +622,16 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler) ...@@ -543,16 +622,16 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
XVECEXP (pat, 0, i + 1) XVECEXP (pat, 0, i + 1)
= gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref); = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
if (npregs > 0) if (npregs_consec > 0)
{ {
if (--npregs == 0) if (--npregs_consec == 0)
regno = REG_R7 + 1; regno = REG_R7 + 1;
} }
} }
insn = emit_insn (pat); insn = emit_insn (pat);
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
}
if (saveall || is_inthandler) if (saveall || is_inthandler)
emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc); emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
} }
...@@ -636,8 +715,8 @@ n_regs_saved_by_prologue (void) ...@@ -636,8 +715,8 @@ n_regs_saved_by_prologue (void)
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
|| (is_inthandler && !current_function_is_leaf)); || (is_inthandler && !current_function_is_leaf));
int ndregs = all ? 8 : n_dregs_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); int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
int n = ndregs + npregs; int n = ndregs + npregs;
int i; int i;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment