summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog33
-rw-r--r--gcc/function.c41
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/reg-stack.c49
-rw-r--r--gcc/reload1.c17
-rw-r--r--gcc/stmt.c28
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? */
OpenPOWER on IntegriCloud