Commit f285d67b by Richard Kenner Committed by Richard Kenner

function.c (struct epi_info): New field const_equiv.

	PR/6552
	* function.c (struct epi_info): New field const_equiv.
	(update_epilogue_consts): New function.
	(keep_stack_depressed): Clear new field and verify scratch register
	doesn't have it set.
	Call new function via note_stores.
	(handle_epilogue_set): Allow setting SP equiv reg in different mode.
	Allow PLUS where second operand is register known set to constant.
	(emit_equiv_load): Write load using proper mode if source different.
	* config/mips/mips.md (return_internal): Put (return) first.

From-SVN: r73609
parent a477ab83
2003-11-14 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
PR/6552
* function.c (struct epi_info): New field const_equiv.
(update_epilogue_consts): New function.
(keep_stack_depressed): Clear new field and verify scratch register
doesn't have it set.
Call new function via note_stores.
(handle_epilogue_set): Allow setting SP equiv reg in different mode.
Allow PLUS where second operand is register known set to constant.
(emit_equiv_load): Write load using proper mode if source different.
* config/mips/mips.md (return_internal): Put (return) first.
2003-11-14 Kazu Hirata <kazu@cs.umass.edu>
* config/h8300/lib1funcs.asm (___udivsi3): Add a comment.
......
......@@ -8249,8 +8249,8 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
;; Normal return.
(define_insn "return_internal"
[(use (match_operand 0 "pmode_register_operand" ""))
(return)]
[(return)
(use (match_operand 0 "pmode_register_operand" ""))]
""
"%*j\t%0%/"
[(set_attr "type" "jump")
......
......@@ -7296,9 +7296,12 @@ struct epi_info
rtx equiv_reg_src; /* If nonzero, the value that SP_EQUIV_REG
should be set to once we no longer need
its value. */
rtx const_equiv[FIRST_PSEUDO_REGISTER]; /* Any known constant equivalences
for registers. */
};
static void handle_epilogue_set (rtx, struct epi_info *);
static void update_epilogue_consts PARAMS ((rtx, rtx, void *));
static void emit_equiv_load (struct epi_info *);
/* Modify INSN, a list of one or more insns that is part of the epilogue, to
......@@ -7311,8 +7314,7 @@ keep_stack_depressed (rtx insns)
struct epi_info info;
rtx insn, next;
/* If the epilogue is just a single instruction, it ust be OK as is. */
/* If the epilogue is just a single instruction, it must be OK as is. */
if (NEXT_INSN (insns) == NULL_RTX)
return insns;
......@@ -7324,6 +7326,9 @@ keep_stack_depressed (rtx insns)
info.sp_offset = 0;
info.equiv_reg_src = 0;
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
info.const_equiv[j] = 0;
insn = insns;
next = NULL_RTX;
while (insn != NULL_RTX)
......@@ -7415,7 +7420,8 @@ keep_stack_depressed (rtx insns)
&& !refers_to_regno_p (regno,
regno + HARD_REGNO_NREGS (regno,
Pmode),
info.equiv_reg_src, NULL))
info.equiv_reg_src, NULL)
&& info.const_equiv[regno] == 0)
break;
if (regno == FIRST_PSEUDO_REGISTER)
......@@ -7471,6 +7477,8 @@ keep_stack_depressed (rtx insns)
info.sp_equiv_reg = info.new_sp_equiv_reg;
info.sp_offset = info.new_sp_offset;
/* Now update any constants this insn sets. */
note_stores (PATTERN (insn), update_epilogue_consts, &info);
insn = next;
}
......@@ -7494,11 +7502,18 @@ handle_epilogue_set (rtx set, struct epi_info *p)
if (SET_DEST (set) != stack_pointer_rtx)
abort ();
if (GET_CODE (SET_SRC (set)) == PLUS
&& GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
if (GET_CODE (SET_SRC (set)) == PLUS)
{
p->new_sp_equiv_reg = XEXP (SET_SRC (set), 0);
if (GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
p->new_sp_offset = INTVAL (XEXP (SET_SRC (set), 1));
else if (GET_CODE (XEXP (SET_SRC (set), 1)) == REG
&& REGNO (XEXP (SET_SRC (set), 1)) < FIRST_PSEUDO_REGISTER
&& p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))] != 0)
p->new_sp_offset
= INTVAL (p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))]);
else
abort ();
}
else
p->new_sp_equiv_reg = SET_SRC (set), p->new_sp_offset = 0;
......@@ -7521,11 +7536,16 @@ handle_epilogue_set (rtx set, struct epi_info *p)
there seems little point in handling that case. Note that we have
to allow for the case where we are setting the register set in
the previous part of a PARALLEL inside a single insn. But use the
old offset for any updates within this insn. */
old offset for any updates within this insn. We must allow for the case
where the register is being set in a different (usually wider) mode than
Pmode). */
else if (p->new_sp_equiv_reg != 0 && reg_set_p (p->new_sp_equiv_reg, set))
{
if (!rtx_equal_p (p->new_sp_equiv_reg, SET_DEST (set))
|| p->equiv_reg_src != 0)
if (p->equiv_reg_src != 0
|| GET_CODE (p->new_sp_equiv_reg) != REG
|| GET_CODE (SET_DEST (set)) != REG
|| GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) > BITS_PER_WORD
|| REGNO (p->new_sp_equiv_reg) != REGNO (SET_DEST (set)))
abort ();
else
p->equiv_reg_src
......@@ -7548,15 +7568,38 @@ handle_epilogue_set (rtx set, struct epi_info *p)
}
}
/* Update the tracking information for registers set to constants. */
static void
update_epilogue_consts (rtx dest, rtx x, void *data)
{
struct epi_info *p = (struct epi_info *) data;
if (GET_CODE (dest) != REG || REGNO (dest) >= FIRST_PSEUDO_REGISTER)
return;
else if (GET_CODE (x) == CLOBBER || ! rtx_equal_p (dest, SET_DEST (x))
|| GET_CODE (SET_SRC (x)) != CONST_INT)
p->const_equiv[REGNO (dest)] = 0;
else
p->const_equiv[REGNO (dest)] = SET_SRC (x);
}
/* Emit an insn to do the load shown in p->equiv_reg_src, if needed. */
static void
emit_equiv_load (struct epi_info *p)
{
if (p->equiv_reg_src != 0)
emit_move_insn (p->sp_equiv_reg, p->equiv_reg_src);
{
rtx dest = p->sp_equiv_reg;
if (GET_MODE (p->equiv_reg_src) != GET_MODE (dest))
dest = gen_rtx_REG (GET_MODE (p->equiv_reg_src),
REGNO (p->sp_equiv_reg));
emit_move_insn (dest, p->equiv_reg_src);
p->equiv_reg_src = 0;
}
}
#endif
......
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