diff options
-rw-r--r-- | gcc/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/function.c | 41 | ||||
-rw-r--r-- | gcc/function.h | 4 | ||||
-rw-r--r-- | gcc/reg-stack.c | 49 | ||||
-rw-r--r-- | gcc/reload1.c | 17 | ||||
-rw-r--r-- | gcc/stmt.c | 28 |
6 files changed, 118 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b0cc01803a1..145a329c371 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> diff --git a/gcc/function.c b/gcc/function.c index a93f48b0322..0df0b82092d 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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) diff --git a/gcc/function.h b/gcc/function.h index 24055e32b63..f476bbee937 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -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. */ diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index e20e92e8595..4efaea1c73f 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -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); - else + + if (pat != PATTERN (insn)) { - note = find_reg_note (insn, REG_UNUSED, *dest); - if (!note) - abort (); + /* 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 + { + /* 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; } diff --git a/gcc/reload1.c b/gcc/reload1.c index 5291d9bf3e7..2f50fb33c4d 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -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; diff --git a/gcc/stmt.c b/gcc/stmt.c index 715f6e0cd69..f38b94fc942 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -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? */ |