@@ -1752,6 +1752,10 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE__GRIDDIM__GROUP(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__GRIDDIM_), 1)
+/* _CONDTEMP_ holding temporary with iteration count. */
+#define OMP_CLAUSE__CONDTEMP__ITER(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__CONDTEMP_)->base.public_flag)
+
/* SSA_NAME accessors. */
/* Whether SSA_NAME NODE is a virtual operand. This simply caches the
@@ -8146,17 +8146,29 @@ gimplify_scan_omp_clauses (tree *list_p,
}
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
@@ -11559,6 +11571,28 @@ gimplify_omp_for (tree *expr_p, gimple_s
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;
@@ -1414,12 +1414,16 @@ scan_sharing_clauses (tree clauses, omp_
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_:
@@ -3840,6 +3844,11 @@ lower_rec_input_clauses (tree clauses, g
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;
}
@@ -4054,7 +4063,8 @@ lower_rec_input_clauses (tree clauses, g
}
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:
@@ -4730,6 +4740,11 @@ lower_rec_input_clauses (tree clauses, g
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:
@@ -4757,15 +4772,52 @@ lower_rec_input_clauses (tree clauses, g
{
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);
@@ -5222,7 +5274,17 @@ lower_rec_input_clauses (tree clauses, g
}
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)
{
@@ -5398,10 +5460,39 @@ lower_lastprivate_conditional_clauses (t
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)
@@ -5440,6 +5531,7 @@ lower_lastprivate_conditional_clauses (t
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;
@@ -5559,9 +5651,12 @@ lower_lastprivate_clauses (tree clauses,
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_);
@@ -5701,6 +5796,7 @@ lower_lastprivate_clauses (tree clauses,
gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
}
+ next:
c = OMP_CLAUSE_CHAIN (c);
if (c == NULL && !par_clauses)
{
@@ -6826,15 +6922,15 @@ lower_omp_sections (gimple_stmt_iterator
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);
@@ -8486,14 +8582,14 @@ lower_omp_for (gimple_stmt_iterator *gsi
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
@@ -10721,8 +10817,10 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p
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);
}
@@ -4908,7 +4908,10 @@ expand_omp_simd (struct omp_region *regi
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)
{
@@ -5038,6 +5041,18 @@ expand_omp_simd (struct omp_region *regi
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);
@@ -5103,6 +5118,19 @@ expand_omp_simd (struct omp_region *regi
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);
@@ -8,7 +8,7 @@ foo (int *p)
for (i = 0; i < 32; i++)
if (p[i])
a = i;
- #pragma omp simd lastprivate (conditional: b) /* { dg-message "not supported yet" } */
+ #pragma omp simd lastprivate (conditional: b)
for (i = 0; i < 32; i++)
if (p[i])
b = i;
@@ -0,0 +1,52 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-final { scan-tree-dump-times "vectorized \[12] loops" 2 "vect" { target vect_condition } } } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+ int x = 5;
+ #pragma omp simd lastprivate (conditional: x)
+ for (int i = 0; i < 128; i++)
+ if (a[i])
+ x = a[i];
+ return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+ int x = 0;
+ #pragma omp simd lastprivate (conditional: x, v)
+ for (int i = 16; i < 128; ++i)
+ {
+ if (a[i])
+ x = a[i];
+ if (b[i])
+ v = b[i] + 10;
+ }
+ return x;
+}
+
+int
+main ()
+{
+ int a[128], b[128], i;
+ check_vect ();
+ for (i = 0; i < 128; i++)
+ {
+ a[i] = ((i % 11) == 2) ? i + 10 : 0;
+ asm volatile ("" : "+g" (i));
+ b[i] = ((i % 13) == 5) ? i * 2 : 0;
+ }
+ if (foo (a) != 133)
+ abort ();
+ if (bar (b, a) != 244)
+ abort ();
+ if (v != 143)
+ abort ();
+ return 0;
+}
@@ -0,0 +1,51 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+ int x = 5;
+ #pragma omp simd lastprivate (conditional: x) safelen (1)
+ for (int i = 0; i < 128; i++)
+ if (a[i])
+ x = a[i];
+ return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+ int x = 0;
+ #pragma omp simd lastprivate (conditional: x, v) if (0)
+ for (int i = 16; i < 128; ++i)
+ {
+ if (a[i])
+ x = a[i];
+ if (b[i])
+ v = b[i] + 10;
+ }
+ return x;
+}
+
+int
+main ()
+{
+ int a[128], b[128], i;
+ check_vect ();
+ for (i = 0; i < 128; i++)
+ {
+ a[i] = ((i % 11) == 2) ? i + 10 : 0;
+ asm volatile ("" : "+g" (i));
+ b[i] = ((i % 13) == 5) ? i * 2 : 0;
+ }
+ if (foo (a) != 133)
+ abort ();
+ if (bar (b, a) != 244)
+ abort ();
+ if (v != 143)
+ abort ();
+ return 0;
+}