diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8ab2a1a1f5d3..f5627878c70d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,8 @@ 2005-07-27 Jan Hubicka + * tree-tailcall.c (decrease_profile): New function. + (eliminate_tail_call): Use it. + * cgraphunit.c (cgraph_function_and_variable_visibility): Set visibility flags correctly in whole program mode. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1025b6b9e471..a874b2ad4c5c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-07-27 Jan Hubicka + + * inliner-1.c: Add cleanup of dumps. + * val-prof-*.c: Likewise. + * update-tailcall.c: New. + 2005-07-26 Diego Novillo PR 22591 diff --git a/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c b/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c index 9a1cd01f337e..b27b4fdc81bc 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c @@ -35,3 +35,4 @@ main () declaration or other apperances of the string in dump. */ /* { dg-final-use { scan-tree-dump "cold_function ..;" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "hot_function ..;" "optimized"} } */ +/* { dg-final-use { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-prof/update-tailcall.c b/gcc/testsuite/gcc.dg/tree-prof/update-tailcall.c new file mode 100644 index 000000000000..32ad34857b56 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/update-tailcall.c @@ -0,0 +1,20 @@ +/* { dg-options "-O2 -fdump-tree-tailcall -fdump-tree-optimized" } */ +__attribute__ ((noinline)) +int factorial(int x) +{ + if (x == 1) + return 1; + else + return x*factorial(--x); +} +int gbl; +int +main() +{ + gbl = factorial(100); + return 0; +} +/* { dg-final-use { scan-tree-dump-not "Invalid sum" "tailc"} } */ +/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ +/* { dg-final-use { cleanup-tree-dump "tailc" } } */ +/* { dg-final-use { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c index db3bc950f5a6..dfe994ffef9b 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c @@ -18,3 +18,5 @@ main () /* { dg-final-use { scan-tree-dump "Div.mod by constant n=257 transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-tree-dump "if \\(n != 257\\)" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ +/* { dg-final-use { cleanup-tree-dump "optimized" } } */ +/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c index c11f7ea20e42..49a98e35958c 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c +++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c @@ -28,3 +28,5 @@ main () didn't get optimized out. */ /* { dg-final-use { scan-tree-dump "n \\+ \\-1" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ +/* { dg-final-use { cleanup-tree-dump "optimized" } } */ +/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c index 91ebd376177f..f233d670cc2e 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c +++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c @@ -28,3 +28,5 @@ main () didn't get optimized out. */ /* { dg-final-use { scan-tree-dump "if \\(n \\>" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ +/* { dg-final-use { cleanup-tree-dump "optimized" } } */ +/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c index 4fff1123beb6..86418e05e3af 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c +++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c @@ -28,3 +28,5 @@ main () didn't get optimized out. */ /* { dg-final-use { scan-tree-dump "if \\(n \\>" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ +/* { dg-final-use { cleanup-tree-dump "optimized" } } */ +/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index 3a40a61d1ed2..3c7518d7b860 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -668,6 +668,29 @@ adjust_return_value (basic_block bb, tree m, tree a) update_stmt (ret_stmt); } +/* Subtract COUNT and FREQUENCY from the basic block and it's + outgoing edge. */ +static void +decrease_profile (basic_block bb, gcov_type count, int frequency) +{ + edge e; + bb->count -= count; + if (bb->count < 0) + bb->count = 0; + bb->frequency -= frequency; + if (bb->frequency < 0) + bb->frequency = 0; + if (!single_succ_p (bb)) + { + gcc_assert (!EDGE_COUNT (bb->succs)); + return; + } + e = single_succ_edge (bb); + e->count -= count; + if (e->count < 0) + e->count = 0; +} + /* Eliminates tail call described by T. TMP_VARS is a list of temporary variables used to copy the function arguments. */ @@ -717,6 +740,13 @@ eliminate_tail_call (struct tailcall *t) release_defs (t); } + /* Number of executions of function has reduced by the tailcall. */ + e = single_succ_edge (t->call_block); + decrease_profile (EXIT_BLOCK_PTR, e->count, EDGE_FREQUENCY (e)); + decrease_profile (ENTRY_BLOCK_PTR, e->count, EDGE_FREQUENCY (e)); + if (e->dest != EXIT_BLOCK_PTR) + decrease_profile (e->dest, e->count, EDGE_FREQUENCY (e)); + /* Replace the call by a jump to the start of function. */ e = redirect_edge_and_branch (single_succ_edge (t->call_block), first); gcc_assert (e);