diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-04 10:20:51 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-04 10:20:51 +0000 |
commit | 03ed154b4d8e57e186b37733cf5b095a5f506a2f (patch) | |
tree | 8a7fb7efd8062ba4c47caab5ee275060e1dd09a5 /gcc/omp-low.c | |
parent | 8469434ffecc1151fea8f2f78e0f8bd70ab21acb (diff) | |
download | gcc-03ed154b4d8e57e186b37733cf5b095a5f506a2f.tar.gz |
PR middle-end/29965
* omp-low.c (determine_parallel_type): Don't try to optimize combined
parallels if region->exit or region->inner->exit is NULL.
(expand_omp_parallel): Handle NULL region->exit even if cfg is already
built.
(expand_omp_for_generic): Handle NULL region->cond and region->exit.
(expand_omp_for): Use expand_omp_for_generic if either region->cond
or region->exit is NULL.
(expand_omp_sections): Handle NULL region->cond or region->exit.
(expand_omp_synch):
* gcc.dg/gomp/pr29965-1.c: New test.
* gcc.dg/gomp/pr29965-2.c: New test.
* gcc.dg/gomp/pr29965-3.c: New test.
* gcc.dg/gomp/pr29965-4.c: New test.
* gcc.dg/gomp/pr29965-5.c: New test.
* gcc.dg/gomp/pr29965-6.c: New test.
* g++.dg/gomp/pr29965-1.C: New test.
* g++.dg/gomp/pr29965-2.C: New test.
* g++.dg/gomp/pr29965-3.C: New test.
* g++.dg/gomp/pr29965-4.C: New test.
* g++.dg/gomp/pr29965-5.C: New test.
* g++.dg/gomp/pr29965-6.C: New test.
* g++.dg/gomp/pr29965-7.C: New test.
* g++.dg/gomp/pr29965-8.C: New test.
* g++.dg/gomp/pr29965-9.C: New test.
* g++.dg/gomp/pr29965-10.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119483 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/omp-low.c')
-rw-r--r-- | gcc/omp-low.c | 150 |
1 files changed, 103 insertions, 47 deletions
diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 0816103f190..30dbc713e8d 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -365,7 +365,8 @@ determine_parallel_type (struct omp_region *region) basic_block par_entry_bb, par_exit_bb; basic_block ws_entry_bb, ws_exit_bb; - if (region == NULL || region->inner == NULL) + if (region == NULL || region->inner == NULL + || region->exit == NULL || region->inner->exit == NULL) return; /* We only support parallel+for and parallel+sections. */ @@ -2443,7 +2444,6 @@ expand_omp_parallel (struct omp_region *region) block_stmt_iterator si; entry_succ_e = single_succ_edge (entry_bb); - exit_succ_e = single_succ_edge (exit_bb); si = bsi_last (entry_bb); gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL); @@ -2451,7 +2451,11 @@ expand_omp_parallel (struct omp_region *region) new_bb = entry_bb; remove_edge (entry_succ_e); - make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU); + if (exit_bb) + { + exit_succ_e = single_succ_edge (exit_bb); + make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU); + } } else { @@ -2574,10 +2578,11 @@ expand_omp_for_generic (struct omp_region *region, enum built_in_function start_fn, enum built_in_function next_fn) { - tree l0, l1, l2, l3; + tree l0, l1, l2 = NULL, l3 = NULL; tree type, istart0, iend0, iend; tree t, args, list; - basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l3_bb; + basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb; + basic_block l2_bb = NULL, l3_bb = NULL; block_stmt_iterator si; bool in_combined_parallel = is_combined_parallel (region); @@ -2589,18 +2594,25 @@ expand_omp_for_generic (struct omp_region *region, TREE_ADDRESSABLE (istart0) = 1; TREE_ADDRESSABLE (iend0) = 1; + gcc_assert ((region->cont != NULL) ^ (region->exit == NULL)); + entry_bb = region->entry; l0_bb = create_empty_bb (entry_bb); l1_bb = single_succ (entry_bb); - cont_bb = region->cont; - l2_bb = create_empty_bb (cont_bb); - l3_bb = single_succ (cont_bb); - exit_bb = region->exit; l0 = tree_block_label (l0_bb); l1 = tree_block_label (l1_bb); - l2 = tree_block_label (l2_bb); - l3 = tree_block_label (l3_bb); + + cont_bb = region->cont; + exit_bb = region->exit; + if (cont_bb) + { + l2_bb = create_empty_bb (cont_bb); + l3_bb = single_succ (cont_bb); + + l2 = tree_block_label (l2_bb); + l3 = tree_block_label (l3_bb); + } si = bsi_last (entry_bb); gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR); @@ -2626,9 +2638,12 @@ expand_omp_for_generic (struct omp_region *region, args = tree_cons (NULL, t, args); t = build_function_call_expr (built_in_decls[start_fn], args); t = get_formal_tmp_var (t, &list); - t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0), - build_and_jump (&l3)); - append_to_statement_list (t, &list); + if (cont_bb) + { + t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0), + build_and_jump (&l3)); + append_to_statement_list (t, &list); + } bsi_insert_after (&si, list, BSI_SAME_STMT); } bsi_remove (&si, true); @@ -2646,6 +2661,15 @@ expand_omp_for_generic (struct omp_region *region, si = bsi_start (l0_bb); bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); + /* Handle the rare case where BODY doesn't ever return. */ + if (cont_bb == NULL) + { + remove_edge (single_succ_edge (entry_bb)); + make_edge (entry_bb, l0_bb, EDGE_FALLTHRU); + make_edge (l0_bb, l1_bb, EDGE_FALLTHRU); + return; + } + /* Code to control the increment and predicate for the sequential loop goes in the first half of EXIT_BB (we split EXIT_BB so that we can inherit all the edges going out of the loop @@ -3098,7 +3122,10 @@ expand_omp_for (struct omp_region *region) extract_omp_for_data (last_stmt (region->entry), &fd); region->sched_kind = fd.sched_kind; - if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC && !fd.have_ordered) + if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC + && !fd.have_ordered + && region->cont + && region->exit) { if (fd.chunk_size == NULL) expand_omp_for_static_nochunk (region, &fd); @@ -3156,15 +3183,28 @@ expand_omp_sections (struct omp_region *region) entry_bb = region->entry; l0_bb = create_empty_bb (entry_bb); + l0 = tree_block_label (l0_bb); + + gcc_assert ((region->cont != NULL) ^ (region->exit == NULL)); l1_bb = region->cont; - l2_bb = single_succ (l1_bb); - default_bb = create_empty_bb (l1_bb->prev_bb); - exit_bb = region->exit; + if (l1_bb) + { + l2_bb = single_succ (l1_bb); + default_bb = create_empty_bb (l1_bb->prev_bb); - l0 = tree_block_label (l0_bb); - l1 = tree_block_label (l1_bb); + l1 = tree_block_label (l1_bb); + } + else + { + l2_bb = create_empty_bb (l0_bb); + default_bb = l2_bb; + + l1 = NULL; + } l2 = tree_block_label (l2_bb); + exit_bb = region->exit; + v = create_tmp_var (unsigned_type_node, ".section"); /* We will build a switch() with enough cases for all the @@ -3201,7 +3241,7 @@ expand_omp_sections (struct omp_region *region) build_int_cst (unsigned_type_node, 0), NULL, l2); TREE_VEC_ELT (label_vec, 0) = t; make_edge (l0_bb, l2_bb, 0); - + /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */ for (inner = region->inner, i = 1; inner; inner = inner->next, ++i) { @@ -3220,15 +3260,19 @@ expand_omp_sections (struct omp_region *region) gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si))); bsi_remove (&si, true); - si = bsi_last (s_exit_bb); - gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN); - bsi_remove (&si, true); - e = single_pred_edge (s_entry_bb); e->flags = 0; redirect_edge_pred (e, l0_bb); single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU; + + if (s_exit_bb == NULL) + continue; + + si = bsi_last (s_exit_bb); + gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN); + bsi_remove (&si, true); + single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU; } @@ -3244,24 +3288,30 @@ expand_omp_sections (struct omp_region *region) bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); /* Code to get the next section goes in L1_BB. */ - si = bsi_last (l1_bb); - gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE); + if (l1_bb) + { + si = bsi_last (l1_bb); + gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE); - t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT]; - t = build_function_call_expr (t, NULL); - t = build2 (MODIFY_EXPR, void_type_node, v, t); - bsi_insert_after (&si, t, BSI_SAME_STMT); - bsi_remove (&si, true); + t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT]; + t = build_function_call_expr (t, NULL); + t = build2 (MODIFY_EXPR, void_type_node, v, t); + bsi_insert_after (&si, t, BSI_SAME_STMT); + bsi_remove (&si, true); + } /* Cleanup function replaces OMP_RETURN in EXIT_BB. */ - si = bsi_last (exit_bb); - if (OMP_RETURN_NOWAIT (bsi_stmt (si))) - t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT]; - else - t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END]; - t = build_function_call_expr (t, NULL); - bsi_insert_after (&si, t, BSI_SAME_STMT); - bsi_remove (&si, true); + if (exit_bb) + { + si = bsi_last (exit_bb); + if (OMP_RETURN_NOWAIT (bsi_stmt (si))) + t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT]; + else + t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END]; + t = build_function_call_expr (t, NULL); + bsi_insert_after (&si, t, BSI_SAME_STMT); + bsi_remove (&si, true); + } /* Connect the new blocks. */ if (is_combined_parallel (region)) @@ -3274,9 +3324,12 @@ expand_omp_sections (struct omp_region *region) else make_edge (entry_bb, l0_bb, EDGE_FALLTHRU); - e = single_succ_edge (l1_bb); - redirect_edge_succ (e, l0_bb); - e->flags = EDGE_FALLTHRU; + if (l1_bb) + { + e = single_succ_edge (l1_bb); + redirect_edge_succ (e, l0_bb); + e->flags = EDGE_FALLTHRU; + } } @@ -3337,10 +3390,13 @@ expand_omp_synch (struct omp_region *region) bsi_remove (&si, true); single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; - si = bsi_last (exit_bb); - gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN); - bsi_remove (&si, true); - single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU; + if (exit_bb) + { + si = bsi_last (exit_bb); + gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN); + bsi_remove (&si, true); + single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU; + } } |