diff options
author | Jakub Jelinek <jakub@redhat.com> | 2008-06-12 13:03:50 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-06-12 13:03:50 +0200 |
commit | c34938a8aa48af61df1835c2c0dab95d4ef6ca1a (patch) | |
tree | 8845c75445d9484761a9f34010411ff92b5aefca /gcc/omp-low.c | |
parent | b377855627f22cdef5712621e89e68048a94a164 (diff) | |
download | gcc-c34938a8aa48af61df1835c2c0dab95d4ef6ca1a.tar.gz |
re PR middle-end/36506 (Broken #pragma omp sections reduction (+:x))
PR middle-end/36506
* omp-low.c (expand_omp_sections): Handle #pragma omp sections with
reductions.
* testsuite/libgomp.c/reduction-5.c: New test.
From-SVN: r136696
Diffstat (limited to 'gcc/omp-low.c')
-rw-r--r-- | gcc/omp-low.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/gcc/omp-low.c b/gcc/omp-low.c index e9223b2afb2..85b83332ff8 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; |