exit(0) is miscompiled under i686 linux
Richard Henderson
rth@cygnus.com
Sat Oct 7 14:03:00 GMT 2000
On Fri, Oct 06, 2000 at 07:42:57PM -0400, John David Anglin wrote:
> With todays cvs, I experienced failure of the first rdbz test in the
> libio testsuite. Tracking this, I find that the `exit(0);' statement
> in rdbzmain.c compiles to:
>
> movl $0, 8(%ebp)
> jmp exit
>
> with -O2 or -O3. As a result, the exit status value is garbage.
This is the fault of my noreturn patch -- sibcalls to noreturn
functions no longer got an edge to EXIT, which meant that the
code intended to insert sibcall_epilogue patterns didn't.
It's a quandry: we need the more accurate CFG for the "control
reaches end of non-void function" test. But then if we brute
force search for sibcalls to insert the sibcall_epilogue
patterns, we'll wind up with flow2 warning about wanting to
delete dead epilogue code (the loads for the call-saved registers
are dead becase we don't return).
I think the best way to solve this is to not create sibcalls
to noreturn functions. This is a pessimization for functions
that would otherwise be leaf functions, but a win otherwise,
since the epilogue code is usually larger than the call.
r~
* calls.c (expand_call): Disallow sibcalls to noreturn functions.
* flow.c (make_edges): Revert last change.
* config/alpha/alpha.h (FUNCTION_OK_FOR_SIBCALL): Don't test
TREE_THIS_VOLATILE.
* config/pa/pa.h (FUNCTION_OK_FOR_SIBCALL): Likewise.
Index: calls.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/calls.c,v
retrieving revision 1.158
diff -c -p -d -r1.158 calls.c
*** calls.c 2000/09/17 12:45:49 1.158
--- calls.c 2000/10/07 20:50:22
*************** expand_call (exp, target, ignore)
*** 2463,2468 ****
--- 2463,2469 ----
before the sibcall_epilogue. */
|| fndecl == NULL_TREE
|| (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP))
+ || TREE_THIS_VOLATILE (fndecl)
|| !FUNCTION_OK_FOR_SIBCALL (fndecl)
/* If this function requires more stack slots than the current
function, we cannot change it into a sibling call. */
Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.342
diff -c -p -d -r1.342 flow.c
*** flow.c 2000/10/06 06:01:26 1.342
--- flow.c 2000/10/07 20:50:23
*************** make_edges (label_value_list)
*** 1152,1163 ****
wouldn't have created the sibling call in the first place. */
if (code == CALL_INSN && SIBLING_CALL_P (insn))
! {
! if (! find_reg_note (insn, REG_NORETURN, NULL_RTX))
! make_edge (edge_cache, bb, EXIT_BLOCK_PTR,
! EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
! }
! else
/* If this is a CALL_INSN, then mark it as reaching the active EH
handler for this CALL_INSN. If we're handling asynchronous
--- 1152,1159 ----
wouldn't have created the sibling call in the first place. */
if (code == CALL_INSN && SIBLING_CALL_P (insn))
! make_edge (edge_cache, bb, EXIT_BLOCK_PTR,
! EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
/* If this is a CALL_INSN, then mark it as reaching the active EH
handler for this CALL_INSN. If we're handling asynchronous
*************** make_edges (label_value_list)
*** 1165,1171 ****
Also mark the CALL_INSN as reaching any nonlocal goto handler. */
! if (code == CALL_INSN || asynchronous_exceptions)
{
/* Add any appropriate EH edges. We do this unconditionally
since there may be a REG_EH_REGION or REG_EH_RETHROW note
--- 1161,1167 ----
Also mark the CALL_INSN as reaching any nonlocal goto handler. */
! else if (code == CALL_INSN || asynchronous_exceptions)
{
/* Add any appropriate EH edges. We do this unconditionally
since there may be a REG_EH_REGION or REG_EH_RETHROW note
Index: config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/alpha/alpha.h,v
retrieving revision 1.106
diff -c -p -d -r1.106 alpha.h
*** alpha.h 2000/10/02 08:21:35 1.106
--- alpha.h 2000/10/07 20:50:42
*************** extern int alpha_memory_latency;
*** 1187,1194 ****
#define FUNCTION_OK_FOR_SIBCALL(DECL) \
(DECL \
&& ((TREE_ASM_WRITTEN (DECL) && !flag_pic) \
! || ! TREE_PUBLIC (DECL) \
! || (0 && TREE_THIS_VOLATILE (DECL))))
/* Try to output insns to set TARGET equal to the constant C if it can be
done in less than N insns. Do all computations in MODE. Returns the place
--- 1187,1193 ----
#define FUNCTION_OK_FOR_SIBCALL(DECL) \
(DECL \
&& ((TREE_ASM_WRITTEN (DECL) && !flag_pic) \
! || ! TREE_PUBLIC (DECL)))
/* Try to output insns to set TARGET equal to the constant C if it can be
done in less than N insns. Do all computations in MODE. Returns the place
Index: config/pa/pa.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/pa/pa.h,v
retrieving revision 1.93
diff -c -p -d -r1.93 pa.h
*** pa.h 2000/09/25 10:11:22 1.93
--- pa.h 2000/10/07 20:50:43
*************** while (0)
*** 2014,2021 ****
#define FUNCTION_OK_FOR_SIBCALL(DECL) \
(DECL \
&& ! TARGET_64BIT \
! && (! TREE_PUBLIC (DECL) \
! || TREE_THIS_VOLATILE (DECL)))
#define PREDICATE_CODES \
{"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
--- 2014,2020 ----
#define FUNCTION_OK_FOR_SIBCALL(DECL) \
(DECL \
&& ! TARGET_64BIT \
! && ! TREE_PUBLIC (DECL))
#define PREDICATE_CODES \
{"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
More information about the Gcc-patches
mailing list