Commit bd695e1e by Richard Henderson

function.c (diddle_return_value): New.

        * function.c (diddle_return_value): New.
        (expand_function_end): Use it.
        * stmt.c (expand_null_return): Likewise.
        (expand_value_return): Likewise.

        * reg-stack.c (subst_stack_regs_pat): Handle clobbers at top-level.

        * reload1.c (reload): Don't remove return value clobbers.

From-SVN: r30401
parent 49886fe1
Fri Nov 5 19:38:14 1999 Richard Henderson <rth@cygnus.com>
* function.c (diddle_return_value): New.
(expand_function_end): Use it.
* stmt.c (expand_null_return): Likewise.
(expand_value_return): Likewise.
* reg-stack.c (subst_stack_regs_pat): Handle clobbers at top-level.
* reload1.c (reload): Don't remove return value clobbers.
Thu Nov 4 13:33:46 1999 Richard Henderson <rth@cygnus.com> Thu Nov 4 13:33:46 1999 Richard Henderson <rth@cygnus.com>
* rtl.c (read_rtx): Use fatal_with_file_and_line not fatal. * rtl.c (read_rtx): Use fatal_with_file_and_line not fatal.
......
...@@ -6150,6 +6150,36 @@ expand_dummy_function_end () ...@@ -6150,6 +6150,36 @@ expand_dummy_function_end ()
current_function = 0; current_function = 0;
} }
/* Emit CODE for each register of the return value. Useful values for
code are USE and CLOBBER. */
void
diddle_return_value (code)
enum rtx_code code;
{
rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
if (return_reg)
{
if (GET_CODE (return_reg) == REG
&& REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
emit_insn (gen_rtx_fmt_e (code, VOIDmode, return_reg));
else if (GET_CODE (return_reg) == PARALLEL)
{
int i;
for (i = 0; i < XVECLEN (return_reg, 0); i++)
{
rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
if (GET_CODE (x) == REG
&& REGNO (x) < FIRST_PSEUDO_REGISTER)
emit_insn (gen_rtx_fmt_e (code, VOIDmode, x));
}
}
}
}
/* Generate RTL for the end of the current function. /* Generate RTL for the end of the current function.
FILENAME and LINE are the current position in the source file. FILENAME and LINE are the current position in the source file.
...@@ -6332,7 +6362,16 @@ expand_function_end (filename, line, end_bindings) ...@@ -6332,7 +6362,16 @@ expand_function_end (filename, line, end_bindings)
structure returning. */ structure returning. */
if (return_label) if (return_label)
{
/* Before the return label, clobber the return registers so that
they are not propogated live to the rest of the function. This
can only happen with functions that drop through; if there had
been a return statement, there would have either been a return
rtx, or a jump to the return label. */
diddle_return_value (CLOBBER);
emit_label (return_label); emit_label (return_label);
}
/* C++ uses this. */ /* C++ uses this. */
if (end_bindings) if (end_bindings)
......
...@@ -578,6 +578,10 @@ extern void free_expr_status PROTO((struct function *)); ...@@ -578,6 +578,10 @@ extern void free_expr_status PROTO((struct function *));
extern rtx get_first_block_beg PROTO((void)); extern rtx get_first_block_beg PROTO((void));
#ifdef RTX_CODE
extern void diddle_return_value PROTO((enum rtx_code));
#endif
extern void init_virtual_regs PROTO((struct emit_status *)); extern void init_virtual_regs PROTO((struct emit_status *));
/* Called once, at initialization, to initialize function.c. */ /* Called once, at initialization, to initialize function.c. */
......
...@@ -1394,16 +1394,20 @@ subst_stack_regs_pat (insn, regstack, pat) ...@@ -1394,16 +1394,20 @@ subst_stack_regs_pat (insn, regstack, pat)
{ {
rtx note; rtx note;
/* The fix_truncdi_1 pattern wants to be able to allocate it's
own scratch register. It does this by clobbering an fp reg
so that it is assured of an empty reg-stack register.
If the register is live, kill it now. Remove the DEAD/UNUSED
note so we don't try to kill it later too. */
dest = get_true_reg (&XEXP (pat, 0)); dest = get_true_reg (&XEXP (pat, 0));
if (STACK_REG_P (*dest)) if (STACK_REG_P (*dest))
{ {
note = find_reg_note (insn, REG_DEAD, *dest); note = find_reg_note (insn, REG_DEAD, *dest);
if (pat != PATTERN (insn))
{
/* The fix_truncdi_1 pattern wants to be able to allocate
it's own scratch register. It does this by clobbering
an fp reg so that it is assured of an empty reg-stack
register. If the register is live, kill it now.
Remove the DEAD/UNUSED note so we don't try to kill it
later too. */
if (note) if (note)
emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE); emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
else else
...@@ -1412,10 +1416,27 @@ subst_stack_regs_pat (insn, regstack, pat) ...@@ -1412,10 +1416,27 @@ subst_stack_regs_pat (insn, regstack, pat)
if (!note) if (!note)
abort (); abort ();
} }
remove_note (insn, note); remove_note (insn, note);
replace_reg (dest, LAST_STACK_REG); replace_reg (dest, LAST_STACK_REG);
} }
else
{
/* A top-level clobber with no REG_DEAD, and no hard-regnum
indicates an uninitialized value. Because reload removed
all other clobbers, this must be due to a function
returning without a value. Load up a NaN. */
if (! note
&& get_hard_regnum (regstack, *dest) == -1)
{
pat = gen_rtx_SET (VOIDmode,
FP_MODE_REG (REGNO (*dest), SFmode),
nan);
PATTERN (insn) = pat;
move_for_stack_reg (insn, regstack, pat);
}
}
}
break; break;
} }
......
...@@ -1106,13 +1106,12 @@ reload (first, global, dumpfile) ...@@ -1106,13 +1106,12 @@ reload (first, global, dumpfile)
which are only valid during and after reload. */ which are only valid during and after reload. */
reload_completed = 1; reload_completed = 1;
/* Make a pass over all the insns and delete all USEs which we /* Make a pass over all the insns and delete all USEs which we inserted
inserted only to tag a REG_EQUAL note on them. Remove all only to tag a REG_EQUAL note on them. Remove all REG_DEAD and REG_UNUSED
REG_DEAD and REG_UNUSED notes. Delete all CLOBBER insns and notes. Delete all CLOBBER insns that don't refer to the return value
simplify (subreg (reg)) operands. Also remove all REG_RETVAL and and simplify (subreg (reg)) operands. Also remove all REG_RETVAL and
REG_LIBCALL notes since they are no longer useful or accurate. REG_LIBCALL notes since they are no longer useful or accurate. Strip
Strip and regenerate REG_INC notes that may have been moved and regenerate REG_INC notes that may have been moved around. */
around. */
for (insn = first; insn; insn = NEXT_INSN (insn)) for (insn = first; insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
...@@ -1121,7 +1120,9 @@ reload (first, global, dumpfile) ...@@ -1121,7 +1120,9 @@ reload (first, global, dumpfile)
if ((GET_CODE (PATTERN (insn)) == USE if ((GET_CODE (PATTERN (insn)) == USE
&& find_reg_note (insn, REG_EQUAL, NULL_RTX)) && find_reg_note (insn, REG_EQUAL, NULL_RTX))
|| GET_CODE (PATTERN (insn)) == CLOBBER) || (GET_CODE (PATTERN (insn)) == CLOBBER
&& (GET_CODE (XEXP (PATTERN (insn), 0)) != REG
|| ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))))
{ {
PUT_CODE (insn, NOTE); PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0; NOTE_SOURCE_FILE (insn) = 0;
......
...@@ -2665,7 +2665,13 @@ void ...@@ -2665,7 +2665,13 @@ void
expand_null_return () expand_null_return ()
{ {
struct nesting *block = block_stack; struct nesting *block = block_stack;
rtx last_insn = 0; rtx last_insn = get_last_insn ();
/* If this function was declared to return a value, but we
didn't, clobber the return registers so that they are not
propogated live to the rest of the function. */
diddle_return_value (CLOBBER);
/* Does any pending block have cleanups? */ /* Does any pending block have cleanups? */
...@@ -2710,25 +2716,7 @@ expand_value_return (val) ...@@ -2710,25 +2716,7 @@ expand_value_return (val)
emit_move_insn (return_reg, val); emit_move_insn (return_reg, val);
} }
if (GET_CODE (return_reg) == REG diddle_return_value (USE);
&& REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
emit_insn (gen_rtx_USE (VOIDmode, return_reg));
/* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */
else if (GET_CODE (return_reg) == PARALLEL)
{
int i;
for (i = 0; i < XVECLEN (return_reg, 0); i++)
{
rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
if (GET_CODE (x) == REG
&& REGNO (x) < FIRST_PSEUDO_REGISTER)
emit_insn (gen_rtx_USE (VOIDmode, x));
}
}
/* Does any pending block have cleanups? */ /* Does any pending block have cleanups? */
......
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