static int target_nesting_level;
static struct omp_region *root_omp_region;
static bitmap task_shared_vars;
+static vec<omp_context *> taskreg_contexts;
static void scan_omp (gimple_seq *, omp_context *);
static tree scan_omp_1_op (tree *, int *, void *);
}
ctx = new_omp_context (stmt, outer_ctx);
+ taskreg_contexts.safe_push (ctx);
if (taskreg_nesting_level > 1)
ctx->is_nested = true;
ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
if (TYPE_FIELDS (ctx->record_type) == NULL)
ctx->record_type = ctx->receiver_decl = NULL;
- else
- {
- layout_type (ctx->record_type);
- fixup_child_record_type (ctx);
- }
}
/* Scan an OpenMP task directive. */
omp_context *ctx;
tree name, t;
gimple stmt = gsi_stmt (*gsi);
- location_t loc = gimple_location (stmt);
/* Ignore task directives with empty bodies. */
if (optimize > 0
}
ctx = new_omp_context (stmt, outer_ctx);
+ taskreg_contexts.safe_push (ctx);
if (taskreg_nesting_level > 1)
ctx->is_nested = true;
ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
t = build_int_cst (long_integer_type_node, 1);
gimple_omp_task_set_arg_align (stmt, t);
}
+}
+
+
+/* If any decls have been made addressable during scan_omp,
+ adjust their fields if needed, and layout record types
+ of parallel/task constructs. */
+
+static void
+finish_taskreg_scan (omp_context *ctx)
+{
+ if (ctx->record_type == NULL_TREE)
+ return;
+
+ /* If any task_shared_vars were needed, verify all
+ OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
+ statements if use_pointer_for_field hasn't changed
+ because of that. If it did, update field types now. */
+ if (task_shared_vars)
+ {
+ tree c;
+
+ for (c = gimple_omp_taskreg_clauses (ctx->stmt);
+ c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
+ {
+ tree decl = OMP_CLAUSE_DECL (c);
+
+ /* Global variables don't need to be copied,
+ the receiver side will use them directly. */
+ if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
+ continue;
+ if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
+ || !use_pointer_for_field (decl, ctx))
+ continue;
+ tree field = lookup_field (decl, ctx);
+ if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
+ && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
+ continue;
+ TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
+ TREE_THIS_VOLATILE (field) = 0;
+ DECL_USER_ALIGN (field) = 0;
+ DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
+ if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
+ TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
+ if (ctx->srecord_type)
+ {
+ tree sfield = lookup_sfield (decl, ctx);
+ TREE_TYPE (sfield) = TREE_TYPE (field);
+ TREE_THIS_VOLATILE (sfield) = 0;
+ DECL_USER_ALIGN (sfield) = 0;
+ DECL_ALIGN (sfield) = DECL_ALIGN (field);
+ if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
+ TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
+ }
+ }
+ }
+
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
+ {
+ layout_type (ctx->record_type);
+ fixup_child_record_type (ctx);
+ }
else
{
+ location_t loc = gimple_location (ctx->stmt);
tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
/* Move VLA fields to the end. */
p = &TYPE_FIELDS (ctx->record_type);
fixup_child_record_type (ctx);
if (ctx->srecord_type)
layout_type (ctx->srecord_type);
- t = fold_convert_loc (loc, long_integer_type_node,
- TYPE_SIZE_UNIT (ctx->record_type));
- gimple_omp_task_set_arg_size (stmt, t);
+ tree t = fold_convert_loc (loc, long_integer_type_node,
+ TYPE_SIZE_UNIT (ctx->record_type));
+ gimple_omp_task_set_arg_size (ctx->stmt, t);
t = build_int_cst (long_integer_type_node,
TYPE_ALIGN_UNIT (ctx->record_type));
- gimple_omp_task_set_arg_align (stmt, t);
+ gimple_omp_task_set_arg_align (ctx->stmt, t);
}
}
execute_lower_omp (void)
{
gimple_seq body;
+ int i;
+ omp_context *ctx;
/* This pass always runs, to provide PROP_gimple_lomp.
But there is nothing to do unless -fopenmp is given. */
body = gimple_body (current_function_decl);
scan_omp (&body, NULL);
gcc_assert (taskreg_nesting_level == 0);
+ FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
+ finish_taskreg_scan (ctx);
+ taskreg_contexts.release ();
if (all_contexts->root)
{