marshalling to implement data sharing and copying clauses.
Contributed by Diego Novillo <dnovillo@redhat.com>
- Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
This file is part of GCC.
#include "tree-iterator.h"
#include "tree-inline.h"
#include "langhooks.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
#include "tree-flow.h"
#include "timevar.h"
#include "flags.h"
#include "cfgloop.h"
-/* Lowering of OpenMP parallel and workshare constructs proceeds in two
+/* Lowering of OpenMP parallel and workshare constructs proceeds in two
phases. The first phase scans the function looking for OMP statements
and then for variables that must be replaced to satisfy data sharing
clauses. The second phase expands code for the constructs, as well as
struct omp_context *outer;
gimple stmt;
- /* Map variables to fields in a structure that allows communication
+ /* Map variables to fields in a structure that allows communication
between sending and receiving threads. */
splay_tree field_map;
tree record_type;
/* Find an OpenMP clause of type KIND within CLAUSES. */
tree
-find_omp_clause (tree clauses, enum tree_code kind)
+find_omp_clause (tree clauses, enum omp_clause_code kind)
{
for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
if (OMP_CLAUSE_CODE (clauses) == kind)
struct omp_for_data_loop *loop;
int i;
struct omp_for_data_loop dummy_loop;
+ location_t loc = gimple_location (for_stmt);
fd->for_stmt = for_stmt;
fd->pre = NULL;
else
loop = &dummy_loop;
-
+
loop->v = gimple_omp_for_index (for_stmt, i);
gcc_assert (SSA_VAR_P (loop->v));
gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
break;
case LE_EXPR:
if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
- loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
+ loop->n2 = fold_build2_loc (loc,
+ POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
loop->n2, size_one_node);
else
- loop->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
+ loop->n2 = fold_build2_loc (loc,
+ PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
build_int_cst (TREE_TYPE (loop->n2), 1));
loop->cond_code = LT_EXPR;
break;
case GE_EXPR:
if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
- loop->n2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
+ loop->n2 = fold_build2_loc (loc,
+ POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
loop->n2, size_int (-1));
else
- loop->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
+ loop->n2 = fold_build2_loc (loc,
+ MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
build_int_cst (TREE_TYPE (loop->n2), 1));
loop->cond_code = GT_EXPR;
break;
break;
case MINUS_EXPR:
loop->step = TREE_OPERAND (t, 1);
- loop->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (loop->step),
+ loop->step = fold_build1_loc (loc,
+ NEGATE_EXPR, TREE_TYPE (loop->step),
loop->step);
break;
default:
tree n;
if (loop->cond_code == LT_EXPR)
- n = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
+ n = fold_build2_loc (loc,
+ PLUS_EXPR, TREE_TYPE (loop->v),
loop->n2, loop->step);
else
n = loop->n1;
if (loop->cond_code == LT_EXPR)
{
n1 = loop->n1;
- n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (loop->v),
+ n2 = fold_build2_loc (loc,
+ PLUS_EXPR, TREE_TYPE (loop->v),
loop->n2, loop->step);
}
else
{
- n1 = fold_build2 (MINUS_EXPR, TREE_TYPE (loop->v),
+ n1 = fold_build2_loc (loc,
+ MINUS_EXPR, TREE_TYPE (loop->v),
loop->n2, loop->step);
n2 = loop->n1;
}
itype
= lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
- t = fold_build2 (PLUS_EXPR, itype,
- fold_convert (itype, loop->step), t);
- t = fold_build2 (PLUS_EXPR, itype, t,
- fold_convert (itype, loop->n2));
- t = fold_build2 (MINUS_EXPR, itype, t,
- fold_convert (itype, loop->n1));
+ t = fold_build2_loc (loc,
+ PLUS_EXPR, itype,
+ fold_convert_loc (loc, itype, loop->step), t);
+ t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
+ fold_convert_loc (loc, itype, loop->n2));
+ t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
+ fold_convert_loc (loc, itype, loop->n1));
if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
- t = fold_build2 (TRUNC_DIV_EXPR, itype,
- fold_build1 (NEGATE_EXPR, itype, t),
- fold_build1 (NEGATE_EXPR, itype,
- fold_convert (itype,
- loop->step)));
+ t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
+ fold_build1_loc (loc, NEGATE_EXPR, itype, t),
+ fold_build1_loc (loc, NEGATE_EXPR, itype,
+ fold_convert_loc (loc, itype,
+ loop->step)));
else
- t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
- fold_convert (itype, loop->step));
- t = fold_convert (long_long_unsigned_type_node, t);
+ t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
+ fold_convert_loc (loc, itype, loop->step));
+ t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
if (count != NULL_TREE)
- count = fold_build2 (MULT_EXPR, long_long_unsigned_type_node,
+ count = fold_build2_loc (loc,
+ MULT_EXPR, long_long_unsigned_type_node,
count, t);
else
count = t;
if (collapse_count && *collapse_count == NULL)
{
if (count)
- *collapse_count = fold_convert (iter_type, count);
+ *collapse_count = fold_convert_loc (loc, iter_type, count);
else
*collapse_count = create_tmp_var (iter_type, ".count");
}
# BLOCK 2 (PAR_ENTRY_BB)
.omp_data_o.i = i;
#pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
-
+
# BLOCK 3 (WS_ENTRY_BB)
.omp_data_i = &.omp_data_o;
D.1667 = .omp_data_i->i;
hack something up here, it is really not worth the aggravation. */
static bool
-workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
+workshare_safe_to_combine_p (basic_block ws_entry_bb)
{
struct omp_for_data fd;
- gimple par_stmt, ws_stmt;
-
- par_stmt = last_stmt (par_entry_bb);
- ws_stmt = last_stmt (ws_entry_bb);
+ gimple ws_stmt = last_stmt (ws_entry_bb);
if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
return true;
parallel+workshare call. WS_STMT is the workshare directive being
expanded. */
-static tree
+static VEC(tree,gc) *
get_ws_args_for (gimple ws_stmt)
{
tree t;
+ location_t loc = gimple_location (ws_stmt);
+ VEC(tree,gc) *ws_args;
if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
{
struct omp_for_data fd;
- tree ws_args;
extract_omp_for_data (ws_stmt, &fd, NULL);
- ws_args = NULL_TREE;
- if (fd.chunk_size)
- {
- t = fold_convert (long_integer_type_node, fd.chunk_size);
- ws_args = tree_cons (NULL, t, ws_args);
- }
+ ws_args = VEC_alloc (tree, gc, 3 + (fd.chunk_size != 0));
- t = fold_convert (long_integer_type_node, fd.loop.step);
- ws_args = tree_cons (NULL, t, ws_args);
+ t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
+ VEC_quick_push (tree, ws_args, t);
- t = fold_convert (long_integer_type_node, fd.loop.n2);
- ws_args = tree_cons (NULL, t, ws_args);
+ t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
+ VEC_quick_push (tree, ws_args, t);
- t = fold_convert (long_integer_type_node, fd.loop.n1);
- ws_args = tree_cons (NULL, t, ws_args);
+ t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
+ VEC_quick_push (tree, ws_args, t);
+
+ if (fd.chunk_size)
+ {
+ t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
+ VEC_quick_push (tree, ws_args, t);
+ }
return ws_args;
}
the exit of the sections region. */
basic_block bb = single_succ (gimple_bb (ws_stmt));
t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
- t = tree_cons (NULL, t, NULL);
- return t;
+ ws_args = VEC_alloc (tree, gc, 1);
+ VEC_quick_push (tree, ws_args, t);
+ return ws_args;
}
gcc_unreachable ();
if (single_succ (par_entry_bb) == ws_entry_bb
&& single_succ (ws_exit_bb) == par_exit_bb
- && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
+ && workshare_safe_to_combine_p (ws_entry_bb)
&& (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
|| (last_and_only_stmt (ws_entry_bb)
&& last_and_only_stmt (par_exit_bb))))
omp_context *up;
for (up = shared_ctx->outer; up; up = up->outer)
- if (maybe_lookup_decl (decl, up))
+ if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
break;
- if (up && is_taskreg_ctx (up))
+ if (up)
{
tree c;
tree
copy_var_decl (tree var, tree name, tree type)
{
- tree copy = build_decl (VAR_DECL, name, type);
+ tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
- DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
DECL_CONTEXT (copy) = DECL_CONTEXT (var);
- DECL_SOURCE_LOCATION (copy) = DECL_SOURCE_LOCATION (var);
TREE_USED (copy) = 1;
DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
tree copy = copy_var_decl (var, name, type);
DECL_CONTEXT (copy) = current_function_decl;
- TREE_CHAIN (copy) = ctx->block_vars;
+ DECL_CHAIN (copy) = ctx->block_vars;
ctx->block_vars = copy;
return copy;
if (x != NULL)
field = x;
- x = build_fold_indirect_ref (ctx->receiver_decl);
+ x = build_simple_mem_ref (ctx->receiver_decl);
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
if (by_ref)
- x = build_fold_indirect_ref (x);
+ x = build_simple_mem_ref (x);
return x;
}
{
x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
x = build_outer_var_ref (x, ctx);
- x = build_fold_indirect_ref (x);
+ x = build_simple_mem_ref (x);
}
else if (is_taskreg_ctx (ctx))
{
gcc_unreachable ();
if (is_reference (var))
- x = build_fold_indirect_ref (x);
+ x = build_simple_mem_ref (x);
return x;
}
else if ((mask & 3) == 1 && is_reference (var))
type = TREE_TYPE (type);
- field = build_decl (FIELD_DECL, DECL_NAME (var), type);
+ field = build_decl (DECL_SOURCE_LOCATION (var),
+ FIELD_DECL, DECL_NAME (var), type);
/* Remember what variable this field was created for. This does have a
side effect of making dwarf2out ignore this member, so for helpful
insert_field_into_struct (ctx->record_type, field);
if (ctx->srecord_type)
{
- sfield = build_decl (FIELD_DECL, DECL_NAME (var), type);
+ sfield = build_decl (DECL_SOURCE_LOCATION (var),
+ FIELD_DECL, DECL_NAME (var), type);
DECL_ABSTRACT_ORIGIN (sfield) = var;
DECL_ALIGN (sfield) = DECL_ALIGN (field);
DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
{
- sfield = build_decl (FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
+ sfield = build_decl (DECL_SOURCE_LOCATION (var),
+ FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
insert_field_into_struct (ctx->srecord_type, sfield);
splay_tree_insert (ctx->sfield_map,
if (TREE_CODE (var) == LABEL_DECL)
{
- new_var = create_artificial_label ();
+ new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
DECL_CONTEXT (new_var) = current_function_decl;
insert_decl_map (&ctx->cb, var, new_var);
return new_var;
fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
region->cont->index);
}
-
+
if (region->exit)
fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
region->exit->index);
dump_omp_region (file, region->next, indent);
}
-void
+DEBUG_FUNCTION void
debug_omp_region (struct omp_region *region)
{
dump_omp_region (stderr, region, 0);
}
-void
+DEBUG_FUNCTION void
debug_all_omp_regions (void)
{
dump_omp_region (stderr, root_omp_region, 0);
ctx->cb.dst_node = ctx->cb.src_node;
ctx->cb.src_cfun = cfun;
ctx->cb.copy_decl = omp_copy_decl;
- ctx->cb.eh_region = -1;
+ ctx->cb.eh_lp_nr = 0;
ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
ctx->depth = 1;
}
if (ctx->record_type)
{
tree t;
- for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
+ for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
DECL_ABSTRACT_ORIGIN (t) = NULL;
}
if (ctx->srecord_type)
{
tree t;
- for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = TREE_CHAIN (t))
+ for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
DECL_ABSTRACT_ORIGIN (t) = NULL;
}
variably_modified_type_p doesn't work the way we expect for
record types. Testing each field for whether it needs remapping
and creating a new record by hand works, however. */
- for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
+ for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
break;
if (f)
type = lang_hooks.types.make_type (RECORD_TYPE);
name = DECL_NAME (TYPE_NAME (ctx->record_type));
- name = build_decl (TYPE_DECL, name, type);
+ name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
+ TYPE_DECL, name, type);
TYPE_NAME (type) = name;
- for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
+ for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
{
tree new_f = copy_node (f);
DECL_CONTEXT (new_f) = type;
TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
- TREE_CHAIN (new_f) = new_fields;
+ DECL_CHAIN (new_f) = new_fields;
walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
&ctx->cb, NULL);
break;
case OMP_CLAUSE_COPYPRIVATE:
- if (ctx->outer)
- scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
- /* FALLTHRU */
-
case OMP_CLAUSE_COPYIN:
decl = OMP_CLAUSE_DECL (c);
by_ref = use_pointer_for_field (decl, NULL);
static tree
create_omp_child_function_name (bool task_copy)
{
- tree name = DECL_ASSEMBLER_NAME (current_function_decl);
- size_t len = IDENTIFIER_LENGTH (name);
- char *tmp_name, *prefix;
- const char *suffix;
-
- suffix = task_copy ? "_omp_cpyfn" : "_omp_fn";
- prefix = XALLOCAVEC (char, len + strlen (suffix) + 1);
- memcpy (prefix, IDENTIFIER_POINTER (name), len);
- strcpy (prefix + len, suffix);
-#ifndef NO_DOT_IN_LABEL
- prefix[len] = '.';
-#elif !defined NO_DOLLAR_IN_LABEL
- prefix[len] = '$';
-#endif
- ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
- return get_identifier (tmp_name);
+ return (clone_function_name (current_function_decl,
+ task_copy ? "_omp_cpyfn" : "_omp_fn"));
}
/* Build a decl for the omp child function. It'll not contain a body
else
type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
- decl = build_decl (FUNCTION_DECL, name, type);
- decl = lang_hooks.decls.pushdecl (decl);
+ decl = build_decl (gimple_location (ctx->stmt),
+ FUNCTION_DECL, name, type);
if (!task_copy)
ctx->cb.dst_fn = decl;
TREE_STATIC (decl) = 1;
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
+ DECL_NAMELESS (decl) = 1;
DECL_IGNORED_P (decl) = 0;
TREE_PUBLIC (decl) = 0;
DECL_UNINLINABLE (decl) = 1;
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = make_node (BLOCK);
- t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+ t = build_decl (DECL_SOURCE_LOCATION (decl),
+ RESULT_DECL, NULL_TREE, void_type_node);
DECL_ARTIFICIAL (t) = 1;
DECL_IGNORED_P (t) = 1;
+ DECL_CONTEXT (t) = decl;
DECL_RESULT (decl) = t;
- t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
+ t = build_decl (DECL_SOURCE_LOCATION (decl),
+ PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
DECL_ARTIFICIAL (t) = 1;
+ DECL_NAMELESS (t) = 1;
DECL_ARG_TYPE (t) = ptr_type_node;
DECL_CONTEXT (t) = current_function_decl;
TREE_USED (t) = 1;
ctx->receiver_decl = t;
else
{
- t = build_decl (PARM_DECL, get_identifier (".omp_data_o"),
+ t = build_decl (DECL_SOURCE_LOCATION (decl),
+ PARM_DECL, get_identifier (".omp_data_o"),
ptr_type_node);
DECL_ARTIFICIAL (t) = 1;
+ DECL_NAMELESS (t) = 1;
DECL_ARG_TYPE (t) = ptr_type_node;
DECL_CONTEXT (t) = current_function_decl;
TREE_USED (t) = 1;
- TREE_CHAIN (t) = DECL_ARGUMENTS (decl);
+ TREE_ADDRESSABLE (t) = 1;
+ DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
DECL_ARGUMENTS (decl) = t;
}
- /* Allocate memory for the function structure. The call to
+ /* Allocate memory for the function structure. The call to
allocate_struct_function clobbers CFUN, so we need to restore
it afterward. */
push_struct_function (decl);
- DECL_SOURCE_LOCATION (decl) = gimple_location (ctx->stmt);
cfun->function_end_locus = gimple_location (ctx->stmt);
pop_cfun ();
}
ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
name = create_tmp_var_name (".omp_data_s");
- name = build_decl (TYPE_DECL, name, ctx->record_type);
+ name = build_decl (gimple_location (stmt),
+ TYPE_DECL, name, ctx->record_type);
+ DECL_ARTIFICIAL (name) = 1;
+ DECL_NAMELESS (name) = 1;
TYPE_NAME (ctx->record_type) = name;
create_omp_child_function (ctx, false);
gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
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->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
name = create_tmp_var_name (".omp_data_s");
- name = build_decl (TYPE_DECL, name, ctx->record_type);
+ name = build_decl (gimple_location (stmt),
+ TYPE_DECL, name, ctx->record_type);
+ DECL_ARTIFICIAL (name) = 1;
+ DECL_NAMELESS (name) = 1;
TYPE_NAME (ctx->record_type) = name;
create_omp_child_function (ctx, false);
gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
if (ctx->srecord_type)
{
name = create_tmp_var_name (".omp_data_a");
- name = build_decl (TYPE_DECL, name, ctx->srecord_type);
+ name = build_decl (gimple_location (stmt),
+ TYPE_DECL, name, ctx->srecord_type);
+ DECL_ARTIFICIAL (name) = 1;
+ DECL_NAMELESS (name) = 1;
TYPE_NAME (ctx->srecord_type) = name;
create_omp_child_function (ctx, true);
}
q = &TREE_CHAIN (*q);
}
else
- p = &TREE_CHAIN (*p);
+ p = &DECL_CHAIN (*p);
*p = vla_fields;
layout_type (ctx->record_type);
fixup_child_record_type (ctx);
if (ctx->srecord_type)
layout_type (ctx->srecord_type);
- t = fold_convert (long_integer_type_node,
+ t = fold_convert_loc (loc, long_integer_type_node,
TYPE_SIZE_UNIT (ctx->record_type));
gimple_omp_task_set_arg_size (stmt, t);
t = build_int_cst (long_integer_type_node,
ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
name = create_tmp_var_name (".omp_copy_s");
- name = build_decl (TYPE_DECL, name, ctx->record_type);
+ name = build_decl (gimple_location (stmt),
+ TYPE_DECL, name, ctx->record_type);
TYPE_NAME (ctx->record_type) = name;
scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
if (ctx && TYPE_P (t))
*tp = remap_type (t, &ctx->cb);
else if (!DECL_P (t))
- *walk_subtrees = 1;
+ {
+ *walk_subtrees = 1;
+ if (ctx)
+ {
+ tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
+ if (tem != TREE_TYPE (t))
+ {
+ if (TREE_CODE (t) == INTEGER_CST)
+ *tp = build_int_cst_wide (tem,
+ TREE_INT_CST_LOW (t),
+ TREE_INT_CST_HIGH (t));
+ else
+ TREE_TYPE (t) = tem;
+ }
+ }
+ }
break;
}
*handled_ops_p = false;
if (ctx)
- for (var = gimple_bind_vars (stmt); var ; var = TREE_CHAIN (var))
+ for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
insert_decl_map (&ctx->cb, var, var);
}
break;
tree
omp_reduction_init (tree clause, tree type)
{
+ location_t loc = OMP_CLAUSE_LOCATION (clause);
switch (OMP_CLAUSE_REDUCTION_CODE (clause))
{
case PLUS_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_XOR_EXPR:
case NE_EXPR:
- return fold_convert (type, integer_zero_node);
+ return fold_convert_loc (loc, type, integer_zero_node);
case MULT_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_ANDIF_EXPR:
case EQ_EXPR:
- return fold_convert (type, integer_one_node);
+ return fold_convert_loc (loc, type, integer_one_node);
case BIT_AND_EXPR:
- return fold_convert (type, integer_minus_one_node);
+ return fold_convert_loc (loc, type, integer_minus_one_node);
case MAX_EXPR:
if (SCALAR_FLOAT_TYPE_P (type))
/* Do all the fixed sized types in the first pass, and the variable sized
types in the second pass. This makes sure that the scalar arguments to
- the variable sized types are processed before we use them in the
+ the variable sized types are processed before we use them in the
variable sized operations. */
for (pass = 0; pass < 2; ++pass)
{
enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
tree var, new_var;
bool by_ref;
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
switch (c_kind)
{
gimple_seq_add_stmt (ilist, stmt);
- x = fold_convert (TREE_TYPE (ptr), tmp);
+ x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
gimplify_assign (ptr, x, ilist);
}
}
if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
{
x = build_receiver_ref (var, false, ctx);
- x = build_fold_addr_expr (x);
+ x = build_fold_addr_expr_loc (clause_loc, x);
}
else if (TREE_CONSTANT (x))
{
x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
name);
gimple_add_tmp_var (x);
- x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
+ TREE_ADDRESSABLE (x) = 1;
+ x = build_fold_addr_expr_loc (clause_loc, x);
}
else
{
- x = build_call_expr (built_in_decls[BUILT_IN_ALLOCA], 1, x);
- x = fold_convert (TREE_TYPE (new_var), x);
+ x = build_call_expr_loc (clause_loc,
+ built_in_decls[BUILT_IN_ALLOCA], 1, x);
}
+ x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
gimplify_assign (new_var, x, ilist);
- new_var = build_fold_indirect_ref (new_var);
+ new_var = build_simple_mem_ref_loc (clause_loc, new_var);
}
else if (c_kind == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
/* ??? If VAR is not passed by reference, and the variable
hasn't been initialized yet, then we'll get a warning for
the store into the omp_data_s structure. Ideally, we'd be
- able to notice this and not store anything at all, but
+ able to notice this and not store anything at all, but
we're generating code too early. Suppress the warning. */
if (!by_ref)
TREE_NO_WARNING (var) = 1;
x = build_outer_var_ref (var, ctx);
if (is_reference (var))
- x = build_fold_addr_expr (x);
+ x = build_fold_addr_expr_loc (clause_loc, x);
SET_DECL_VALUE_EXPR (placeholder, x);
DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
gimple stmt;
tree label_true, arm1, arm2;
- label = create_artificial_label ();
- label_true = create_artificial_label ();
+ label = create_artificial_label (UNKNOWN_LOCATION);
+ label_true = create_artificial_label (UNKNOWN_LOCATION);
arm1 = TREE_OPERAND (predicate, 0);
arm2 = TREE_OPERAND (predicate, 1);
gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
for (c = clauses; c ;)
{
tree var, new_var;
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
{
x = build_outer_var_ref (var, ctx);
if (is_reference (var))
- new_var = build_fold_indirect_ref (new_var);
+ new_var = build_simple_mem_ref_loc (clause_loc, new_var);
x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
gimplify_and_add (x, stmt_list);
}
{
tree var, ref, new_var;
enum tree_code code;
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
continue;
var = OMP_CLAUSE_DECL (c);
new_var = lookup_decl (var, ctx);
if (is_reference (var))
- new_var = build_fold_indirect_ref (new_var);
+ new_var = build_simple_mem_ref_loc (clause_loc, new_var);
ref = build_outer_var_ref (var, ctx);
code = OMP_CLAUSE_REDUCTION_CODE (c);
if (count == 1)
{
- tree addr = build_fold_addr_expr (ref);
+ tree addr = build_fold_addr_expr_loc (clause_loc, ref);
addr = save_expr (addr);
ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
- x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
+ x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
x = build2 (OMP_ATOMIC, void_type_node, addr, x);
gimplify_and_add (x, stmt_seqp);
return;
tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
if (is_reference (var))
- ref = build_fold_addr_expr (ref);
+ ref = build_fold_addr_expr_loc (clause_loc, ref);
SET_DECL_VALUE_EXPR (placeholder, ref);
DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
{
- tree var, ref, x;
+ tree var, new_var, ref, x;
bool by_ref;
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
continue;
by_ref = use_pointer_for_field (var, NULL);
ref = build_sender_ref (var, ctx);
- x = lookup_decl_in_outer_ctx (var, ctx);
- x = by_ref ? build_fold_addr_expr (x) : x;
+ x = new_var = lookup_decl_in_outer_ctx (var, ctx);
+ if (by_ref)
+ {
+ x = build_fold_addr_expr_loc (clause_loc, new_var);
+ x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
+ }
gimplify_assign (ref, x, slist);
- ref = build_receiver_ref (var, by_ref, ctx);
+ ref = build_receiver_ref (var, false, ctx);
+ if (by_ref)
+ {
+ ref = fold_convert_loc (clause_loc,
+ build_pointer_type (TREE_TYPE (new_var)),
+ ref);
+ ref = build_fold_indirect_ref_loc (clause_loc, ref);
+ }
if (is_reference (var))
{
- ref = build_fold_indirect_ref (ref);
- var = build_fold_indirect_ref (var);
+ ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
+ ref = build_simple_mem_ref_loc (clause_loc, ref);
+ new_var = build_simple_mem_ref_loc (clause_loc, new_var);
}
- x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
+ x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
gimplify_and_add (x, rlist);
}
}
{
tree val, ref, x, var;
bool by_ref, do_in = false, do_out = false;
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
switch (OMP_CLAUSE_CODE (c))
{
if (do_in)
{
ref = build_sender_ref (val, ctx);
- x = by_ref ? build_fold_addr_expr (var) : var;
+ x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
gimplify_assign (ref, x, ilist);
if (is_task_ctx (ctx))
DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
return;
record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
- for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
+ for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
{
ovar = DECL_ABSTRACT_ORIGIN (f);
nvar = maybe_lookup_decl (ovar, ctx);
x = build_sender_ref (ovar, ctx);
gimplify_assign (x, var, ilist);
- if (!TREE_READONLY (var))
+ if (!TREE_READONLY (var)
+ /* We don't need to receive a new reference to a result
+ or parm decl. In fact we may not store to it as we will
+ invalidate any pending RSO and generate wrong gimple
+ during inlining. */
+ && !((TREE_CODE (var) == RESULT_DECL
+ || TREE_CODE (var) == PARM_DECL)
+ && DECL_BY_REFERENCE (var)))
{
x = build_sender_ref (ovar, ctx);
gimplify_assign (var, x, olist);
}
-/* Build the function calls to GOMP_parallel_start etc to actually
+/* Build the function calls to GOMP_parallel_start etc to actually
generate the parallel operation. REGION is the parallel region
being expanded. BB is the block where to insert the code. WS_ARGS
will be set if this is a call to a combined parallel+workshare
static void
expand_parallel_call (struct omp_region *region, basic_block bb,
- gimple entry_stmt, tree ws_args)
+ gimple entry_stmt, VEC(tree,gc) *ws_args)
{
tree t, t1, t2, val, cond, c, clauses;
gimple_stmt_iterator gsi;
gimple stmt;
int start_ix;
+ location_t clause_loc;
+ VEC(tree,gc) *args;
clauses = gimple_omp_parallel_clauses (entry_stmt);
c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
if (c)
- val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
+ {
+ val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
+ clause_loc = OMP_CLAUSE_LOCATION (c);
+ }
+ else
+ clause_loc = gimple_location (entry_stmt);
/* Ensure 'val' is of the correct type. */
- val = fold_convert (unsigned_type_node, val);
+ val = fold_convert_loc (clause_loc, unsigned_type_node, val);
/* If we found the clause 'if (cond)', build either
(cond != 0) or (cond ? val : 1u). */
cond = gimple_boolify (cond);
if (integer_zerop (val))
- val = fold_build2 (EQ_EXPR, unsigned_type_node, cond,
+ val = fold_build2_loc (clause_loc,
+ EQ_EXPR, unsigned_type_node, cond,
build_int_cst (TREE_TYPE (cond), 0));
else
{
{
gimple phi = create_phi_node (tmp_join, bb);
SSA_NAME_DEF_STMT (tmp_join) = phi;
- add_phi_arg (phi, tmp_then, e_then);
- add_phi_arg (phi, tmp_else, e_else);
+ add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
+ add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
}
val = tmp_join;
t1 = build_fold_addr_expr (t);
t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
- if (ws_args)
- {
- tree args = tree_cons (NULL, t2,
- tree_cons (NULL, t1,
- tree_cons (NULL, val, ws_args)));
- t = build_function_call_expr (built_in_decls[start_ix], args);
- }
- else
- t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
+ args = VEC_alloc (tree, gc, 3 + VEC_length (tree, ws_args));
+ VEC_quick_push (tree, args, t2);
+ VEC_quick_push (tree, args, t1);
+ VEC_quick_push (tree, args, val);
+ VEC_splice (tree, args, ws_args);
+
+ t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
+ built_in_decls[start_ix], args);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
t = null_pointer_node;
else
t = build_fold_addr_expr (t);
- t = build_call_expr (gimple_omp_parallel_child_fn (entry_stmt), 1, t);
+ t = build_call_expr_loc (gimple_location (entry_stmt),
+ gimple_omp_parallel_child_fn (entry_stmt), 1, t);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
- t = build_call_expr (built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
+ t = build_call_expr_loc (gimple_location (entry_stmt),
+ built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
}
{
tree t, t1, t2, t3, flags, cond, c, clauses;
gimple_stmt_iterator gsi;
+ location_t loc = gimple_location (entry_stmt);
clauses = gimple_omp_task_clauses (entry_stmt);
if (t == NULL)
t2 = null_pointer_node;
else
- t2 = build_fold_addr_expr (t);
- t1 = build_fold_addr_expr (gimple_omp_task_child_fn (entry_stmt));
+ t2 = build_fold_addr_expr_loc (loc, t);
+ t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
t = gimple_omp_task_copy_fn (entry_stmt);
if (t == NULL)
t3 = null_pointer_node;
else
- t3 = build_fold_addr_expr (t);
+ t3 = build_fold_addr_expr_loc (loc, t);
t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3,
gimple_omp_task_arg_size (entry_stmt),
static gimple_seq
maybe_catch_exception (gimple_seq body)
{
- gimple f, t;
+ gimple g;
+ tree decl;
if (!flag_exceptions)
return body;
- if (lang_protect_cleanup_actions)
- t = lang_protect_cleanup_actions ();
+ if (lang_hooks.eh_protect_cleanup_actions != NULL)
+ decl = lang_hooks.eh_protect_cleanup_actions ();
else
- t = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
+ decl = built_in_decls[BUILT_IN_TRAP];
- f = gimple_build_eh_filter (NULL, gimple_seq_alloc_with_stmt (t));
- gimple_eh_filter_set_must_not_throw (f, true);
-
- t = gimple_build_try (body, gimple_seq_alloc_with_stmt (f),
+ g = gimple_build_eh_must_not_throw (decl);
+ g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
GIMPLE_TRY_CATCH);
- return gimple_seq_alloc_with_stmt (t);
+ return gimple_seq_alloc_with_stmt (g);
}
/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
static tree
-list2chain (tree list)
+vec2chain (VEC(tree,gc) *v)
{
- tree t;
+ tree chain = NULL_TREE, t;
+ unsigned ix;
- for (t = list; t; t = TREE_CHAIN (t))
+ FOR_EACH_VEC_ELT_REVERSE (tree, v, ix, t)
{
- tree var = TREE_VALUE (t);
- if (TREE_CHAIN (t))
- TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
- else
- TREE_CHAIN (var) = NULL_TREE;
+ DECL_CHAIN (t) = chain;
+ chain = t;
}
- return list ? TREE_VALUE (list) : NULL_TREE;
+ return chain;
}
edge_iterator ei;
edge e;
gimple stmt;
+ int any_addressable_vars = -1;
exit_bb = region->exit;
if (gsi_end_p (gsi))
continue;
stmt = gsi_stmt (gsi);
- if (gimple_code (stmt) == GIMPLE_OMP_RETURN)
- gimple_omp_return_set_nowait (stmt);
+ if (gimple_code (stmt) == GIMPLE_OMP_RETURN
+ && !gimple_omp_return_nowait_p (stmt))
+ {
+ /* OpenMP 3.0 tasks unfortunately prevent this optimization
+ in many cases. If there could be tasks queued, the barrier
+ might be needed to let the tasks run before some local
+ variable of the parallel that the task uses as shared
+ runs out of scope. The task can be spawned either
+ from within current function (this would be easy to check)
+ or from some function it calls and gets passed an address
+ of such a variable. */
+ if (any_addressable_vars < 0)
+ {
+ gimple parallel_stmt = last_stmt (region->entry);
+ tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
+ tree local_decls, block, decl;
+ unsigned ix;
+
+ any_addressable_vars = 0;
+ FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
+ if (TREE_ADDRESSABLE (decl))
+ {
+ any_addressable_vars = 1;
+ break;
+ }
+ for (block = gimple_block (stmt);
+ !any_addressable_vars
+ && block
+ && TREE_CODE (block) == BLOCK;
+ block = BLOCK_SUPERCONTEXT (block))
+ {
+ for (local_decls = BLOCK_VARS (block);
+ local_decls;
+ local_decls = DECL_CHAIN (local_decls))
+ if (TREE_ADDRESSABLE (local_decls))
+ {
+ any_addressable_vars = 1;
+ break;
+ }
+ if (block == gimple_block (parallel_stmt))
+ break;
+ }
+ }
+ if (!any_addressable_vars)
+ gimple_omp_return_set_nowait (stmt);
+ }
}
}
continue;
if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
- || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl)))
- != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
+ || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
+ TREE_TYPE (TREE_TYPE (built_in))))
continue;
gimple_call_set_fndecl (call, built_in);
{
basic_block entry_bb, exit_bb, new_bb;
struct function *child_cfun;
- tree child_fn, block, t, ws_args, *tp;
+ tree child_fn, block, t;
+ tree save_current;
gimple_stmt_iterator gsi;
gimple entry_stmt, stmt;
edge e;
+ VEC(tree,gc) *ws_args;
entry_stmt = last_stmt (region->entry);
child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
if (is_combined_parallel (region))
ws_args = region->ws_args;
else
- ws_args = NULL_TREE;
+ ws_args = NULL;
if (child_cfun->cfg)
{
}
else
{
+ unsigned srcidx, dstidx, num;
+
/* If the parallel region needs data sent from the parent
function, then the very first statement (except possible
tree profile counter updates) of the parallel body
/* Declare local variables needed in CHILD_CFUN. */
block = DECL_INITIAL (child_fn);
- BLOCK_VARS (block) = list2chain (child_cfun->local_decls);
+ BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
+ /* The gimplifier could record temporaries in parallel/task block
+ rather than in containing function's local_decls chain,
+ which would mean cgraph missed finalizing them. Do it now. */
+ for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
+ if (TREE_CODE (t) == VAR_DECL
+ && TREE_STATIC (t)
+ && !DECL_EXTERNAL (t))
+ varpool_finalize_decl (t);
DECL_SAVED_TREE (child_fn) = NULL;
gimple_set_body (child_fn, bb_seq (single_succ (entry_bb)));
TREE_USED (block) = 1;
/* Reset DECL_CONTEXT on function arguments. */
- for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
+ for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = child_fn;
/* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
}
/* Move the parallel region into CHILD_CFUN. */
-
+
if (gimple_in_ssa_p (cfun))
{
push_cfun (child_cfun);
single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
/* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
- for (tp = &child_cfun->local_decls; *tp; )
- if (DECL_CONTEXT (TREE_VALUE (*tp)) != cfun->decl)
- tp = &TREE_CHAIN (*tp);
- else
- *tp = TREE_CHAIN (*tp);
+ num = VEC_length (tree, child_cfun->local_decls);
+ for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
+ {
+ t = VEC_index (tree, child_cfun->local_decls, srcidx);
+ if (DECL_CONTEXT (t) == cfun->decl)
+ continue;
+ if (srcidx != dstidx)
+ VEC_replace (tree, child_cfun->local_decls, dstidx, t);
+ dstidx++;
+ }
+ if (dstidx != num)
+ VEC_truncate (tree, child_cfun->local_decls, dstidx);
/* Inform the callgraph about the new function. */
DECL_STRUCT_FUNCTION (child_fn)->curr_properties
/* Fix the callgraph edges for child_cfun. Those for cfun will be
fixed in a following pass. */
push_cfun (child_cfun);
+ save_current = current_function_decl;
+ current_function_decl = child_fn;
if (optimize)
optimize_omp_library_calls (entry_stmt);
rebuild_cgraph_edges ();
if (flag_exceptions)
{
basic_block bb;
- tree save_current = current_function_decl;
bool changed = false;
- current_function_decl = child_fn;
FOR_EACH_BB (bb)
changed |= gimple_purge_dead_eh_edges (bb);
if (changed)
cleanup_tree_cfg ();
- current_function_decl = save_current;
}
+ if (gimple_in_ssa_p (cfun))
+ update_ssa (TODO_update_ssa);
+ current_function_decl = save_current;
pop_cfun ();
}
-
+
/* Emit a library call to launch the children threads. */
if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
expand_parallel_call (region, new_bb, entry_stmt, ws_args);
t4 = build_fold_addr_expr (iend0);
t3 = build_fold_addr_expr (istart0);
t2 = fold_convert (fd->iter_type, fd->loop.step);
- t1 = fold_convert (fd->iter_type, fd->loop.n2);
- t0 = fold_convert (fd->iter_type, fd->loop.n1);
+ if (POINTER_TYPE_P (type)
+ && TYPE_PRECISION (type) != TYPE_PRECISION (fd->iter_type))
+ {
+ /* Avoid casting pointers to integer of a different size. */
+ tree itype
+ = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0);
+ t1 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n2));
+ t0 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n1));
+ }
+ else
+ {
+ t1 = fold_convert (fd->iter_type, fd->loop.n2);
+ t0 = fold_convert (fd->iter_type, fd->loop.n1);
+ }
if (bias)
{
t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
/* Iteration setup for sequential loop goes in L0_BB. */
gsi = gsi_start_bb (l0_bb);
+ t = istart0;
if (bias)
- t = fold_convert (type, fold_build2 (MINUS_EXPR, fd->iter_type,
- istart0, bias));
- else
- t = fold_convert (type, istart0);
+ t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
+ if (POINTER_TYPE_P (type))
+ t = fold_convert (lang_hooks.types.type_for_size (TYPE_PRECISION (type),
+ 0), t);
+ t = fold_convert (type, t);
t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE,
false, GSI_CONTINUE_LINKING);
stmt = gimple_build_assign (fd->loop.v, t);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+ t = iend0;
if (bias)
- t = fold_convert (type, fold_build2 (MINUS_EXPR, fd->iter_type,
- iend0, bias));
- else
- t = fold_convert (type, iend0);
+ t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
+ if (POINTER_TYPE_P (type))
+ t = fold_convert (lang_hooks.types.type_for_size (TYPE_PRECISION (type),
+ 0), t);
+ t = fold_convert (type, t);
iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
if (fd->collapse > 1)
itype = lang_hooks.types.type_for_size (TYPE_PRECISION (vtype), 0);
t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
t = fold_convert (itype, t);
- t = fold_build2 (MULT_EXPR, itype, t, fd->loops[i].step);
+ t = fold_build2 (MULT_EXPR, itype, t,
+ fold_convert (itype, fd->loops[i].step));
if (POINTER_TYPE_P (vtype))
t = fold_build2 (POINTER_PLUS_EXPR, vtype,
fd->loops[i].n1, fold_convert (sizetype, t));
t = fold_convert (itype, t);
nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
-
+
t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
t = fold_convert (itype, t);
threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
stmt = gimple_build_assign (fd->loop.v, t);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
-
+
t = fold_convert (itype, e0);
t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
if (POINTER_TYPE_P (type))
find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
-
+
set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, body_bb,
recompute_dominator (CDI_DOMINATORS, body_bb));
t = fold_convert (itype, t);
nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
true, GSI_SAME_STMT);
-
+
t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
t = fold_convert (itype, t);
threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e);
gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
-
+
/* Remove GIMPLE_OMP_CONTINUE. */
gsi_remove (&si, true);
gsi_next (&psi), ++i)
{
gimple nphi;
+ source_location locus;
phi = gsi_stmt (psi);
t = gimple_phi_result (phi);
SSA_NAME_DEF_STMT (t) = nphi;
t = PHI_ARG_DEF_FROM_EDGE (phi, se);
+ locus = gimple_phi_arg_location_from_edge (phi, se);
+
/* A special case -- fd->loop.v is not yet computed in
iter_part_bb, we need to use v_extra instead. */
if (t == fd->loop.v)
t = v_extra;
- add_phi_arg (nphi, t, ene);
- add_phi_arg (nphi, redirect_edge_var_map_def (vm), re);
+ add_phi_arg (nphi, t, ene, locus);
+ locus = redirect_edge_var_map_location (vm);
+ add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
}
gcc_assert (!gsi_end_p (psi) && i == VEC_length (edge_var_map, head));
redirect_edge_var_map_clear (re);
/* Make phi node for trip. */
phi = create_phi_node (trip_main, iter_part_bb);
SSA_NAME_DEF_STMT (trip_main) = phi;
- add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
- add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
+ add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
+ UNKNOWN_LOCATION);
+ add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
+ UNKNOWN_LOCATION);
}
set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
next_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
- BUILT_IN_GOMP_LOOP_STATIC_NEXT;
}
- expand_omp_for_generic (region, &fd, start_ix, next_ix);
+ expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
+ (enum built_in_function) next_ix);
}
update_ssa (TODO_update_ssa_only_virtuals);
static void
expand_omp_sections (struct omp_region *region)
{
- tree t, u, vin = NULL, vmain, vnext, l1, l2;
+ tree t, u, vin = NULL, vmain, vnext, l2;
VEC (tree,heap) *label_vec;
unsigned len;
basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
l2_bb = region->exit;
if (exit_reachable)
{
- if (single_pred (l2_bb) == l0_bb)
+ if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
l2 = gimple_block_label (l2_bb);
else
{
}
}
default_bb = create_empty_bb (l1_bb->prev_bb);
- l1 = gimple_block_label (l1_bb);
}
else
{
default_bb = create_empty_bb (l0_bb);
- l1 = NULL_TREE;
l2 = gimple_block_label (default_bb);
}
{
enum built_in_function base;
tree decl, itype, call;
- enum insn_code *optab;
+ direct_optab optab;
tree rhs;
basic_block store_bb = single_succ (load_bb);
gimple_stmt_iterator gsi;
gimple stmt;
+ location_t loc;
/* We expect to find the following sequences:
-
+
load_bb:
GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
store_bb:
val = tmp OP something; (or: something OP tmp)
- GIMPLE_OMP_STORE (val)
+ GIMPLE_OMP_STORE (val)
- ???FIXME: Allow a more flexible sequence.
+ ???FIXME: Allow a more flexible sequence.
Perhaps use data flow to pick the statements.
-
+
*/
gsi = gsi_after_labels (store_bb);
stmt = gsi_stmt (gsi);
+ loc = gimple_location (stmt);
if (!is_gimple_assign (stmt))
return false;
gsi_next (&gsi);
decl = built_in_decls[base + index + 1];
itype = TREE_TYPE (TREE_TYPE (decl));
- if (optab[TYPE_MODE (itype)] == CODE_FOR_nothing)
+ if (direct_optab_handler (optab, TYPE_MODE (itype)) == CODE_FOR_nothing)
return false;
gsi = gsi_last_bb (load_bb);
gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
- call = build_call_expr (decl, 2, addr, fold_convert (itype, rhs));
- call = fold_convert (void_type_node, call);
+ call = build_call_expr_loc (loc,
+ decl, 2, addr,
+ fold_convert_loc (loc, itype, rhs));
+ call = fold_convert_loc (loc, void_type_node, call);
force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
gsi_remove (&gsi, true);
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
itype = TREE_TYPE (TREE_TYPE (cmpxchg));
- if (sync_compare_and_swap[TYPE_MODE (itype)] == CODE_FOR_nothing)
+ if (direct_optab_handler (sync_compare_and_swap_optab, TYPE_MODE (itype))
+ == CODE_FOR_nothing)
return false;
/* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
{
tree iaddr_val;
- iaddr = create_tmp_var (build_pointer_type (itype), NULL);
+ iaddr = create_tmp_var (build_pointer_type_for_mode (itype, ptr_mode,
+ true), NULL);
iaddr_val
= force_gimple_operand_gsi (&si,
fold_convert (TREE_TYPE (iaddr), addr),
false, NULL_TREE, true, GSI_SAME_STMT);
stmt = gimple_build_assign (iaddr, iaddr_val);
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
- DECL_NO_TBAA_P (iaddr) = 1;
- DECL_POINTER_ALIAS_SET (iaddr) = 0;
loadedi = create_tmp_var (itype, NULL);
if (gimple_in_ssa_p (cfun))
{
loadedi = loaded_val;
}
- initial = force_gimple_operand_gsi (&si, build_fold_indirect_ref (iaddr),
- true, NULL_TREE, true, GSI_SAME_STMT);
+ initial
+ = force_gimple_operand_gsi (&si,
+ build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
+ iaddr,
+ build_int_cst (TREE_TYPE (iaddr), 0)),
+ true, NULL_TREE, true, GSI_SAME_STMT);
/* Move the value to the LOADEDI temporary. */
if (gimple_in_ssa_p (cfun))
/* Build the compare&swap statement. */
new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
new_storedi = force_gimple_operand_gsi (&si,
- fold_convert (itype, new_storedi),
+ fold_convert (TREE_TYPE (loadedi),
+ new_storedi),
true, NULL_TREE,
true, GSI_SAME_STMT);
old_vali = loadedi;
else
{
- old_vali = create_tmp_var (itype, NULL);
+ old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
if (gimple_in_ssa_p (cfun))
add_referenced_var (old_vali);
stmt = gimple_build_assign (old_vali, loadedi);
}
/* Note that we always perform the comparison as an integer, even for
- floating point. This allows the atomic operation to properly
+ floating point. This allows the atomic operation to properly
succeed even with NaNs and -0.0. */
stmt = gimple_build_cond_empty
(build2 (NE_EXPR, boolean_type_node,
references are within #pragma omp atomic directives. According to
responses received from omp@openmp.org, appears to be within spec.
Which makes sense, since that's how several other compilers handle
- this situation as well.
+ this situation as well.
LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
expanding. STORED_VAL is the operand of the matching
GIMPLE_OMP_ATOMIC_STORE.
- We replace
- GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
+ We replace
+ GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
loaded_val = *addr;
and replace
GIMPLE_OMP_ATOMIC_ATORE (stored_val) with
- *addr = stored_val;
+ *addr = stored_val;
*/
static bool
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
- t = build_function_call_expr (t, 0);
+ t = build_call_expr (t, 0);
force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
- stmt = gimple_build_assign (loaded_val, build_fold_indirect_ref (addr));
+ stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
gsi_remove (&si, true);
si = gsi_last_bb (store_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
- stmt = gimple_build_assign (build_fold_indirect_ref (unshare_expr (addr)),
- stored_val);
+ stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
+ stored_val);
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
- t = build_function_call_expr (t, 0);
+ t = build_call_expr (t, 0);
force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
gsi_remove (&si, true);
return true;
}
-/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
- using expand_omp_atomic_fetch_op. If it failed, we try to
+/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
+ using expand_omp_atomic_fetch_op. If it failed, we try to
call expand_omp_atomic_pipeline, and if it fails too, the
ultimate fallback is wrapping the operation in a mutex
- (expand_omp_atomic_mutex). REGION is the atomic region built
- by build_omp_regions_1(). */
+ (expand_omp_atomic_mutex). REGION is the atomic region built
+ by build_omp_regions_1(). */
static void
expand_omp_atomic (struct omp_region *region)
static bool
gate_expand_omp (void)
{
- return (flag_openmp != 0 && errorcount == 0);
+ return (flag_openmp != 0 && !seen_error ());
}
-struct gimple_opt_pass pass_expand_omp =
+struct gimple_opt_pass pass_expand_omp =
{
{
GIMPLE_PASS,
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
PROP_gimple_any, /* properties_required */
- PROP_gimple_lomp, /* properties_provided */
+ 0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func /* todo_flags_finish */
gimple_seq_add_seq (&body, l);
gimple_omp_section_set_last (sec_start);
}
-
+
gimple_seq_add_stmt (&body, gimple_build_omp_return (false));
}
static void
lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
{
- tree tlabel = create_artificial_label ();
- tree flabel = create_artificial_label ();
+ location_t loc = gimple_location (single_stmt);
+ tree tlabel = create_artificial_label (loc);
+ tree flabel = create_artificial_label (loc);
gimple call, cond;
tree lhs, decl;
gimple_seq_add_stmt (pre_p, call);
cond = gimple_build_cond (EQ_EXPR, lhs,
- fold_convert (TREE_TYPE (lhs), boolean_true_node),
+ fold_convert_loc (loc, TREE_TYPE (lhs),
+ boolean_true_node),
tlabel, flabel);
gimple_seq_add_stmt (pre_p, cond);
gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
{
tree ptr_type, t, l0, l1, l2;
gimple_seq copyin_seq;
+ location_t loc = gimple_location (single_stmt);
ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
ptr_type = build_pointer_type (ctx->record_type);
ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
- l0 = create_artificial_label ();
- l1 = create_artificial_label ();
- l2 = create_artificial_label ();
+ l0 = create_artificial_label (loc);
+ l1 = create_artificial_label (loc);
+ l2 = create_artificial_label (loc);
- t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
- t = fold_convert (ptr_type, t);
+ t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
+ t = fold_convert_loc (loc, ptr_type, t);
gimplify_assign (ctx->receiver_decl, t, pre_p);
t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
©in_seq, ctx);
- t = build_fold_addr_expr (ctx->sender_decl);
- t = build_call_expr (built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 1, t);
+ t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
+ t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END],
+ 1, t);
gimplify_and_add (t, pre_p);
t = build_and_jump (&l2);
bind_body = maybe_catch_exception (bind_body);
- t = gimple_build_omp_return
+ t = gimple_build_omp_return
(!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
OMP_CLAUSE_NOWAIT));
gimple_seq_add_stmt (&bind_body, t);
{
tree block, lab = NULL, x;
gimple stmt = gsi_stmt (*gsi_p), bind;
+ location_t loc = gimple_location (stmt);
gimple_seq tseq;
struct gimplify_ctx gctx;
bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
block);
- x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+ x = build_call_expr_loc (loc, built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
tseq = NULL;
tree block;
tree name, lock, unlock;
gimple stmt = gsi_stmt (*gsi_p), bind;
+ location_t loc = gimple_location (stmt);
gimple_seq tbody;
struct gimplify_ctx gctx;
if (!critical_name_mutexes)
critical_name_mutexes
- = splay_tree_new_ggc (splay_tree_compare_pointers);
+ = splay_tree_new_ggc (splay_tree_compare_pointers,
+ ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
+ ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
if (n == NULL)
decl = (tree) n->value;
lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
- lock = build_call_expr (lock, 1, build_fold_addr_expr (decl));
+ lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
- unlock = build_call_expr (unlock, 1, build_fold_addr_expr (decl));
+ unlock = build_call_expr_loc (loc, unlock, 1,
+ build_fold_addr_expr_loc (loc, decl));
}
else
{
lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
- lock = build_call_expr (lock, 0);
+ lock = build_call_expr_loc (loc, lock, 0);
unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
- unlock = build_call_expr (unlock, 0);
+ unlock = build_call_expr_loc (loc, unlock, 0);
}
push_gimplify_context (&gctx);
tree clauses, cond, vinit;
enum tree_code cond_code;
gimple_seq stmts;
-
+
cond_code = fd->loop.cond_code;
cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
tree *rhs_p, block;
struct omp_for_data fd;
gimple stmt = gsi_stmt (*gsi_p), new_stmt;
- gimple_seq omp_for_body, body, dlist, ilist;
+ gimple_seq omp_for_body, body, dlist;
size_t i;
struct gimplify_ctx gctx;
}
/* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
- ilist = NULL;
dlist = NULL;
body = NULL;
lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
gsi_replace (gsi_p, new_stmt, true);
}
-/* Callback for walk_stmts. Check if the current statement only contains
+/* Callback for walk_stmts. Check if the current statement only contains
GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
static tree
type = lang_hooks.types.make_type (RECORD_TYPE);
name = DECL_NAME (TYPE_NAME (orig_type));
- name = build_decl (TYPE_DECL, name, type);
+ name = build_decl (gimple_location (tcctx->ctx->stmt),
+ TYPE_DECL, name, type);
TYPE_NAME (type) = name;
for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
splay_tree_node n;
struct omp_taskcopy_context tcctx;
struct gimplify_ctx gctx;
+ location_t loc = gimple_location (task_stmt);
child_fn = gimple_omp_task_copy_fn (task_stmt);
child_cfun = DECL_STRUCT_FUNCTION (child_fn);
DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
/* Reset DECL_CONTEXT on function arguments. */
- for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
+ for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = child_fn;
/* Populate the function. */
/* Remap src and dst argument types if needed. */
record_type = ctx->record_type;
srecord_type = ctx->srecord_type;
- for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
+ for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
{
record_needs_remap = true;
break;
}
- for (f = TYPE_FIELDS (srecord_type); f ; f = TREE_CHAIN (f))
+ for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
{
srecord_needs_remap = true;
tcctx.cb.dst_node = tcctx.cb.src_node;
tcctx.cb.src_cfun = ctx->cb.src_cfun;
tcctx.cb.copy_decl = task_copyfn_copy_decl;
- tcctx.cb.eh_region = -1;
+ tcctx.cb.eh_lp_nr = 0;
tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
tcctx.cb.decl_map = pointer_map_create ();
tcctx.ctx = ctx;
arg = DECL_ARGUMENTS (child_fn);
TREE_TYPE (arg) = build_pointer_type (record_type);
- sarg = TREE_CHAIN (arg);
+ sarg = DECL_CHAIN (arg);
TREE_TYPE (sarg) = build_pointer_type (srecord_type);
/* First pass: initialize temporaries used in record_type and srecord_type
n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
sf = (tree) n->value;
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
- src = build_fold_indirect_ref (sarg);
+ src = build_simple_mem_ref_loc (loc, sarg);
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
append_to_statement_list (t, &list);
sf = (tree) n->value;
if (tcctx.cb.decl_map)
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
- src = build_fold_indirect_ref (sarg);
+ src = build_simple_mem_ref_loc (loc, sarg);
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
- dst = build_fold_indirect_ref (arg);
+ dst = build_simple_mem_ref_loc (loc, arg);
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
append_to_statement_list (t, &list);
sf = (tree) n->value;
if (tcctx.cb.decl_map)
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
- src = build_fold_indirect_ref (sarg);
+ src = build_simple_mem_ref_loc (loc, sarg);
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
if (use_pointer_for_field (decl, NULL) || is_reference (decl))
- src = build_fold_indirect_ref (src);
+ src = build_simple_mem_ref_loc (loc, src);
}
else
src = decl;
- dst = build_fold_indirect_ref (arg);
+ dst = build_simple_mem_ref_loc (loc, arg);
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
append_to_statement_list (t, &list);
sf = (tree) n->value;
if (tcctx.cb.decl_map)
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
- src = build_fold_indirect_ref (sarg);
+ src = build_simple_mem_ref_loc (loc, sarg);
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
if (use_pointer_for_field (decl, NULL))
- src = build_fold_indirect_ref (src);
+ src = build_simple_mem_ref_loc (loc, src);
}
else
src = decl;
- dst = build_fold_indirect_ref (arg);
+ dst = build_simple_mem_ref_loc (loc, arg);
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
append_to_statement_list (t, &list);
(splay_tree_key) TREE_OPERAND (ind, 0));
sf = (tree) n->value;
sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
- src = build_fold_indirect_ref (sarg);
+ src = build_simple_mem_ref_loc (loc, sarg);
src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
- src = build_fold_indirect_ref (src);
- dst = build_fold_indirect_ref (arg);
+ src = build_simple_mem_ref_loc (loc, src);
+ dst = build_simple_mem_ref_loc (loc, arg);
dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
append_to_statement_list (t, &list);
(splay_tree_key) TREE_OPERAND (ind, 0));
df = (tree) n->value;
df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
- ptr = build_fold_indirect_ref (arg);
+ ptr = build_simple_mem_ref_loc (loc, arg);
ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
- build_fold_addr_expr (dst));
+ build_fold_addr_expr_loc (loc, dst));
append_to_statement_list (t, &list);
}
gimple par_bind, bind;
gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
struct gimplify_ctx gctx;
+ location_t loc = gimple_location (stmt);
clauses = gimple_omp_taskreg_clauses (stmt);
par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
ctx->sender_decl
= create_tmp_var (ctx->srecord_type ? ctx->srecord_type
: ctx->record_type, ".omp_data_o");
+ DECL_NAMELESS (ctx->sender_decl) = 1;
+ TREE_ADDRESSABLE (ctx->sender_decl) = 1;
gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
}
if (ctx->record_type)
{
- t = build_fold_addr_expr (ctx->sender_decl);
+ t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
/* fixup_child_record_type might have changed receiver_decl's type. */
- t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
+ t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
gimple_seq_add_stmt (&new_body,
gimple_build_assign (ctx->receiver_decl, t));
}
/* If we have issued syntax errors, avoid doing any heavy lifting.
Just replace the OpenMP directives with a NOP to avoid
confusing RTL expansion. */
- if (errorcount && is_gimple_omp (stmt))
+ if (seen_error () && is_gimple_omp (stmt))
{
gsi_replace (gsi_p, gimple_build_nop (), true);
return;
{
gimple_seq body;
+ /* This pass always runs, to provide PROP_gimple_lomp.
+ But there is nothing to do unless -fopenmp is given. */
+ if (flag_openmp == 0)
+ return 0;
+
all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
delete_omp_context);
return 0;
}
-static bool
-gate_lower_omp (void)
-{
- return flag_openmp != 0;
-}
-
-struct gimple_opt_pass pass_lower_omp =
+struct gimple_opt_pass pass_lower_omp =
{
{
GIMPLE_PASS,
"omplower", /* name */
- gate_lower_omp, /* gate */
+ NULL, /* gate */
execute_lower_omp, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
PROP_gimple_any, /* properties_required */
PROP_gimple_lomp, /* properties_provided */
0, /* properties_destroyed */
if (label_ctx == branch_ctx)
return false;
-
+
/*
Previously we kept track of the label's entire context in diagnose_sb_[12]
so we could traverse it and issue a correct "exit" or "enter" error
for issuing exit/enter error messages. If someone really misses the
distinct error message... patches welcome.
*/
-
+
#if 0
/* Try to avoid confusing the user by producing and error message
with correct "exit" or "enter" verbiage. We prefer "exit"
switch (gimple_code (stmt))
{
WALK_SUBSTMTS;
-
+
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SECTIONS:
wi->info = context;
break;
+ case GIMPLE_COND:
+ {
+ tree lab = gimple_cond_true_label (stmt);
+ if (lab)
+ {
+ n = splay_tree_lookup (all_labels,
+ (splay_tree_key) lab);
+ diagnose_sb_0 (gsi_p, context,
+ n ? (gimple) n->value : NULL);
+ }
+ lab = gimple_cond_false_label (stmt);
+ if (lab)
+ {
+ n = splay_tree_lookup (all_labels,
+ (splay_tree_key) lab);
+ diagnose_sb_0 (gsi_p, context,
+ n ? (gimple) n->value : NULL);
+ }
+ }
+ break;
+
case GIMPLE_GOTO:
{
tree lab = gimple_goto_dest (stmt);
return NULL_TREE;
}
-void
-diagnose_omp_structured_block_errors (tree fndecl)
+static unsigned int
+diagnose_omp_structured_block_errors (void)
{
- tree save_current = current_function_decl;
struct walk_stmt_info wi;
- struct function *old_cfun = cfun;
- gimple_seq body = gimple_body (fndecl);
-
- current_function_decl = fndecl;
- set_cfun (DECL_STRUCT_FUNCTION (fndecl));
+ gimple_seq body = gimple_body (current_function_decl);
all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
splay_tree_delete (all_labels);
all_labels = NULL;
- set_cfun (old_cfun);
- current_function_decl = save_current;
+ return 0;
+}
+
+static bool
+gate_diagnose_omp_blocks (void)
+{
+ return flag_openmp != 0;
}
+struct gimple_opt_pass pass_diagnose_omp_blocks =
+{
+ {
+ GIMPLE_PASS,
+ "*diagnose_omp_blocks", /* name */
+ gate_diagnose_omp_blocks, /* gate */
+ diagnose_omp_structured_block_errors, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_NONE, /* tv_id */
+ PROP_gimple_any, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+ }
+};
+
#include "gt-omp-low.h"