This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR c/6358


Hi!

The following testcase would ICE, because current_function_return_rtx
was used (in diddle_return_value called down from expand_null_return)
before it was changed to the actual hard register in expand_function_end.
Thus, we ended up with:

(insn 10 8 11 (clobber (reg:DF 58)) -1 (nil)
    (nil))

(insn 11 10 12 (clobber (reg:DF 58)) -1 (nil)
    (nil))

(jump_insn 12 11 13 (set (pc)
        (label_ref 16)) -1 (nil)
    (nil))

(barrier 13 12 14)

(note 14 13 19 NOTE_INSN_FUNCTION_END)

(insn 19 14 20 (clobber (reg/i:DF 8 st(0))) -1 (nil)
    (nil))

(insn 20 19 16 (clobber (reg:DF 58)) -1 (nil)
    (nil))

(code_label 16 20 18 1 "" "" [0 uses])

(insn 18 16 21 (set (reg/i:DF 8 st(0))
        (reg:DF 58)) -1 (nil)
    (nil))

(insn 21 18 0 (use (reg/i:DF 8 st(0))) -1 (nil)
    (nil))

while insn 10 should have been (clobber (reg/i:DF 8 st(0))).
Fixed by splitting real_decl_rtl assignment into assign_parms
and leaving the rest (copying DECL_RTL(DECL_RESULT(current_function_decl))
into it) in expand_function_end.
>From what I could see, all users of current_function_return_rtx outside
of function.c are post expand_function_end (thus nothing changes for them
by this patch) and the only place where it should make a difference is in
diddle_return_value where we really want the hard register, not pseudo.
Ok to commit if testing succeeds?

2002-04-18  Jakub Jelinek  <jakub@redhat.com>

	PR c/6358
	* function.c (assign_parms): Assign hard current_function_return_rtx
	register here...
	(expand_function_end): ...not here.

	* gcc.c-torture/compile/20020418-1.c: New test.

--- gcc/testsuite/gcc.c-torture/compile/20020418-1.c.jj	Thu Apr 18 18:39:31 2002
+++ gcc/testsuite/gcc.c-torture/compile/20020418-1.c	Thu Apr 18 18:35:44 2002
@@ -0,0 +1,18 @@
+/* PR c/6358
+   This testcase ICEd on IA-32 in foo, because current_function_return_rtx
+   was assigned a hard register only after expand_null_return was called,
+   thus return pseudo was clobbered twice and the hard register not at
+   all.  */
+
+void baz (void);
+                       
+double foo (void)
+{
+  baz ();
+  return;
+}
+
+double bar (void)
+{
+  baz ();
+}
--- gcc/function.c.jj	Mon Apr 15 14:42:04 2002
+++ gcc/function.c	Thu Apr 18 18:31:42 2002
@@ -5144,6 +5144,35 @@ assign_parms (fndecl)
   current_function_return_rtx
     = (DECL_RTL_SET_P (DECL_RESULT (fndecl))
        ? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX);
+
+  /* If scalar return value was computed in a pseudo-reg, or was a named
+     return value that got dumped to the stack, copy that to the hard
+     return register.  */
+  if (DECL_RTL_SET_P (DECL_RESULT (fndecl)))
+    {
+      tree decl_result = DECL_RESULT (fndecl);
+      rtx decl_rtl = DECL_RTL (decl_result);
+
+      if (REG_P (decl_rtl)
+	  ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
+	  : DECL_REGISTER (decl_result))
+	{
+	  rtx real_decl_rtl;
+
+#ifdef FUNCTION_OUTGOING_VALUE
+	  real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result),
+						   fndecl);
+#else
+	  real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result),
+					  fndecl);
+#endif
+	  REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
+	  /* The delay slot scheduler assumes that current_function_return_rtx
+	     holds the hard register containing the return value, not a
+	     temporary pseudo.  */
+	  current_function_return_rtx = real_decl_rtl;
+	}
+    }
 }
 
 /* Indicate whether REGNO is an incoming argument to the current function
@@ -6957,16 +6986,11 @@ expand_function_end (filename, line, end
 	  ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
 	  : DECL_REGISTER (decl_result))
 	{
-	  rtx real_decl_rtl;
+	  rtx real_decl_rtl = current_function_return_rtx;
 
-#ifdef FUNCTION_OUTGOING_VALUE
-	  real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result),
-						   current_function_decl);
-#else
-	  real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result),
-					  current_function_decl);
-#endif
-	  REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
+	  /* This should be set in assign_parms.  */
+	  if (! REG_FUNCTION_VALUE_P (real_decl_rtl))
+	    abort ();
 
 	  /* If this is a BLKmode structure being returned in registers,
 	     then use the mode computed in expand_return.  Note that if
@@ -6994,11 +7018,6 @@ expand_function_end (filename, line, end
 			     int_size_in_bytes (TREE_TYPE (decl_result)));
 	  else
 	    emit_move_insn (real_decl_rtl, decl_rtl);
-
-	  /* The delay slot scheduler assumes that current_function_return_rtx
-	     holds the hard register containing the return value, not a
-	     temporary pseudo.  */
-	  current_function_return_rtx = real_decl_rtl;
 	}
     }
 

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]