location_t location;
enum omp_clause_default_kind default_kind;
bool is_parallel;
+ bool is_combined_parallel;
};
struct gimplify_ctx
/* Create a new omp construct that deals with variable remapping. */
static struct gimplify_omp_ctx *
-new_omp_context (bool is_parallel)
+new_omp_context (bool is_parallel, bool is_combined_parallel)
{
struct gimplify_omp_ctx *c;
c->privatized_types = pointer_set_create ();
c->location = input_location;
c->is_parallel = is_parallel;
+ c->is_combined_parallel = is_combined_parallel;
c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
return c;
walk_tree (&init, force_labels_r, NULL, NULL);
}
- /* This decl isn't mentioned in the enclosing block, so add it to the
- list of temps. FIXME it seems a bit of a kludge to say that
- anonymous artificial vars aren't pushed, but everything else is. */
- if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
+ /* Some front ends do not explicitly declare all anonymous
+ artificial variables. We compensate here by declaring the
+ variables, though it would be better if the front ends would
+ explicitly declare them. */
+ if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
+ && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
gimple_add_tmp_var (decl);
}
default:
/* Other expressions that get here must have boolean values, but
might need to be converted to the appropriate mode. */
- return convert (boolean_type_node, expr);
+ return fold_convert (boolean_type_node, expr);
}
}
i = VEC_index (constructor_elt, elts, 1)->value;
if (r == NULL || i == NULL)
{
- tree zero = convert (TREE_TYPE (type), integer_zero_node);
+ tree zero = fold_convert (TREE_TYPE (type), integer_zero_node);
if (r == NULL)
r = zero;
if (i == NULL)
tree type = TREE_TYPE (*expr_p);
*expr_p = build3 (COND_EXPR, type, *expr_p,
- convert (type, boolean_true_node),
- convert (type, boolean_false_node));
+ fold_convert (type, boolean_true_node),
+ fold_convert (type, boolean_false_node));
return GS_OK;
}
if (n->value & GOVD_SHARED)
{
if (ctx == gimplify_omp_ctxp)
- error ("iteration variable %qs should be private",
+ {
+ error ("iteration variable %qs should be private",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ n->value = GOVD_PRIVATE;
+ return true;
+ }
+ else
+ return false;
+ }
+ else if ((n->value & GOVD_EXPLICIT) != 0
+ && (ctx == gimplify_omp_ctxp
+ || (ctx->is_combined_parallel
+ && gimplify_omp_ctxp->outer_context == ctx)))
+ {
+ if ((n->value & GOVD_FIRSTPRIVATE) != 0)
+ error ("iteration variable %qs should not be firstprivate",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ else if ((n->value & GOVD_REDUCTION) != 0)
+ error ("iteration variable %qs should not be reduction",
IDENTIFIER_POINTER (DECL_NAME (decl)));
- n->value = GOVD_PRIVATE;
}
return true;
}
- if (ctx->outer_context)
- return omp_is_private (ctx->outer_context, decl);
- else if (ctx->is_parallel)
+ if (ctx->is_parallel)
return false;
+ else if (ctx->outer_context)
+ return omp_is_private (ctx->outer_context, decl);
else
return !is_global_var (decl);
}
and previous omp contexts. */
static void
-gimplify_scan_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel)
+gimplify_scan_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel,
+ bool in_combined_parallel)
{
struct gimplify_omp_ctx *ctx, *outer_ctx;
tree c;
- ctx = new_omp_context (in_parallel);
+ ctx = new_omp_context (in_parallel, in_combined_parallel);
outer_ctx = ctx->outer_context;
while ((c = *list_p) != NULL)
remove = true;
break;
}
+ /* Handle NRV results passed by reference. */
+ if (TREE_CODE (decl) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (decl, 0)) == RESULT_DECL
+ && DECL_BY_REFERENCE (TREE_OPERAND (decl, 0)))
+ OMP_CLAUSE_DECL (c) = decl = TREE_OPERAND (decl, 0);
omp_add_variable (ctx, decl, flags);
- if (TREE_CODE (c) == OMP_CLAUSE_REDUCTION
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
{
omp_add_variable (ctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
- GOVD_LOCAL);
+ GOVD_LOCAL | GOVD_SEEN);
gimplify_omp_ctxp = ctx;
push_gimplify_context ();
gimplify_stmt (&OMP_CLAUSE_REDUCTION_INIT (c));
remove = true;
break;
}
+ /* Handle NRV results passed by reference. */
+ if (TREE_CODE (decl) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (decl, 0)) == RESULT_DECL
+ && DECL_BY_REFERENCE (TREE_OPERAND (decl, 0)))
+ OMP_CLAUSE_DECL (c) = decl = TREE_OPERAND (decl, 0);
do_notice:
if (outer_ctx)
omp_notice_variable (outer_ctx, decl, true);
break;
- case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_IF:
+ OMP_CLAUSE_OPERAND (c, 0)
+ = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
+ /* Fall through. */
+
+ case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_NUM_THREADS:
gs = gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
is_gimple_val, fb_rvalue);
{
tree expr = *expr_p;
- gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p, true);
+ gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p, true,
+ OMP_PARALLEL_COMBINED (expr));
push_gimplify_context ();
for_stmt = *expr_p;
- gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, false);
+ gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, false, false);
t = OMP_FOR_INIT (for_stmt);
gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
decl = TREE_OPERAND (t, 0);
gcc_assert (DECL_P (decl));
gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl)));
- gcc_assert (!TYPE_UNSIGNED (TREE_TYPE (decl)));
/* Make sure the iteration variable is private. */
if (omp_is_private (gimplify_omp_ctxp, decl))
{
tree stmt = *expr_p;
- gimplify_scan_omp_clauses (&OMP_CLAUSES (stmt), pre_p, false);
+ gimplify_scan_omp_clauses (&OMP_CLAUSES (stmt), pre_p, false, false);
gimplify_to_stmt_list (&OMP_BODY (stmt));
gimplify_adjust_omp_clauses (&OMP_CLAUSES (stmt));
ret = gimplify_var_or_parm_decl (expr_p);
break;
+ case RESULT_DECL:
+ /* When within an OpenMP context, notice uses of variables. */
+ if (gimplify_omp_ctxp)
+ omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
+ ret = GS_ALL_DONE;
+ break;
+
case SSA_NAME:
/* Allow callbacks into the gimplifier during optimization. */
ret = GS_ALL_DONE;
ret = gimplify_omp_atomic (expr_p, pre_p);
break;
- case OMP_RETURN_EXPR:
+ case OMP_RETURN:
+ case OMP_CONTINUE:
ret = GS_ALL_DONE;
break;
/* Historically, the compiler has treated a bare
reference to a volatile lvalue as forcing a load. */
tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
- /* Normally, we do want to create a temporary for a
+ /* Normally, we do not want to create a temporary for a
TREE_ADDRESSABLE type because such a type should not be
copied by bitwise-assignment. However, we make an
exception here, as all we are doing here is ensuring that
if (referenced_vars)
{
for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
- add_referenced_tmp_var (t);
+ add_referenced_var (t);
}
pop_gimplify_context (NULL);