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. */
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);
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
{
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);
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);
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);
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
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);
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
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)
{
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;
}
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))
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;
+ }
}
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;
+ }
}