2019-05-27 Jakub Jelinek <jakub@redhat.com>
+ * gimplify.c (gimplify_scan_omp_clauses): Allow lastprivate conditional
+ on sections construct.
+ * omp-low.c (lower_lastprivate_conditional_clauses): Handle sections
+ construct.
+ (lower_omp_sections): Handle lastprivate conditional.
+ (lower_omp_1) <case GIMPLE_ASSIGN>: Handle sections construct with
+ lastprivate_conditional_map.
+ * omp-expand.c (expand_omp_sections): Handle lastprivate conditional.
+
* omp-low.c (lower_omp_1) <case GIMPLE_ASSIGN>: Look through ordered,
critical, taskgroup and section regions when looking for a region
with non-NULL lastprivate_conditional_map.
}
if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
{
- if (code == OMP_FOR)
+ if (code == OMP_FOR || code == OMP_SECTIONS)
flags |= GOVD_LASTPRIVATE_CONDITIONAL;
else
{
vin = gimple_omp_sections_control (sections_stmt);
tree clauses = gimple_omp_sections_clauses (sections_stmt);
tree reductmp = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
- if (reductmp)
- {
- tree reductions = OMP_CLAUSE_DECL (reductmp);
- gcc_assert (TREE_CODE (reductions) == SSA_NAME);
- gimple *g = SSA_NAME_DEF_STMT (reductions);
- reductions = gimple_assign_rhs1 (g);
- OMP_CLAUSE_DECL (reductmp) = reductions;
- gimple_stmt_iterator gsi = gsi_for_stmt (g);
+ tree condtmp = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
+ tree cond_var = NULL_TREE;
+ if (reductmp || condtmp)
+ {
+ tree reductions = null_pointer_node, mem = null_pointer_node;
+ tree memv = NULL_TREE, condtemp = NULL_TREE;
+ gimple_stmt_iterator gsi = gsi_none ();
+ gimple *g = NULL;
+ if (reductmp)
+ {
+ reductions = OMP_CLAUSE_DECL (reductmp);
+ gcc_assert (TREE_CODE (reductions) == SSA_NAME);
+ g = SSA_NAME_DEF_STMT (reductions);
+ reductions = gimple_assign_rhs1 (g);
+ OMP_CLAUSE_DECL (reductmp) = reductions;
+ gsi = gsi_for_stmt (g);
+ }
+ else
+ gsi = si;
+ if (condtmp)
+ {
+ condtemp = OMP_CLAUSE_DECL (condtmp);
+ tree c = omp_find_clause (OMP_CLAUSE_CHAIN (condtmp),
+ OMP_CLAUSE__CONDTEMP_);
+ cond_var = OMP_CLAUSE_DECL (c);
+ tree type = TREE_TYPE (condtemp);
+ memv = create_tmp_var (type);
+ TREE_ADDRESSABLE (memv) = 1;
+ unsigned cnt = 0;
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ ++cnt;
+ unsigned HOST_WIDE_INT sz
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))) * cnt;
+ expand_omp_build_assign (&gsi, memv, build_int_cst (type, sz),
+ false);
+ mem = build_fold_addr_expr (memv);
+ }
t = build_int_cst (unsigned_type_node, len - 1);
u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS2_START);
- stmt = gimple_build_call (u, 3, t, reductions, null_pointer_node);
+ stmt = gimple_build_call (u, 3, t, reductions, mem);
gimple_call_set_lhs (stmt, vin);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- gsi_remove (&gsi, true);
- release_ssa_name (gimple_assign_lhs (g));
+ if (condtmp)
+ {
+ expand_omp_build_assign (&gsi, condtemp, memv, false);
+ tree t = build2 (PLUS_EXPR, TREE_TYPE (cond_var),
+ vin, build_one_cst (TREE_TYPE (cond_var)));
+ expand_omp_build_assign (&gsi, cond_var, t, false);
+ }
+ if (reductmp)
+ {
+ gsi_remove (&gsi, true);
+ release_ssa_name (gimple_assign_lhs (g));
+ }
}
else if (!is_combined_parallel (region))
{
u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
stmt = gimple_build_call (u, 0);
}
- if (!reductmp)
+ if (!reductmp && !condtmp)
{
gimple_call_set_lhs (stmt, vin);
gsi_insert_after (&si, stmt, GSI_SAME_STMT);
bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
stmt = gimple_build_call (bfn_decl, 0);
gimple_call_set_lhs (stmt, vnext);
- gsi_insert_after (&si, stmt, GSI_SAME_STMT);
+ gsi_insert_before (&si, stmt, GSI_SAME_STMT);
+ if (cond_var)
+ {
+ tree t = build2 (PLUS_EXPR, TREE_TYPE (cond_var),
+ vnext, build_one_cst (TREE_TYPE (cond_var)));
+ expand_omp_build_assign (&si, cond_var, t, false);
+ }
gsi_remove (&si, true);
single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
static void
lower_lastprivate_conditional_clauses (tree *clauses, omp_context *ctx)
{
- struct omp_for_data fd;
tree iter_type = NULL_TREE;
tree cond_ptr = NULL_TREE;
tree iter_var = NULL_TREE;
{
if (iter_type == NULL)
{
- omp_extract_for_data (as_a <gomp_for *> (ctx->stmt), &fd, NULL);
- iter_type = unsigned_type_for (fd.iter_type);
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
+ {
+ struct omp_for_data fd;
+ omp_extract_for_data (as_a <gomp_for *> (ctx->stmt), &fd,
+ NULL);
+ iter_type = unsigned_type_for (fd.iter_type);
+ }
+ else if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
+ iter_type = unsigned_type_node;
cond_ptr = create_tmp_var_raw (build_pointer_type (iter_type));
DECL_CONTEXT (cond_ptr) = current_function_decl;
DECL_SEEN_IN_BIND_EXPR_P (cond_ptr) = 1;
gomp_sections *stmt;
gimple *t;
gbind *new_stmt, *bind;
- gimple_seq ilist, dlist, olist, tred_dlist = NULL, new_body;
+ gimple_seq ilist, dlist, olist, tred_dlist = NULL, clist = NULL, new_body;
stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
&ilist, &dlist, ctx, NULL);
+ control = create_tmp_var (unsigned_type_node, ".section");
+ gimple_omp_sections_set_control (stmt, control);
+
+ tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
+ lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
+
new_body = gimple_omp_body (stmt);
gimple_omp_set_body (stmt, NULL);
tgsi = gsi_start (new_body);
{
gimple_seq l = NULL;
lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
- NULL, &l, NULL, ctx);
+ &ilist, &l, &clist, ctx);
gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
gimple_omp_section_set_last (sec_start);
}
olist = NULL;
lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist,
- NULL, ctx);
+ &clist, ctx);
+ if (clist)
+ {
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ gcall *g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&olist, g);
+ gimple_seq_add_seq (&olist, clist);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&olist, g);
+ }
block = make_node (BLOCK);
new_stmt = gimple_build_bind (NULL, NULL, block);
gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
gimple_seq_add_stmt (&new_body, bind);
- control = create_tmp_var (unsigned_type_node, ".section");
t = gimple_build_omp_continue (control, control);
- gimple_omp_sections_set_control (stmt, control);
gimple_seq_add_stmt (&new_body, t);
gimple_seq_add_seq (&new_body, olist);
if (DECL_P (lhs))
if (tree *v = up->lastprivate_conditional_map->get (lhs))
{
- tree clauses
- = gimple_omp_for_clauses (as_a <gomp_for *> (up->stmt));
+ tree clauses;
+ if (gimple_code (up->stmt) == GIMPLE_OMP_FOR)
+ clauses = gimple_omp_for_clauses (up->stmt);
+ else
+ clauses = gimple_omp_sections_clauses (up->stmt);
tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
OMP_CLAUSE__CONDTEMP_);
2019-05-27 Jakub Jelinek <jakub@redhat.com>
+ * testsuite/libgomp.c-c++-common/lastprivate_conditional_4.c: New test.
+
* testsuite/libgomp.c-c++-common/lastprivate-conditional-3.c: New test.
PR libgomp/90641
--- /dev/null
+#include <stdlib.h>
+
+int x;
+long long y;
+int r, s, t;
+
+void
+foo (const char *a)
+{
+ #pragma omp sections lastprivate (conditional: x, y)
+ {
+ if (a[0])
+ x = a[0];
+ #pragma omp section
+ {
+ if (a[1])
+ x = a[1];
+ if (a[2])
+ y = a[2];
+ }
+ #pragma omp section
+ if (a[3])
+ y = a[3];
+ #pragma omp section
+ if (a[4])
+ x = a[4];
+ #pragma omp section
+ {
+ if (a[5])
+ x = a[5];
+ if (a[6])
+ y = a[6];
+ }
+ }
+}
+
+void
+bar (const char *a)
+{
+ #pragma omp sections lastprivate (conditional: x, y) reduction (task, +: t)
+ {
+ if (a[0])
+ x = a[0];
+ #pragma omp section
+ {
+ if (a[1])
+ x = a[1];
+ if (a[2])
+ y = a[2];
+ #pragma omp task in_reduction (+: t)
+ t++;
+ }
+ #pragma omp section
+ if (a[3])
+ y = a[3];
+ #pragma omp section
+ if (a[4])
+ x = a[4];
+ #pragma omp section
+ {
+ #pragma omp task in_reduction (+: t)
+ ++t;
+ if (a[5])
+ x = a[5];
+ if (a[6])
+ y = a[6];
+ }
+ }
+}
+
+void
+baz (const char *a)
+{
+ #pragma omp sections lastprivate (conditional: x, y) reduction (+: r, s)
+ {
+ if (a[0])
+ x = a[0];
+ #pragma omp section
+ {
+ if (a[1])
+ x = a[1];
+ ++r;
+ ++s;
+ if (a[2])
+ y = a[2];
+ }
+ #pragma omp section
+ if (a[3])
+ y = a[3];
+ #pragma omp section
+ {
+ ++s;
+ if (a[4])
+ x = a[4];
+ }
+ #pragma omp section
+ {
+ if (a[5])
+ x = a[5];
+ if (a[6])
+ y = a[6];
+ ++s;
+ }
+ }
+}
+
+int
+main ()
+{
+ #pragma omp parallel
+ {
+ foo ("\0\1\2\3\0\5");
+ if (x != 5 || y != 3)
+ abort ();
+ #pragma omp barrier
+ foo ("\6\0\0\0\0\0\7");
+ if (x != 6 || y != 7)
+ abort ();
+ #pragma omp barrier
+ foo ("\7\6\5\4\3\2\1");
+ if (x != 2 || y != 1)
+ abort ();
+ #pragma omp barrier
+ foo ("\0\0\4\3\0\7");
+ if (x != 7 || y != 3)
+ abort ();
+ #pragma omp barrier
+ bar ("\0\1\2\4\0\5");
+ if (x != 5 || y != 4 || t != 2)
+ abort ();
+ #pragma omp barrier
+ bar ("\6\0\0\0\0\0\7");
+ if (x != 6 || y != 7 || t != 4)
+ abort ();
+ #pragma omp barrier
+ bar ("\7\6\5\4\3\2\1");
+ if (x != 2 || y != 1 || t != 6)
+ abort ();
+ #pragma omp barrier
+ bar ("\0\0\4\3\0\7");
+ if (x != 7 || y != 3 || t != 8)
+ abort ();
+ #pragma omp barrier
+ baz ("\0\1\2\4\0\5");
+ if (x != 5 || y != 4 || r != 1 || s != 3)
+ abort ();
+ #pragma omp barrier
+ baz ("\6\0\0\0\0\0\7");
+ if (x != 6 || y != 7 || r != 2 || s != 6)
+ abort ();
+ #pragma omp barrier
+ baz ("\7\6\5\4\3\2\1");
+ if (x != 2 || y != 1 || r != 3 || s != 9)
+ abort ();
+ #pragma omp barrier
+ baz ("\0\0\4\3\0\7");
+ if (x != 7 || y != 3 || r != 4 || s != 12)
+ abort ();
+ }
+ return 0;
+}