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> 2003-11-14 Kazu Hirata <kazu@cs.umass.edu>
* config/h8300/lib1funcs.asm (___udivsi3): Add a comment. * 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%/" ...@@ -8249,8 +8249,8 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
;; Normal return. ;; Normal return.
(define_insn "return_internal" (define_insn "return_internal"
[(use (match_operand 0 "pmode_register_operand" "")) [(return)
(return)] (use (match_operand 0 "pmode_register_operand" ""))]
"" ""
"%*j\t%0%/" "%*j\t%0%/"
[(set_attr "type" "jump") [(set_attr "type" "jump")
......
...@@ -7296,9 +7296,12 @@ struct epi_info ...@@ -7296,9 +7296,12 @@ struct epi_info
rtx equiv_reg_src; /* If nonzero, the value that SP_EQUIV_REG rtx equiv_reg_src; /* If nonzero, the value that SP_EQUIV_REG
should be set to once we no longer need should be set to once we no longer need
its value. */ 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 handle_epilogue_set (rtx, struct epi_info *);
static void update_epilogue_consts PARAMS ((rtx, rtx, void *));
static void emit_equiv_load (struct epi_info *); static void emit_equiv_load (struct epi_info *);
/* Modify INSN, a list of one or more insns that is part of the epilogue, to /* 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) ...@@ -7311,8 +7314,7 @@ keep_stack_depressed (rtx insns)
struct epi_info info; struct epi_info info;
rtx insn, next; 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) if (NEXT_INSN (insns) == NULL_RTX)
return insns; return insns;
...@@ -7324,6 +7326,9 @@ keep_stack_depressed (rtx insns) ...@@ -7324,6 +7326,9 @@ keep_stack_depressed (rtx insns)
info.sp_offset = 0; info.sp_offset = 0;
info.equiv_reg_src = 0; info.equiv_reg_src = 0;
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
info.const_equiv[j] = 0;
insn = insns; insn = insns;
next = NULL_RTX; next = NULL_RTX;
while (insn != NULL_RTX) while (insn != NULL_RTX)
...@@ -7415,7 +7420,8 @@ keep_stack_depressed (rtx insns) ...@@ -7415,7 +7420,8 @@ keep_stack_depressed (rtx insns)
&& !refers_to_regno_p (regno, && !refers_to_regno_p (regno,
regno + HARD_REGNO_NREGS (regno, regno + HARD_REGNO_NREGS (regno,
Pmode), Pmode),
info.equiv_reg_src, NULL)) info.equiv_reg_src, NULL)
&& info.const_equiv[regno] == 0)
break; break;
if (regno == FIRST_PSEUDO_REGISTER) if (regno == FIRST_PSEUDO_REGISTER)
...@@ -7471,6 +7477,8 @@ keep_stack_depressed (rtx insns) ...@@ -7471,6 +7477,8 @@ keep_stack_depressed (rtx insns)
info.sp_equiv_reg = info.new_sp_equiv_reg; info.sp_equiv_reg = info.new_sp_equiv_reg;
info.sp_offset = info.new_sp_offset; info.sp_offset = info.new_sp_offset;
/* Now update any constants this insn sets. */
note_stores (PATTERN (insn), update_epilogue_consts, &info);
insn = next; insn = next;
} }
...@@ -7494,11 +7502,18 @@ handle_epilogue_set (rtx set, struct epi_info *p) ...@@ -7494,11 +7502,18 @@ handle_epilogue_set (rtx set, struct epi_info *p)
if (SET_DEST (set) != stack_pointer_rtx) if (SET_DEST (set) != stack_pointer_rtx)
abort (); abort ();
if (GET_CODE (SET_SRC (set)) == PLUS if (GET_CODE (SET_SRC (set)) == PLUS)
&& GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
{ {
p->new_sp_equiv_reg = XEXP (SET_SRC (set), 0); 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)); 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 else
p->new_sp_equiv_reg = SET_SRC (set), p->new_sp_offset = 0; 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) ...@@ -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 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 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 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)) 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)) if (p->equiv_reg_src != 0
|| 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 (); abort ();
else else
p->equiv_reg_src p->equiv_reg_src
...@@ -7548,15 +7568,38 @@ handle_epilogue_set (rtx set, struct epi_info *p) ...@@ -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. */ /* Emit an insn to do the load shown in p->equiv_reg_src, if needed. */
static void static void
emit_equiv_load (struct epi_info *p) emit_equiv_load (struct epi_info *p)
{ {
if (p->equiv_reg_src != 0) 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; p->equiv_reg_src = 0;
}
} }
#endif #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