return is_parallel_ctx (ctx) || is_task_ctx (ctx) || is_host_teams_ctx (ctx);
}
-/* Return true if EXPR is variable sized. */
+/* Return true if EXPR is variable sized. If IS_REF is true, then
+ EXPR is assumed to be a reference and the object it refers
+ to is checked instead. */
static inline bool
-is_variable_sized (const_tree expr)
+is_variable_sized (const_tree expr, bool is_ref = false)
{
+ if (is_ref)
+ expr = TREE_TYPE (expr);
return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
}
ilist = NULL;
olist = NULL;
+
+ gimple_seq alloc_dlist = NULL;
+ hash_map<tree, tree> alloc_map;
+ hash_map<tree, gimple_seq> alloc_seq_map;
+
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
switch (OMP_CLAUSE_CODE (c))
{
- tree var, x;
+ tree var, x, new_var, allocator, allocate_ptr, size;
+ gimple_seq alloc_seq;
+ bool by_ref;
default:
break;
}
map_cnt++;
var = OMP_CLAUSE_DECL (c);
- if (!omp_privatize_by_reference (var)
- && !is_gimple_reg_type (TREE_TYPE (var)))
+ new_var = lookup_decl (var, ctx);
+ allocator = NULL_TREE;
+ allocate_ptr = NULL_TREE;
+ size = TREE_TYPE (var);
+ by_ref = omp_privatize_by_reference (var);
+ if (by_ref)
+ size = TREE_TYPE (size);
+ size = TYPE_SIZE_UNIT (size);
+ if (is_variable_sized (var, by_ref))
+ size = lookup_decl (size, ctx);
+ alloc_seq = NULL;
+ if (lower_private_allocate (var, new_var, allocator, allocate_ptr,
+ &alloc_seq, ctx, by_ref, size))
+ {
+ alloc_map.put (new_var, allocate_ptr);
+ alloc_seq_map.put (new_var, alloc_seq);
+ }
+ if (!by_ref && !is_gimple_reg_type (TREE_TYPE (var)))
{
- tree new_var = lookup_decl (var, ctx);
if (is_variable_sized (var))
{
tree pvar = DECL_VALUE_EXPR (var);
x = build_fold_indirect_ref (new_pvar);
TREE_THIS_NOTRAP (x) = 1;
}
+ else if (allocate_ptr)
+ x = build_fold_indirect_ref (allocate_ptr);
else
x = build_receiver_ref (var, true, ctx);
SET_DECL_VALUE_EXPR (new_var, x);
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
&& lang_hooks.decls.omp_array_data (var, true))
map_cnt += 2;
+
+ do_dtor:
+ if (allocator)
+ {
+ if (!is_gimple_val (allocator))
+ {
+ tree avar = create_tmp_var (TREE_TYPE (allocator));
+ gimplify_assign (avar, allocator, &alloc_dlist);
+ allocator = avar;
+ }
+ if (!is_gimple_val (allocate_ptr))
+ {
+ tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr));
+ gimplify_assign (apvar, allocate_ptr, &alloc_dlist);
+ allocate_ptr = apvar;
+ }
+ tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
+ gimple *g = gimple_build_call (f, 2, allocate_ptr, allocator);
+ gimple_seq_add_stmt (&alloc_dlist, g);
+ }
break;
case OMP_CLAUSE_PRIVATE:
break;
}
var = OMP_CLAUSE_DECL (c);
- if (is_variable_sized (var))
+ new_var = lookup_decl (var, ctx);
+ allocator = NULL_TREE;
+ allocate_ptr = NULL_TREE;
+ alloc_seq = NULL;
+ size = TREE_TYPE (var);
+ by_ref = omp_privatize_by_reference (var);
+ if (by_ref)
+ size = TREE_TYPE (size);
+ size = TYPE_SIZE_UNIT (size);
+ if (is_variable_sized (var, by_ref))
+ size = lookup_decl (size, ctx);
+ lower_private_allocate (var, new_var, allocator, allocate_ptr,
+ &alloc_seq, ctx, by_ref, size);
+ if (allocate_ptr)
+ {
+ alloc_map.put (new_var, allocate_ptr);
+ alloc_seq_map.put (new_var, alloc_seq);
+ }
+ if (!allocate_ptr && is_variable_sized (var))
{
tree new_var = lookup_decl (var, ctx);
tree pvar = DECL_VALUE_EXPR (var);
SET_DECL_VALUE_EXPR (new_var, x);
DECL_HAS_VALUE_EXPR_P (new_var) = 1;
}
- break;
+ goto do_dtor;
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_USE_DEVICE_ADDR:
if (offloaded || data_region)
{
tree prev = NULL_TREE;
+ bool by_ref;
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
switch (OMP_CLAUSE_CODE (c))
{
- tree var, x;
+ tree var, x, new_var, *allocate_ptr;
default:
break;
case OMP_CLAUSE_FIRSTPRIVATE:
if (is_gimple_omp_oacc (ctx->stmt))
break;
var = OMP_CLAUSE_DECL (c);
- if (omp_privatize_by_reference (var)
- || is_gimple_reg_type (TREE_TYPE (var)))
+ new_var = lookup_decl (var, ctx);
+ allocate_ptr = alloc_map.get (new_var);
+ by_ref = omp_privatize_by_reference (var);
+ if (allocate_ptr)
+ {
+ if (is_variable_sized (var, by_ref))
+ /* Handle this in the next pass when the size is
+ available. */
+ break;
+
+ gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
+ gcc_assert (allocate_seq);
+ gimple_seq_add_seq (&new_body, *allocate_seq);
+
+ if (by_ref)
+ {
+ x = fold_convert (TREE_TYPE (new_var), *allocate_ptr);
+ gimplify_assign (new_var, x, &new_body);
+ new_var = build_fold_indirect_ref (new_var);
+ }
+ else
+ new_var = build_simple_mem_ref (*allocate_ptr);
+ }
+ if (by_ref || is_gimple_reg_type (TREE_TYPE (var)))
{
- tree new_var = lookup_decl (var, ctx);
tree type;
type = TREE_TYPE (var);
- if (omp_privatize_by_reference (var))
+ if (by_ref)
type = TREE_TYPE (type);
if ((INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) <= POINTER_SIZE)
x = fold_convert (type, x);
gimplify_expr (&x, &new_body, NULL, is_gimple_val,
fb_rvalue);
- if (omp_privatize_by_reference (var))
+ if (by_ref && !allocate_ptr)
{
tree v = create_tmp_var_raw (type, get_name (var));
gimple_add_tmp_var (v);
gimple_build_assign (v, x));
x = build_fold_addr_expr (v);
}
- gimple_seq_add_stmt (&new_body,
- gimple_build_assign (new_var, x));
+ gimplify_assign (new_var, x, &new_body);
}
else
{
- bool by_ref = !omp_privatize_by_reference (var);
- x = build_receiver_ref (var, by_ref, ctx);
+ x = build_receiver_ref (var, allocate_ptr || !by_ref, ctx);
gimplify_expr (&x, &new_body, NULL, is_gimple_val,
fb_rvalue);
- gimple_seq_add_stmt (&new_body,
- gimple_build_assign (new_var, x));
+ gimplify_assign (new_var, x, &new_body);
}
}
else if (is_variable_sized (var))
gimple_seq_add_stmt (&new_body,
gimple_build_assign (new_var, x));
}
+ else if (allocate_ptr)
+ {
+ x = build_receiver_ref (var, true, ctx);
+ new_var = unshare_expr (new_var);
+ x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
+ gimplify_and_add (x, &new_body);
+ }
break;
case OMP_CLAUSE_PRIVATE:
if (is_gimple_omp_oacc (ctx->stmt))
break;
var = OMP_CLAUSE_DECL (c);
- if (omp_privatize_by_reference (var))
+ new_var = lookup_decl (var, ctx);
+ allocate_ptr = alloc_map.get (new_var);
+ by_ref = omp_privatize_by_reference (var);
+ if (allocate_ptr)
+ {
+ if (is_variable_sized (var, by_ref))
+ /* Handle this in the next pass when the size is
+ available. */
+ break;
+
+ gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
+ gcc_assert (allocate_seq);
+ gimple_seq_add_seq (&new_body, *allocate_seq);
+
+ if (!by_ref)
+ new_var = build_simple_mem_ref (*allocate_ptr);
+ }
+ if (by_ref)
{
location_t clause_loc = OMP_CLAUSE_LOCATION (c);
- tree new_var = lookup_decl (var, ctx);
- x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
- if (TREE_CONSTANT (x))
+ if (!allocate_ptr)
{
- x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
- get_name (var));
- gimple_add_tmp_var (x);
- TREE_ADDRESSABLE (x) = 1;
- x = build_fold_addr_expr_loc (clause_loc, x);
+ x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
+ if (TREE_CONSTANT (x))
+ {
+ x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
+ get_name (var));
+ gimple_add_tmp_var (x);
+ TREE_ADDRESSABLE (x) = 1;
+ x = build_fold_addr_expr_loc (clause_loc, x);
+ }
+ else
+ break;
+
+ x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
+ gimplify_expr (&x, &new_body, NULL, is_gimple_val,
+ fb_rvalue);
}
else
- break;
+ x = *allocate_ptr;
- x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
- gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
gimple_seq_add_stmt (&new_body,
gimple_build_assign (new_var, x));
}
case OMP_CLAUSE_USE_DEVICE_ADDR:
case OMP_CLAUSE_HAS_DEVICE_ADDR:
case OMP_CLAUSE_IS_DEVICE_PTR:
- tree new_var;
gimple_seq assign_body;
bool is_array_data;
bool do_optional_check;
break;
case OMP_CLAUSE_PRIVATE:
var = OMP_CLAUSE_DECL (c);
- if (is_variable_sized (var))
+ by_ref = omp_privatize_by_reference (var);
+ if (is_variable_sized (var, by_ref))
{
- location_t clause_loc = OMP_CLAUSE_LOCATION (c);
tree new_var = lookup_decl (var, ctx);
- tree pvar = DECL_VALUE_EXPR (var);
- gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
- pvar = TREE_OPERAND (pvar, 0);
+ tree *allocate_ptr = alloc_map.get (new_var);
+ if (allocate_ptr)
+ {
+ gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
+ gcc_assert (allocate_seq);
+ gimple_seq_add_seq (&new_body, *allocate_seq);
+ }
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
+ tree pvar = var;
+ if (!by_ref)
+ {
+ pvar = DECL_VALUE_EXPR (var);
+ gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
+ pvar = TREE_OPERAND (pvar, 0);
+ }
gcc_assert (DECL_P (pvar));
tree new_pvar = lookup_decl (pvar, ctx);
- tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
- tree al = size_int (DECL_ALIGN (var));
- tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
- x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
- x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
+ tree x;
+ if (!allocate_ptr)
+ {
+ tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+ tree al = size_int (DECL_ALIGN (var));
+ x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
+ x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
+ x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
+ }
+ else
+ x = *allocate_ptr;
gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
gimple_seq_add_stmt (&new_body,
gimple_build_assign (new_pvar, x));
}
- else if (omp_privatize_by_reference (var)
- && !is_gimple_omp_oacc (ctx->stmt))
+ else if (by_ref && !is_gimple_omp_oacc (ctx->stmt))
{
location_t clause_loc = OMP_CLAUSE_LOCATION (c);
tree new_var = lookup_decl (var, ctx);
gimple_build_assign (new_var, x));
}
break;
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ var = OMP_CLAUSE_DECL (c);
+ by_ref = omp_privatize_by_reference (var);
+ if (is_variable_sized (var, by_ref))
+ {
+ tree new_var = lookup_decl (var, ctx);
+ tree *allocate_ptr = alloc_map.get (new_var);
+ if (!allocate_ptr)
+ break;
+ gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
+ gcc_assert (allocate_seq);
+ gimple_seq_add_seq (&new_body, *allocate_seq);
+
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
+ tree pvar = var;
+ if (!by_ref)
+ {
+ pvar = DECL_VALUE_EXPR (var);
+ gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
+ pvar = TREE_OPERAND (pvar, 0);
+ }
+ gcc_assert (DECL_P (pvar));
+ tree new_pvar = lookup_decl (pvar, ctx);
+ tree x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar),
+ *allocate_ptr);
+ gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
+ gimple_seq_add_stmt (&new_body,
+ gimple_build_assign (new_pvar, x));
+
+ x = build_receiver_ref (var, true, ctx);
+ new_var = unshare_expr (new_var);
+ if (by_ref)
+ new_var = build_fold_indirect_ref (new_var);
+ x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
+ gimplify_and_add (x, &new_body);
+ }
}
gimple_seq fork_seq = NULL;
gimple_seq_add_seq (&new_body, fork_seq);
gimple_seq_add_seq (&new_body, tgt_body);
gimple_seq_add_seq (&new_body, join_seq);
+ gimple_seq_add_seq (&new_body, alloc_dlist);
if (offloaded)
{