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
This commit is contained in:
Richard Henderson 1999-11-04 16:35:10 -08:00
parent 49886fe1ce
commit bd695e1e9d
6 changed files with 118 additions and 54 deletions

View File

@ -1,3 +1,14 @@
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>
* rtl.c (read_rtx): Use fatal_with_file_and_line not fatal.
@ -78,17 +89,17 @@ Wed Nov 3 14:51:59 1999 Mark P. Mitchell <mark@codesourcery.com>
Wed Nov 3 15:40:23 1999 Catherine Moore <clm@cygnus.com>
* defaults.h (ASM_OUTPUT_ALTERNATE_LABEL_NAME): Provide default.
* emit-rtl.c (gen_label_rtx): Support LABEL_ALTERNATE_NAME.
* final.c (final_scan_insn): Emit LABEL_ALTERNATE_NAME.
* ggc-common.c (ggc_mark_rtx_children): Mark LABEL_ALTERNATE_NAME.
* jump.c (delete_unreferenced_labels): Don't delete if
LABEL_ALTERNATE_NAME is set.
* print-rtl.c (print_rtx): Dump alternate name.
* rtl.def (CODE_LABEL): Change format to "iuuis00s".
* rtl.h (LABEL_ALTERNATE_NAME): Define.
* rtl.texi (LABEL_ALTERNATE_NAME): Document.
* tm.texi (ASM_OUTPUT_ALTERNATE_LABEL_NAME): Document.
* defaults.h (ASM_OUTPUT_ALTERNATE_LABEL_NAME): Provide default.
* emit-rtl.c (gen_label_rtx): Support LABEL_ALTERNATE_NAME.
* final.c (final_scan_insn): Emit LABEL_ALTERNATE_NAME.
* ggc-common.c (ggc_mark_rtx_children): Mark LABEL_ALTERNATE_NAME.
* jump.c (delete_unreferenced_labels): Don't delete if
LABEL_ALTERNATE_NAME is set.
* print-rtl.c (print_rtx): Dump alternate name.
* rtl.def (CODE_LABEL): Change format to "iuuis00s".
* rtl.h (LABEL_ALTERNATE_NAME): Define.
* rtl.texi (LABEL_ALTERNATE_NAME): Document.
* tm.texi (ASM_OUTPUT_ALTERNATE_LABEL_NAME): Document.
Wed Nov 3 15:39:19 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>

View File

@ -6150,6 +6150,36 @@ expand_dummy_function_end ()
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.
FILENAME and LINE are the current position in the source file.
@ -6332,7 +6362,16 @@ expand_function_end (filename, line, end_bindings)
structure returning. */
if (return_label)
emit_label (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);
}
/* C++ uses this. */
if (end_bindings)

View File

@ -578,6 +578,10 @@ extern void free_expr_status PROTO((struct function *));
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 *));
/* Called once, at initialization, to initialize function.c. */

View File

@ -1394,27 +1394,48 @@ subst_stack_regs_pat (insn, regstack, pat)
{
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));
if (STACK_REG_P (*dest))
{
note = find_reg_note (insn, REG_DEAD, *dest);
if (note)
emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
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)
emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
else
{
note = find_reg_note (insn, REG_UNUSED, *dest);
if (!note)
abort ();
}
remove_note (insn, note);
replace_reg (dest, LAST_STACK_REG);
}
else
{
note = find_reg_note (insn, REG_UNUSED, *dest);
if (!note)
abort ();
}
/* 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. */
remove_note (insn, note);
replace_reg (dest, LAST_STACK_REG);
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;
}

View File

@ -1106,13 +1106,12 @@ reload (first, global, dumpfile)
which are only valid during and after reload. */
reload_completed = 1;
/* Make a pass over all the insns and delete all USEs which we
inserted only to tag a REG_EQUAL note on them. Remove all
REG_DEAD and REG_UNUSED notes. Delete all CLOBBER insns and
simplify (subreg (reg)) operands. Also remove all REG_RETVAL and
REG_LIBCALL notes since they are no longer useful or accurate.
Strip and regenerate REG_INC notes that may have been moved
around. */
/* Make a pass over all the insns and delete all USEs which we inserted
only to tag a REG_EQUAL note on them. Remove all REG_DEAD and REG_UNUSED
notes. Delete all CLOBBER insns that don't refer to the return value
and simplify (subreg (reg)) operands. Also remove all REG_RETVAL and
REG_LIBCALL notes since they are no longer useful or accurate. Strip
and regenerate REG_INC notes that may have been moved around. */
for (insn = first; insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
@ -1121,7 +1120,9 @@ reload (first, global, dumpfile)
if ((GET_CODE (PATTERN (insn)) == USE
&& 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);
NOTE_SOURCE_FILE (insn) = 0;

View File

@ -2665,7 +2665,13 @@ void
expand_null_return ()
{
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? */
@ -2710,25 +2716,7 @@ expand_value_return (val)
emit_move_insn (return_reg, val);
}
if (GET_CODE (return_reg) == REG
&& 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));
}
}
diddle_return_value (USE);
/* Does any pending block have cleanups? */