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]

Fix for i386 execute/20000731-1.c (sibcall versus regstack)


20000731-1.c reads in part

double foo(void) { return 0.0; }
void bar(void) { (void) foo(); }

On a sensible architecture, it would be safe to use a sibling call to
go from bar to foo.  The 0.0 would be returned in a call-clobbered
floating point register and bar's caller would have no problem.  But
on the x86, the 0.0 is returned in the 387 stack and bar() must pop it
off.  So we can't do that optimization.

Unfortunately, the drop instruction is generated by regstack, which
happens far too late for sibcall to notice that there's a nontrivial
operation between the call to foo and the return from bar.  At -O2 and
-Os, therefore, the above is miscompiled.  At -O1 sibcall is not done;
at -O3, foo is inlined into bar and the problem vanishes.
-mno-fp-ret-in-387 also avoids the bug.

The cure is to disallow sibcall from functions that do not return
floats to functions that do.  Note that the optimization is still
safe for e.g.

double foo(double n) { return n * 2; }
double bar(double n) { return bar(n + 1); }

zw

	* i386.h (FUNCTION_OK_FOR_SIBCALL):  Not OK if DECL's return
	type is a float mode, cfun->decl's return type is not, and
	TARGET_FLOAT_RETURNS_IN_80387.

	* gcc.c-torture/execute/20000731-1.x: Delete.

===================================================================
Index: config/i386/i386.h
--- config/i386/i386.h	2000/07/31 17:33:28	1.121
+++ config/i386/i386.h	2000/08/05 15:45:43
@@ -1319,10 +1319,16 @@ typedef struct ix86_args {
 
 #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
 
-/* If PIC, we cannot optimize sibling calls to global functions
-   because the PLT requires %ebx live.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) \
-  (DECL && (! flag_pic || ! TREE_PUBLIC (DECL)))
+/* If PIC, we cannot make sibling calls to global functions
+   because the PLT requires %ebx live.
+   If we are returning floats on the register stack, we cannot make
+   sibling calls to functions that return floats.  (The stack adjust
+   instruction will wind up after the sibcall jump, and not be executed.) */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) (DECL \
+   && (! flag_pic || ! TREE_PUBLIC (DECL)) \
+   && (! TARGET_FLOAT_RETURNS_IN_80387 \
+       || ! FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (DECL)))) \
+       || FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl))))))
 
 /* This macro is invoked just before the start of a function.
    It is used here to output code for -fpic that will load the
===================================================================
Index: testsuite/gcc.c-torture/execute/20000731-1.x
--- testsuite/gcc.c-torture/execute/20000731-1.x	Sat Aug  5 08:45:44 2000
+++ testsuite/gcc.c-torture/execute/20000731-1.x	Tue May  5 13:32:27 1998
@@ -1,3 +0,0 @@
-# Doesn't work.  Hasn't worked ever, I think.
-set torture_execute_xfail "i?86-*-*"
-return 0


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