diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/omp-low.c | 34 | ||||
-rw-r--r-- | libgomp/ChangeLog | 5 | ||||
-rw-r--r-- | libgomp/testsuite/libgomp.c/reduction-5.c | 78 |
4 files changed, 121 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb6c434e6..f2c5185 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2008-06-12 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/36506 + * omp-low.c (expand_omp_sections): Handle #pragma omp sections with + reductions. + 2008-06-12 Richard Guenther <rguenther@suse.de> PR tree-optimization/36345 diff --git a/gcc/omp-low.c b/gcc/omp-low.c index e9223b2..85b8333 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -4389,6 +4389,8 @@ expand_omp_sections (struct omp_region *region) unsigned i, casei, len; basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb; block_stmt_iterator si; + edge_iterator ei; + edge e; struct omp_region *inner; bool exit_reachable = region->cont != NULL; @@ -4399,10 +4401,30 @@ expand_omp_sections (struct omp_region *region) l2_bb = region->exit; if (exit_reachable) { - gcc_assert (single_pred (l2_bb) == l0_bb); + if (single_pred (l2_bb) == l0_bb) + l2 = tree_block_label (l2_bb); + else + { + /* This can happen if there are reductions. */ + len = EDGE_COUNT (l0_bb->succs); + gcc_assert (len > 0); + e = EDGE_SUCC (l0_bb, len - 1); + si = bsi_last (e->dest); + if (bsi_end_p (si) || TREE_CODE (bsi_stmt (si)) != OMP_SECTION) + l2 = tree_block_label (e->dest); + else + FOR_EACH_EDGE (e, ei, l0_bb->succs) + { + si = bsi_last (e->dest); + if (bsi_end_p (si) || TREE_CODE (bsi_stmt (si)) != OMP_SECTION) + { + l2 = tree_block_label (e->dest); + break; + } + } + } default_bb = create_empty_bb (l1_bb->prev_bb); l1 = tree_block_label (l1_bb); - l2 = tree_block_label (l2_bb); } else { @@ -4480,6 +4502,14 @@ expand_omp_sections (struct omp_region *region) { basic_block s_entry_bb, s_exit_bb; + /* Skip optional reduction region. */ + if (inner->type == OMP_ATOMIC_LOAD) + { + --i; + --casei; + continue; + } + s_entry_bb = inner->entry; s_exit_bb = inner->exit; diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index fb70823c..ff9ed03 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,8 @@ +2008-06-12 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/36506 + * testsuite/libgomp.c/reduction-5.c: New test. + 2008-06-11 Jakub Jelinek <jakub@redhat.com> * libgomp.h (struct gomp_task): Add in_tied_task field. diff --git a/libgomp/testsuite/libgomp.c/reduction-5.c b/libgomp/testsuite/libgomp.c/reduction-5.c new file mode 100644 index 0000000..de87d9f --- /dev/null +++ b/libgomp/testsuite/libgomp.c/reduction-5.c @@ -0,0 +1,78 @@ +/* PR middle-end/36506 */ + +extern void abort (void); + +int +main (void) +{ + int sum = 0, prod = 1; +#pragma omp parallel + #pragma omp sections reduction (+:sum) + { + #pragma omp section + sum += 2; + #pragma omp section + sum += 2; + #pragma omp section + sum += 2; + } + if (sum != 6) + abort (); + sum = 0; +#pragma omp parallel sections reduction (+:sum) + { + #pragma omp section + sum += 2; + #pragma omp section + sum += 2; + #pragma omp section + sum += 2; + } + if (sum != 6) + abort (); + sum = 0; +#pragma omp parallel + #pragma omp sections reduction (+:sum) reduction (*:prod) + { + #pragma omp section + { + sum += 2; + prod *= 2; + } + #pragma omp section + { + sum += 2; + prod *= 2; + } + #pragma omp section + { + sum += 2; + prod *= 2; + } + } + if (sum != 6 || prod != 8) + abort (); + sum = 0; + prod = 1; +#pragma omp parallel sections reduction (+:sum) reduction (*:prod) + { + #pragma omp section + { + sum += 2; + prod *= 2; + } + #pragma omp section + { + sum += 2; + prod *= 2; + } + #pragma omp section + { + sum += 2; + prod *= 2; + } + } + if (sum != 6 || prod != 8) + abort (); + return 0; +} |