}
if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
{
- if (code == OMP_FOR
- || code == OMP_SECTIONS
- || region_type == ORT_COMBINED_PARALLEL)
- flags |= GOVD_LASTPRIVATE_CONDITIONAL;
- else
+ splay_tree_node n = NULL;
+ if (code == OMP_SIMD
+ && outer_ctx
+ && outer_ctx->region_type == ORT_WORKSHARE)
+ {
+ n = splay_tree_lookup (outer_ctx->variables,
+ (splay_tree_key) decl);
+ if (n == NULL
+ && outer_ctx->outer_context
+ && (outer_ctx->outer_context->region_type
+ == ORT_COMBINED_PARALLEL))
+ n = splay_tree_lookup (outer_ctx->outer_context->variables,
+ (splay_tree_key) decl);
+ }
+ if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
{
sorry_at (OMP_CLAUSE_LOCATION (c),
"%<conditional%> modifier on %<lastprivate%> "
"clause not supported yet");
OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
}
+ else
+ flags |= GOVD_LASTPRIVATE_CONDITIONAL;
}
if (outer_ctx
&& (outer_ctx->region_type == ORT_COMBINED_PARALLEL
omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
}
}
+ else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
+ {
+ unsigned lastprivate_conditional = 0;
+ for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ ++lastprivate_conditional;
+ if (lastprivate_conditional)
+ {
+ struct omp_for_data fd;
+ omp_extract_for_data (gfor, &fd, NULL);
+ tree type = unsigned_type_for (fd.iter_type);
+ while (lastprivate_conditional--)
+ {
+ tree c = build_omp_clause (UNKNOWN_LOCATION,
+ OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE_DECL (c) = create_tmp_var (type);
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
+ gimple_omp_for_set_clauses (gfor, c);
+ }
+ }
+ }
if (ret != GS_ALL_DONE)
return GS_ERROR;
OMP_CLAUSE_IF);
tree simdlen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE_SIMDLEN);
+ tree condtemp = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__CONDTEMP_);
tree n1, n2;
+ tree cond_var = condtemp ? OMP_CLAUSE_DECL (condtemp) : NULL_TREE;
if (safelen)
{
expand_omp_build_assign (&gsi, fd->loops[i].v, t);
}
}
+ if (cond_var)
+ {
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR
+ || tree_int_cst_sgn (n1) != 1)
+ expand_omp_build_assign (&gsi, cond_var,
+ build_one_cst (TREE_TYPE (cond_var)));
+ else
+ expand_omp_build_assign (&gsi, cond_var,
+ fold_convert (TREE_TYPE (cond_var), n1));
+ }
/* Remove the GIMPLE_OMP_FOR statement. */
gsi_remove (&gsi, true);
expand_omp_build_assign (&gsi, fd->loops[i].v, t);
}
}
+ if (cond_var)
+ {
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR
+ || tree_int_cst_sgn (n1) != 1)
+ t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+ build_one_cst (TREE_TYPE (cond_var)));
+ else
+ t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+ fold_convert (TREE_TYPE (cond_var), step));
+ expand_omp_build_assign (&gsi, cond_var, t);
+ }
/* Remove GIMPLE_OMP_CONTINUE. */
gsi_remove (&gsi, true);
break;
case OMP_CLAUSE__CONDTEMP_:
+ decl = OMP_CLAUSE_DECL (c);
if (is_parallel_ctx (ctx))
{
- decl = OMP_CLAUSE_DECL (c);
install_var_field (decl, false, 3, ctx);
install_var_local (decl, ctx);
}
+ else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+ && (gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
+ && !OMP_CLAUSE__CONDTEMP__ITER (c))
+ install_var_local (decl, ctx);
break;
case OMP_CLAUSE__CACHE_:
if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
sctx.max_vf = 1;
break;
+ case OMP_CLAUSE__CONDTEMP_:
+ /* FIXME: lastprivate(conditional:) not handled for SIMT yet. */
+ if (sctx.is_simt)
+ sctx.max_vf = 1;
+ break;
default:
continue;
}
}
continue;
case OMP_CLAUSE__CONDTEMP_:
- if (is_parallel_ctx (ctx))
+ if (is_parallel_ctx (ctx)
+ || (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c)))
break;
continue;
default:
SET_DECL_VALUE_EXPR (new_var, x);
DECL_HAS_VALUE_EXPR_P (new_var) = 1;
}
+ else if (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c))
+ {
+ x = build_zero_cst (TREE_TYPE (var));
+ goto do_private;
+ }
break;
case OMP_CLAUSE_LASTPRIVATE:
{
tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
if ((TREE_ADDRESSABLE (new_var) || nx || y
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
ivar, lvar))
{
if (nx)
x = lang_hooks.decls.omp_clause_default_ctor
(c, unshare_expr (ivar), x);
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
+ {
+ x = build2 (MODIFY_EXPR, TREE_TYPE (ivar),
+ unshare_expr (ivar), x);
+ nx = x;
+ }
if (nx && x)
gimplify_and_add (x, &llist[0]);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ {
+ tree v
+ = *ctx->lastprivate_conditional_map->get (new_var);
+ tree t = create_tmp_var (TREE_TYPE (v));
+ tree z = build_zero_cst (TREE_TYPE (v));
+ tree orig_v
+ = build_outer_var_ref (var, ctx,
+ OMP_CLAUSE_LASTPRIVATE);
+ gimple_seq_add_stmt (dlist,
+ gimple_build_assign (t, z));
+ gcc_assert (DECL_HAS_VALUE_EXPR_P (v));
+ tree civar = DECL_VALUE_EXPR (v);
+ gcc_assert (TREE_CODE (civar) == ARRAY_REF);
+ civar = unshare_expr (civar);
+ TREE_OPERAND (civar, 1) = sctx.idx;
+ x = build2 (MODIFY_EXPR, TREE_TYPE (t), t,
+ unshare_expr (civar));
+ x = build2 (COMPOUND_EXPR, TREE_TYPE (orig_v), x,
+ build2 (MODIFY_EXPR, TREE_TYPE (orig_v),
+ orig_v, unshare_expr (ivar)));
+ tree cond = build2 (LT_EXPR, boolean_type_node, t,
+ civar);
+ x = build3 (COND_EXPR, void_type_node, cond, x,
+ void_node);
+ gimple_seq tseq = NULL;
+ gimplify_and_add (x, &tseq);
+ gimple_seq_add_seq (&llist[1], tseq);
+ }
if (y)
{
y = lang_hooks.decls.omp_clause_dtor (c, ivar);
}
if (known_eq (sctx.max_vf, 1U))
- sctx.is_simt = false;
+ {
+ sctx.is_simt = false;
+ if (ctx->lastprivate_conditional_map)
+ {
+ /* When not vectorized, treat lastprivate(conditional:) like
+ normal lastprivate, as there will be just one simd lane
+ writing the privatized variable. */
+ delete ctx->lastprivate_conditional_map;
+ ctx->lastprivate_conditional_map = NULL;
+ }
+ }
if (nonconst_simd_if)
{
tree iter_type = NULL_TREE;
tree cond_ptr = NULL_TREE;
tree iter_var = NULL_TREE;
+ bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
+ tree next = *clauses;
for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
&& OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
{
+ if (is_simd)
+ {
+ tree cc = omp_find_clause (next, OMP_CLAUSE__CONDTEMP_);
+ gcc_assert (cc);
+ if (iter_type == NULL_TREE)
+ {
+ iter_type = TREE_TYPE (OMP_CLAUSE_DECL (cc));
+ iter_var = create_tmp_var_raw (iter_type);
+ DECL_CONTEXT (iter_var) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
+ DECL_CHAIN (iter_var) = ctx->block_vars;
+ ctx->block_vars = iter_var;
+ tree c3
+ = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
+ OMP_CLAUSE_DECL (c3) = iter_var;
+ OMP_CLAUSE_CHAIN (c3) = *clauses;
+ *clauses = c3;
+ ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
+ }
+ next = OMP_CLAUSE_CHAIN (cc);
+ tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+ tree v = lookup_decl (OMP_CLAUSE_DECL (cc), ctx);
+ ctx->lastprivate_conditional_map->put (o, v);
+ continue;
+ }
if (iter_type == NULL)
{
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
ctx->block_vars = iter_var;
tree c3
= build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
OMP_CLAUSE_DECL (c3) = iter_var;
OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
OMP_CLAUSE_CHAIN (c2) = c3;
tree lab2 = NULL_TREE;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
- && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
+ && ctx->lastprivate_conditional_map)
{
- gcc_assert (body_p && ctx->lastprivate_conditional_map);
+ gcc_assert (body_p);
+ if (simduid)
+ goto next;
if (cond_ptr == NULL_TREE)
{
cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
}
+ next:
c = OMP_CLAUSE_CHAIN (c);
if (c == NULL && !par_clauses)
{
gimple_seq_add_stmt (&ilist, gimple_build_assign (rtmp, temp));
}
+ tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
+ lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
+
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_add_stmt (&body, gimple_build_assign (rtmp, temp));
}
+ lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
+ ctx);
+
lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
fdp);
gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
gimple_omp_for_pre_body (stmt));
- lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
- ctx);
-
lower_omp (gimple_omp_body_ptr (stmt), ctx);
/* Lower the header expressions. At this point, we can assume that
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_);
+ if (!OMP_CLAUSE__CONDTEMP__ITER (c))
+ c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
+ OMP_CLAUSE__CONDTEMP_);
+ gcc_assert (OMP_CLAUSE__CONDTEMP__ITER (c));
gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
}