function.c (diddle_return_value): New.
authorRichard Henderson <rth@gcc.gnu.org>
Fri, 5 Nov 1999 00:35:10 +0000 (16:35 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 5 Nov 1999 00:35:10 +0000 (16:35 -0800)
        * 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

gcc/ChangeLog
gcc/function.c
gcc/function.h
gcc/reg-stack.c
gcc/reload1.c
gcc/stmt.c

index b0cc01803a1e48031959e1144fba8fafd53fe6de..145a329c37169c9dda96c68fb88a511a7d70b4a0 100644 (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>
 
index a93f48b03220f263e6407db0f7ef0ff4d0d11e1c..0df0b82092d8a4aa03f16a0fabf1b9f1e5fa0a83 100644 (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)
index 24055e32b63320718218b6c7366ac15a53bb7257..f476bbee93736f1794d7c1c49b995b1faef8175e 100644 (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.  */
index e20e92e859568bd7e487d71aefb055e4fd0d83f2..4efaea1c73f59f8b330ebee915d04b6c0d849335 100644 (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);
-           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;
       }
index 5291d9bf3e756c0a54d806900a0260eb971c503b..2f50fb33c4d78d160ceb9b16578bbed18ac5e855 100644 (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;
index 715f6e0cd69e83c3d80f9a45a0ae34faa33a3a1c..f38b94fc942177c57894b0ad8eb2ab3e30c45c04 100644 (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?  */