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 PR38977, profile-feedback and fork


Building bash with profile-feedback runs into the situation that
we get inconsistent counters around a fork call because we expand
fork as __gcov_fork which flushes the current counters and zeros
them before calling fork.  This of course leads to the situation
of having only one incoming counter but two outgoing ones if the
child process doesn't immediately exec.

Previously this was hidden by us always creating fake edges for
all calls, but

2008-04-05  Ben Elliston  <bje@au.ibm.com>

        * tree-cfg.c (need_fake_edge_p): Return false for calls to
        builtins that return exactly once and do not throw. Cache call to
        call_expr_flags.

changed this to not include most builtins.  Unfortunately fork
is a builtin and is (correctly) not marked as ECF_RETURNS_TWICE.
Of course this doesn't matter here because of the above facts,
so the following patch simply makes sure to generate fake edges
for fork again.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2009-02-06  Richard Guenther  <rguenther@suse.de>

	PR middle-end/38977
	* tree-cfg.c (need_fake_edge_p): Force a fake edge for
	fork because we may expand it as __gcov_fork.

Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c	(revision 143959)
--- gcc/tree-cfg.c	(working copy)
*************** need_fake_edge_p (gimple t)
*** 6444,6452 ****
        && fndecl
        && DECL_BUILT_IN (fndecl)
        && (call_flags & ECF_NOTHROW)
!       && !(call_flags & ECF_NORETURN)
!       && !(call_flags & ECF_RETURNS_TWICE))
!    return false;
  
    if (is_gimple_call (t)
        && !(call_flags & ECF_NORETURN))
--- 6444,6457 ----
        && fndecl
        && DECL_BUILT_IN (fndecl)
        && (call_flags & ECF_NOTHROW)
!       && !(call_flags & ECF_RETURNS_TWICE)
!       /* fork() doesn't really return twice, but the effect of
!          wrapping it in __gcov_fork() which calls __gcov_flush()
! 	 and clears the counters before forking has the same
! 	 effect as returning twice.  Force a fake edge.  */
!       && !(DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
! 	   && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FORK))
!     return false;
  
    if (is_gimple_call (t)
        && !(call_flags & ECF_NORETURN))


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