diff options
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/function.h | 6 | ||||
-rw-r--r-- | gcc/omp-low.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gomp/pr34610.c | 30 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 15 | ||||
-rw-r--r-- | gcc/tree-profile.c | 10 |
7 files changed, 85 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 49c97380790..3fed0b22cab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2008-01-19 Jakub Jelinek <jakub@redhat.com> + + PR gcov-profile/34610 + * tree-cfg.c (make_edges): Mark both outgoing edges from + OMP_CONTINUE and from OMP_FOR as EDGE_ABNORMAL. + * omp-low.c (expand_omp_for): Clear EDGE_ABNORMAL bits + from OMP_FOR and OMP_CONTINUE outgoing edges. + + * tree-profile.c (tree_profiling): Return early if + cfun->after_tree_profile != 0. Set cfun->after_tree_profile + at the end. + * omp-low.c (expand_omp_parallel): Copy after_tree_profile + from cfun to child_cfun. + * function.h (struct function): Add after_tree_profile bit. + 2008-01-19 Anatoly Sokolov <aesok@post.ru> * config/avr/avr.S (_exit): Disable interrupt. diff --git a/gcc/function.h b/gcc/function.h index eb2a7530b9f..abc2303bcf7 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -1,6 +1,7 @@ /* Structure for saving state for a nested function. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2008 + Free Software Foundation, Inc. This file is part of GCC. @@ -459,6 +460,9 @@ struct function GTY(()) /* Nonzero if function being compiled needs to return the address of where it has put a structure value. */ unsigned int returns_pcc_struct : 1; + + /* Nonzero if pass_tree_profile was run on this function. */ + unsigned int after_tree_profile : 1; }; /* If va_list_[gf]pr_size is set to this, it means we don't know how diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 94d63b6a56a..ca0026604ce 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -2497,6 +2497,9 @@ expand_omp_parallel (struct omp_region *region) entry_stmt = last_stmt (region->entry); child_fn = OMP_PARALLEL_FN (entry_stmt); child_cfun = DECL_STRUCT_FUNCTION (child_fn); + /* If this function has been already instrumented, make sure + the child function isn't instrumented again. */ + child_cfun->after_tree_profile = cfun->after_tree_profile; entry_bb = region->entry; exit_bb = region->exit; @@ -3337,6 +3340,16 @@ expand_omp_for (struct omp_region *region) extract_omp_for_data (last_stmt (region->entry), &fd); region->sched_kind = fd.sched_kind; + gcc_assert (EDGE_COUNT (region->entry->succs) == 2); + BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL; + FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL; + if (region->cont) + { + gcc_assert (EDGE_COUNT (region->cont->succs) == 2); + BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL; + FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL; + } + if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC && !fd.have_ordered && region->cont != NULL) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 73c1e6084a0..11e4ed41082 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-01-19 Jakub Jelinek <jakub@redhat.com> + + PR gcov-profile/34610 + * gcc.dg/gomp/pr34610.c: New test. + 2008-01-19 Tobias Burnus <burnus@net-b.de> PR fortran/34760 diff --git a/gcc/testsuite/gcc.dg/gomp/pr34610.c b/gcc/testsuite/gcc.dg/gomp/pr34610.c new file mode 100644 index 00000000000..95353a5625e --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr34610.c @@ -0,0 +1,30 @@ +/* PR gcov-profile/34610 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fprofile-arcs -fopenmp" } */ + +extern void bar (int); +extern void baz (int) __attribute__((noreturn)); + +void +foo (int k) +{ + int i; +#pragma omp for schedule(dynamic) + for (i = 0; i < 10; ++i) + bar (i); +#pragma omp parallel for schedule(static) + for (i = 0; i < 10; ++i) + bar (i); +#pragma omp parallel for schedule(static, 4) + for (i = 0; i < 10; ++i) + bar (i); + if (k) + #pragma omp for schedule(dynamic) + for (i = 0; i < 10; ++i) + baz (i); +#pragma omp parallel + for (i = 0; i < 10; ++i) + bar (i); +} + +/* { dg-final { cleanup-coverage-files } } */ diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 8da55ff7cd9..c702502f1a7 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -1,5 +1,5 @@ /* Control flow functions for trees. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. Contributed by Diego Novillo <dnovillo@redhat.com> @@ -544,14 +544,19 @@ make_edges (void) switch (cur_region->type) { case OMP_FOR: + /* Mark all OMP_FOR and OMP_CONTINUE succs edges as abnormal + to prevent splitting them. */ + single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL; /* Make the loopback edge. */ - make_edge (bb, single_succ (cur_region->entry), 0); - + make_edge (bb, single_succ (cur_region->entry), + EDGE_ABNORMAL); + /* Create an edge from OMP_FOR to exit, which corresponds to the case that the body of the loop is not executed at all. */ - make_edge (cur_region->entry, bb->next_bb, 0); - fallthru = true; + make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL); + make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL); + fallthru = false; break; case OMP_SECTIONS: diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index 95c1136353b..00fbd862ad9 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -1,6 +1,6 @@ /* Calculate branch probabilities, and basic block execution counts. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. Contributed by James E. Wilson, UC Berkeley/Cygnus Support; based on some ideas from Dain Samples of UC Berkeley. @@ -419,8 +419,11 @@ static unsigned int tree_profiling (void) { /* Don't profile functions produced at destruction time, particularly - the gcov datastructure initializer. */ - if (cgraph_state == CGRAPH_STATE_FINISHED) + the gcov datastructure initializer. Don't profile if it has been + already instrumented either (when OpenMP expansion creates + child function from already instrumented body). */ + if (cgraph_state == CGRAPH_STATE_FINISHED + || cfun->after_tree_profile) return 0; /* Re-set global shared temporary variable for edge-counters. */ @@ -441,6 +444,7 @@ tree_profiling (void) easy to adjust it, if and when there is some. */ free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS); + cfun->after_tree_profile = 1; return 0; } |