[gomp3.1] Add support for parsing final and mergeable task clauses and taskyield directive
Jakub Jelinek
jakub@redhat.com
Thu Apr 28 15:51:00 GMT 2011
Hi!
Both final and mergeable are passed to GOMP_task in flags, but mergeable
is currently ignored, we might want to clone it on the compiler side in
that case. taskyield calls new GOMP_taskyield function, which is currently
empty though.
2011-04-28 Jakub Jelinek <jakub@redhat.com>
* tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_FINAL
and OMP_CLAUSE_MERGEABLE.
* tree.c (omp_clause_num_ops): Add OMP_CLAUSE_FINAL and
OMP_CLAUSE_MERGEABLE.
(omp_clause_code_name): Likewise.
(walk_tree_1): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
* tree.h (enum omp_clause_code): Add OMP_CLAUSE_FINAL
and OMP_CLAUSE_MERGEABLE.
(OMP_CLAUSE_FINAL_EXPR): Define.
* omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_FINAL and
OMP_CLAUSE_MERGEABLE.
(expand_task_call): Likewise.
* c-typeck.c (c_finish_omp_clauses): Likewise.
* gimplify.c (gimplify_scan_omp_clauses,
gimplify_adjust_omp_clauses): Likewise.
* tree-nested.c (convert_nonlocal_omp_clauses,
convert_local_omp_clauses): Likewise.
* omp-builtins.def (BUILT_IN_GOMP_TASKYIELD): New builtin.
* c-parser.c (c_parser_omp_taskyield): New function.
(c_parser_pragma): Handle PRAGMA_OMP_TASKYIELD.
(c_parser_omp_clause_name): Handle final and mergeable clauses.
(c_parser_omp_clause_final, c_parser_omp_clause_mergeable): New
functions.
(c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL
and PRAGMA_OMP_CLAUSE_MERGEABLE.
(OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses.
* doc/generic.texi: Mention OMP_CLAUSE_COLLAPSE,
OMP_CLAUSE_UNTIED, OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE.
* c-omp.c (c_finish_omp_taskyield): New function.
* c-common.h (c_finish_omp_taskyield): New prototype.
* c-pragma.c (omp_pragmas): Add taskyield.
* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_TASKYIELD.
(enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FINAL and
PRAGMA_OMP_CLAUSE_MERGEABLE.
* pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_FINAL and
OMP_CLAUSE_MERGEABLE.
* semantics.c (finish_omp_clauses): Likewise.
(finish_omp_taskyield): New function.
* parser.c (cp_parser_omp_clause_name): Handle final and
mergeable clauses.
(cp_parser_omp_clause_final, cp_parser_omp_clause_mergeable): New
functions.
(cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL
and PRAGMA_OMP_CLAUSE_MERGEABLE.
(OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses.
(cp_parser_omp_taskyield): New function.
(cp_parser_pragma): Handle PRAGMA_OMP_TASKYIELD.
* cp-tree.h (finish_omp_taskyield): New prototype.
* openmp.c (gfc_free_omp_clauses): Free also final_expr.
(OMP_CLAUSE_FINAL, OMP_CLAUSE_MERGEABLE): Define.
(gfc_match_omp_clauses): Handle parsing final and mergeable
clauses.
(OMP_TASK_CLAUSES): Allow final and mergeable clauses.
(gfc_match_omp_taskyield): New function.
(resolve_omp_clauses): Resolve final clause.
* dump-parse-tree.c (show_omp_node): Handle EXEC_OMP_TASKYIELD,
print final and mergeable clauses.
(show_code_node): Handle EXEC_OMP_TASKYIELD.
* trans-openmp.c (gfc_trans_omp_clauses): Handle final and
mergeable clauses.
(gfc_trans_omp_taskyield): New function.
(gfc_trans_omp_directive): Handle EXEC_OMP_TASKYIELD.
* gfortran.h (gfc_statement): Add ST_OMP_TASKYIELD.
(gfc_omp_clauses): Add final_expr and mergeable fields.
(gfc_exec_op): Add EXEC_OMP_TASKYIELD.
* trans.c (trans_code): Handle EXEC_OMP_TASKYIELD.
* frontend-passes.c (gfc_code_walker): Also walk final_expr.
* resolve.c (gfc_resolve_blocks, resolve_code): Handle
EXEC_OMP_TASKYIELD.
* st.c (gfc_free_statement): Likewise.
* match.h (gfc_match_omp_taskyield): New prototype.
* parse.c (decode_omp_directive): Handle taskyield directive.
(case_executable): Add ST_OMP_TASKYIELD case.
(gfc_ascii_statement): Handle ST_OMP_TASKYIELD.
* libgomp_g.h (GOMP_taskyield): New prototype.
* libgomp.map (GOMP_taskyield): Export with GOMP_3.0 symver.
* libgomp.h (struct gomp_task): Add final_task field.
* task.c (gomp_init_task): Initialize final_task.
(GOMP_task): Remove unused attribute from flags. Handle final
tasks.
(GOMP_taskyield): New function.
(omp_in_final): Return true if if (false) or final (true) task
or descendant of final (true).
* testsuite/libgomp.c/task-5.c: New test.
* testsuite/libgomp.c++/task-8.C: New test.
* testsuite/libgomp.fortran/task3.f90: New test.
--- gcc/doc/generic.texi (revision 172776)
+++ gcc/doc/generic.texi (working copy)
@@ -2210,7 +2210,9 @@ Clauses are represented by separate sub-
@code{OMP_CLAUSE_COPYPRIVATE}, @code{OMP_CLAUSE_IF},
@code{OMP_CLAUSE_NUM_THREADS}, @code{OMP_CLAUSE_SCHEDULE},
@code{OMP_CLAUSE_NOWAIT}, @code{OMP_CLAUSE_ORDERED},
-@code{OMP_CLAUSE_DEFAULT}, and @code{OMP_CLAUSE_REDUCTION}. Each code
+@code{OMP_CLAUSE_DEFAULT}, @code{OMP_CLAUSE_REDUCTION},
+@code{OMP_CLAUSE_COLLAPSE}, @code{OMP_CLAUSE_UNTIED},
+@code{OMP_CLAUSE_FINAL}, and @code{OMP_CLAUSE_MERGEABLE}. Each code
represents the corresponding OpenMP clause.
Clauses associated with the same directive are chained together
--- gcc/tree-pretty-print.c (revision 172823)
+++ gcc/tree-pretty-print.c (working copy)
@@ -417,6 +417,17 @@ dump_omp_clause (pretty_printer *buffer,
pp_character (buffer, ')');
break;
+ case OMP_CLAUSE_FINAL:
+ pp_string (buffer, "final(");
+ dump_generic_node (buffer, OMP_CLAUSE_FINAL_EXPR (clause),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ break;
+
+ case OMP_CLAUSE_MERGEABLE:
+ pp_string (buffer, "mergeable");
+ break;
+
default:
/* Should never happen. */
dump_generic_node (buffer, clause, spc, flags, false);
--- gcc/c-family/c-omp.c (revision 172823)
+++ gcc/c-family/c-omp.c (working copy)
@@ -96,6 +96,20 @@ c_finish_omp_taskwait (location_t loc)
}
+/* Complete a #pragma omp taskyield construct. LOC is the location of the
+ pragma. */
+
+void
+c_finish_omp_taskyield (location_t loc)
+{
+ tree x;
+
+ x = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+ x = build_call_expr_loc (loc, x, 0);
+ add_stmt (x);
+}
+
+
/* Complete a #pragma omp atomic construct. For CODE OMP_ATOMIC
the expression to be implemented atomically is LHS opcode= RHS.
For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
--- gcc/c-family/c-common.h (revision 172823)
+++ gcc/c-family/c-common.h (working copy)
@@ -999,6 +999,7 @@ extern tree c_finish_omp_atomic (locatio
tree, tree, tree, tree);
extern void c_finish_omp_flush (location_t);
extern void c_finish_omp_taskwait (location_t);
+extern void c_finish_omp_taskyield (location_t);
extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
extern void c_split_parallel_clauses (location_t, tree, tree *, tree *);
extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
--- gcc/c-family/c-pragma.c (revision 172776)
+++ gcc/c-family/c-pragma.c (working copy)
@@ -1180,6 +1180,7 @@ static const struct omp_pragma_def omp_p
{ "single", PRAGMA_OMP_SINGLE },
{ "task", PRAGMA_OMP_TASK },
{ "taskwait", PRAGMA_OMP_TASKWAIT },
+ { "taskyield", PRAGMA_OMP_TASKYIELD },
{ "threadprivate", PRAGMA_OMP_THREADPRIVATE }
};
--- gcc/c-family/c-pragma.h (revision 172776)
+++ gcc/c-family/c-pragma.h (working copy)
@@ -43,6 +43,7 @@ typedef enum pragma_kind {
PRAGMA_OMP_SINGLE,
PRAGMA_OMP_TASK,
PRAGMA_OMP_TASKWAIT,
+ PRAGMA_OMP_TASKYIELD,
PRAGMA_OMP_THREADPRIVATE,
PRAGMA_GCC_PCH_PREPROCESS,
@@ -70,7 +71,9 @@ typedef enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_REDUCTION,
PRAGMA_OMP_CLAUSE_SCHEDULE,
PRAGMA_OMP_CLAUSE_SHARED,
- PRAGMA_OMP_CLAUSE_UNTIED
+ PRAGMA_OMP_CLAUSE_UNTIED,
+ PRAGMA_OMP_CLAUSE_FINAL,
+ PRAGMA_OMP_CLAUSE_MERGEABLE
} pragma_omp_clause;
extern struct cpp_reader* parse_in;
--- gcc/tree.c (revision 172776)
+++ gcc/tree.c (working copy)
@@ -241,7 +241,9 @@ unsigned const char omp_clause_num_ops[]
0, /* OMP_CLAUSE_ORDERED */
0, /* OMP_CLAUSE_DEFAULT */
3, /* OMP_CLAUSE_COLLAPSE */
- 0 /* OMP_CLAUSE_UNTIED */
+ 0, /* OMP_CLAUSE_UNTIED */
+ 1, /* OMP_CLAUSE_FINAL */
+ 0 /* OMP_CLAUSE_MERGEABLE */
};
const char * const omp_clause_code_name[] =
@@ -261,7 +263,9 @@ const char * const omp_clause_code_name[
"ordered",
"default",
"collapse",
- "untied"
+ "untied",
+ "final",
+ "mergeable"
};
@@ -10377,6 +10381,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
@@ -10387,6 +10392,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_MERGEABLE:
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
case OMP_CLAUSE_LASTPRIVATE:
--- gcc/tree.h (revision 172776)
+++ gcc/tree.h (working copy)
@@ -339,7 +339,13 @@ enum omp_clause_code
OMP_CLAUSE_COLLAPSE,
/* OpenMP clause: untied. */
- OMP_CLAUSE_UNTIED
+ OMP_CLAUSE_UNTIED,
+
+ /* OpenMP clause: final (scalar-expression). */
+ OMP_CLAUSE_FINAL,
+
+ /* OpenMP clause: mergeable. */
+ OMP_CLAUSE_MERGEABLE
};
/* The definition of tree nodes fills the next several pages. */
@@ -1800,6 +1806,8 @@ extern void protected_set_expr_location
#define OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ(NODE) \
(OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
+#define OMP_CLAUSE_FINAL_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FINAL), 0)
#define OMP_CLAUSE_IF_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_IF), 0)
#define OMP_CLAUSE_NUM_THREADS_EXPR(NODE) \
--- gcc/omp-low.c (revision 172823)
+++ gcc/omp-low.c (working copy)
@@ -1444,6 +1444,7 @@ scan_sharing_clauses (tree clauses, omp_
ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
break;
+ case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
@@ -1455,6 +1456,7 @@ scan_sharing_clauses (tree clauses, omp_
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
@@ -1505,6 +1507,8 @@ scan_sharing_clauses (tree clauses, omp_
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_FINAL:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
@@ -3082,7 +3086,7 @@ expand_parallel_call (struct omp_region
static void
expand_task_call (basic_block bb, gimple entry_stmt)
{
- tree t, t1, t2, t3, flags, cond, c, clauses;
+ tree t, t1, t2, t3, flags, cond, c, c2, clauses;
gimple_stmt_iterator gsi;
location_t loc = gimple_location (entry_stmt);
@@ -3095,7 +3099,19 @@ expand_task_call (basic_block bb, gimple
cond = boolean_true_node;
c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
- flags = build_int_cst (unsigned_type_node, (c ? 1 : 0));
+ c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
+ flags = build_int_cst (unsigned_type_node,
+ (c ? 1 : 0) + (c2 ? 4 : 0));
+
+ c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
+ if (c)
+ {
+ c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
+ c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
+ build_int_cst (unsigned_type_node, 2),
+ build_int_cst (unsigned_type_node, 0));
+ flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
+ }
gsi = gsi_last_bb (bb);
t = gimple_omp_task_data_arg (entry_stmt);
--- gcc/cp/pt.c (revision 173013)
+++ gcc/cp/pt.c (working copy)
@@ -11759,6 +11759,7 @@ tsubst_omp_clauses (tree clauses, tree a
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_FINAL:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
@@ -11767,6 +11768,7 @@ tsubst_omp_clauses (tree clauses, tree a
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
gcc_unreachable ();
--- gcc/cp/semantics.c (revision 173013)
+++ gcc/cp/semantics.c (working copy)
@@ -3768,6 +3768,14 @@ finish_omp_clauses (tree clauses)
OMP_CLAUSE_IF_EXPR (c) = t;
break;
+ case OMP_CLAUSE_FINAL:
+ t = OMP_CLAUSE_FINAL_EXPR (c);
+ t = maybe_convert_cond (t);
+ if (t == error_mark_node)
+ remove = true;
+ OMP_CLAUSE_FINAL_EXPR (c) = t;
+ break;
+
case OMP_CLAUSE_NUM_THREADS:
t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
if (t == error_mark_node)
@@ -3799,6 +3807,7 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
@@ -4677,6 +4686,16 @@ finish_omp_taskwait (void)
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
+
+void
+finish_omp_taskyield (void)
+{
+ tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+ VEC(tree,gc) *vec = make_tree_vector ();
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
+ finish_expr_stmt (stmt);
+}
void
init_cp_semantics (void)
--- gcc/cp/parser.c (revision 173035)
+++ gcc/cp/parser.c (working copy)
@@ -23352,13 +23352,19 @@ cp_parser_omp_clause_name (cp_parser *pa
result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
break;
case 'f':
- if (!strcmp ("firstprivate", p))
+ if (!strcmp ("final", p))
+ result = PRAGMA_OMP_CLAUSE_FINAL;
+ else if (!strcmp ("firstprivate", p))
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
break;
case 'l':
if (!strcmp ("lastprivate", p))
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
break;
+ case 'm':
+ if (!strcmp ("mergeable", p))
+ result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+ break;
case 'n':
if (!strcmp ("nowait", p))
result = PRAGMA_OMP_CLAUSE_NOWAIT;
@@ -23588,6 +23594,34 @@ cp_parser_omp_clause_default (cp_parser
return c;
}
+/* OpenMP 3.1:
+ final ( expression ) */
+
+static tree
+cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_condition (parser);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_FINAL);
+ OMP_CLAUSE_FINAL_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
/* OpenMP 2.5:
if ( expression ) */
@@ -23616,6 +23650,23 @@ cp_parser_omp_clause_if (cp_parser *pars
return c;
}
+/* OpenMP 3.1:
+ mergeable */
+
+static tree
+cp_parser_omp_clause_mergeable (cp_parser *parser ATTRIBUTE_UNUSED,
+ tree list, location_t location)
+{
+ tree c;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable",
+ location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_MERGEABLE);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
/* OpenMP 2.5:
nowait */
@@ -23917,6 +23968,10 @@ cp_parser_omp_all_clauses (cp_parser *pa
token->location);
c_name = "default";
break;
+ case PRAGMA_OMP_CLAUSE_FINAL:
+ clauses = cp_parser_omp_clause_final (parser, clauses, token->location);
+ c_name = "final";
+ break;
case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
clauses);
@@ -23931,6 +23986,11 @@ cp_parser_omp_all_clauses (cp_parser *pa
clauses);
c_name = "lastprivate";
break;
+ case PRAGMA_OMP_CLAUSE_MERGEABLE:
+ clauses = cp_parser_omp_clause_mergeable (parser, clauses,
+ token->location);
+ c_name = "mergeable";
+ break;
case PRAGMA_OMP_CLAUSE_NOWAIT:
clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
c_name = "nowait";
@@ -25150,7 +25210,9 @@ cp_parser_omp_single (cp_parser *parser,
| (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
| (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+ | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (1u << PRAGMA_OMP_CLAUSE_FINAL) \
+ | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
static tree
cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
@@ -25177,6 +25239,16 @@ cp_parser_omp_taskwait (cp_parser *parse
finish_omp_taskwait ();
}
+/* OpenMP 3.1:
+ # pragma omp taskyield new-line */
+
+static void
+cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
+{
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ finish_omp_taskyield ();
+}
+
/* OpenMP 2.5:
# pragma omp threadprivate (variable-list) */
@@ -25352,6 +25424,22 @@ cp_parser_pragma (cp_parser *parser, enu
}
break;
+ case PRAGMA_OMP_TASKYIELD:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_taskyield (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location,
+ "%<#pragma omp taskyield%> may only be "
+ "used in compound statements");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
case PRAGMA_OMP_THREADPRIVATE:
cp_parser_omp_threadprivate (parser, pragma_tok);
return false;
--- gcc/cp/cp-tree.h (revision 173013)
+++ gcc/cp/cp-tree.h (working copy)
@@ -5338,6 +5338,7 @@ extern void finish_omp_atomic (enum tr
extern void finish_omp_barrier (void);
extern void finish_omp_flush (void);
extern void finish_omp_taskwait (void);
+extern void finish_omp_taskyield (void);
extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool);
extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t,
--- gcc/fortran/openmp.c (revision 173032)
+++ gcc/fortran/openmp.c (working copy)
@@ -66,6 +66,7 @@ gfc_free_omp_clauses (gfc_omp_clauses *c
return;
gfc_free_expr (c->if_expr);
+ gfc_free_expr (c->final_expr);
gfc_free_expr (c->num_threads);
gfc_free_expr (c->chunk_size);
for (i = 0; i < OMP_LIST_NUM; i++)
@@ -182,6 +183,8 @@ cleanup:
#define OMP_CLAUSE_ORDERED (1 << 11)
#define OMP_CLAUSE_COLLAPSE (1 << 12)
#define OMP_CLAUSE_UNTIED (1 << 13)
+#define OMP_CLAUSE_FINAL (1 << 14)
+#define OMP_CLAUSE_MERGEABLE (1 << 15)
/* Match OpenMP directive clauses. MASK is a bitmask of
clauses that are allowed for a particular directive. */
@@ -205,6 +208,9 @@ gfc_match_omp_clauses (gfc_omp_clauses *
if ((mask & OMP_CLAUSE_IF) && c->if_expr == NULL
&& gfc_match ("if ( %e )", &c->if_expr) == MATCH_YES)
continue;
+ if ((mask & OMP_CLAUSE_FINAL) && c->final_expr == NULL
+ && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
+ continue;
if ((mask & OMP_CLAUSE_NUM_THREADS) && c->num_threads == NULL
&& gfc_match ("num_threads ( %e )", &c->num_threads) == MATCH_YES)
continue;
@@ -383,6 +389,12 @@ gfc_match_omp_clauses (gfc_omp_clauses *
c->untied = needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_MERGEABLE) && !c->mergeable
+ && gfc_match ("mergeable") == MATCH_YES)
+ {
+ c->mergeable = needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_COLLAPSE) && !c->collapse)
{
gfc_expr *cexpr = NULL;
@@ -435,7 +447,8 @@ gfc_match_omp_clauses (gfc_omp_clauses *
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
#define OMP_TASK_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
- | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED)
+ | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED \
+ | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE)
match
gfc_match_omp_parallel (void)
@@ -476,6 +489,20 @@ gfc_match_omp_taskwait (void)
match
+gfc_match_omp_taskyield (void)
+{
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after TASKYIELD clause at %C");
+ return MATCH_ERROR;
+ }
+ new_st.op = EXEC_OMP_TASKYIELD;
+ new_st.ext.omp_clauses = NULL;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_critical (void)
{
char n[GFC_MAX_SYMBOL_LEN+1];
@@ -792,6 +819,14 @@ resolve_omp_clauses (gfc_code *code)
gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
&expr->where);
}
+ if (omp_clauses->final_expr)
+ {
+ gfc_expr *expr = omp_clauses->final_expr;
+ if (gfc_resolve_expr (expr) == FAILURE
+ || expr->ts.type != BT_LOGICAL || expr->rank != 0)
+ gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
+ &expr->where);
+ }
if (omp_clauses->num_threads)
{
gfc_expr *expr = omp_clauses->num_threads;
--- gcc/fortran/dump-parse-tree.c (revision 172776)
+++ gcc/fortran/dump-parse-tree.c (working copy)
@@ -1038,6 +1038,7 @@ show_omp_node (int level, gfc_code *c)
case EXEC_OMP_SINGLE: name = "SINGLE"; break;
case EXEC_OMP_TASK: name = "TASK"; break;
case EXEC_OMP_TASKWAIT: name = "TASKWAIT"; break;
+ case EXEC_OMP_TASKYIELD: name = "TASKYIELD"; break;
case EXEC_OMP_WORKSHARE: name = "WORKSHARE"; break;
default:
gcc_unreachable ();
@@ -1070,6 +1071,7 @@ show_omp_node (int level, gfc_code *c)
return;
case EXEC_OMP_BARRIER:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
return;
default:
break;
@@ -1084,6 +1086,12 @@ show_omp_node (int level, gfc_code *c)
show_expr (omp_clauses->if_expr);
fputc (')', dumpfile);
}
+ if (omp_clauses->final_expr)
+ {
+ fputs (" FINAL(", dumpfile);
+ show_expr (omp_clauses->final_expr);
+ fputc (')', dumpfile);
+ }
if (omp_clauses->num_threads)
{
fputs (" NUM_THREADS(", dumpfile);
@@ -1129,6 +1137,8 @@ show_omp_node (int level, gfc_code *c)
fputs (" ORDERED", dumpfile);
if (omp_clauses->untied)
fputs (" UNTIED", dumpfile);
+ if (omp_clauses->mergeable)
+ fputs (" MERGEABLE", dumpfile);
if (omp_clauses->collapse)
fprintf (dumpfile, " COLLAPSE(%d)", omp_clauses->collapse);
for (list_type = 0; list_type < OMP_LIST_NUM; list_type++)
@@ -2134,6 +2144,7 @@ show_code_node (int level, gfc_code *c)
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
show_omp_node (level, c);
break;
--- gcc/fortran/trans-openmp.c (revision 173032)
+++ gcc/fortran/trans-openmp.c (working copy)
@@ -866,6 +866,21 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->final_expr)
+ {
+ tree final_var;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->final_expr);
+ gfc_add_block_to_block (block, &se.pre);
+ final_var = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_FINAL);
+ OMP_CLAUSE_FINAL_EXPR (c) = final_var;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
if (clauses->num_threads)
{
tree num_threads;
@@ -959,6 +974,12 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->mergeable)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_MERGEABLE);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
if (clauses->collapse)
{
c = build_omp_clause (where.lb->location, OMP_CLAUSE_COLLAPSE);
@@ -1719,6 +1740,13 @@ gfc_trans_omp_taskwait (void)
}
static tree
+gfc_trans_omp_taskyield (void)
+{
+ tree decl = built_in_decls [BUILT_IN_GOMP_TASKYIELD];
+ return build_call_expr_loc (input_location, decl, 0);
+}
+
+static tree
gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
{
tree res, tmp, stmt;
@@ -1911,6 +1939,8 @@ gfc_trans_omp_directive (gfc_code *code)
return gfc_trans_omp_task (code);
case EXEC_OMP_TASKWAIT:
return gfc_trans_omp_taskwait ();
+ case EXEC_OMP_TASKYIELD:
+ return gfc_trans_omp_taskyield ();
case EXEC_OMP_WORKSHARE:
return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
default:
--- gcc/fortran/gfortran.h (revision 173032)
+++ gcc/fortran/gfortran.h (working copy)
@@ -208,8 +208,8 @@ typedef enum
ST_OMP_PARALLEL, ST_OMP_PARALLEL_DO, ST_OMP_PARALLEL_SECTIONS,
ST_OMP_PARALLEL_WORKSHARE, ST_OMP_SECTIONS, ST_OMP_SECTION, ST_OMP_SINGLE,
ST_OMP_THREADPRIVATE, ST_OMP_WORKSHARE, ST_OMP_TASK, ST_OMP_END_TASK,
- ST_OMP_TASKWAIT, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL, ST_END_CRITICAL,
- ST_GET_FCN_CHARACTERISTICS, ST_NONE
+ ST_OMP_TASKWAIT, ST_OMP_TASKYIELD, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL,
+ ST_END_CRITICAL, ST_GET_FCN_CHARACTERISTICS, ST_NONE
}
gfc_statement;
@@ -1045,13 +1045,14 @@ enum gfc_omp_default_sharing
typedef struct gfc_omp_clauses
{
struct gfc_expr *if_expr;
+ struct gfc_expr *final_expr;
struct gfc_expr *num_threads;
gfc_namelist *lists[OMP_LIST_NUM];
enum gfc_omp_sched_kind sched_kind;
struct gfc_expr *chunk_size;
enum gfc_omp_default_sharing default_sharing;
int collapse;
- bool nowait, ordered, untied;
+ bool nowait, ordered, untied, mergeable;
}
gfc_omp_clauses;
@@ -2060,7 +2061,8 @@ typedef enum
EXEC_OMP_PARALLEL_SECTIONS, EXEC_OMP_PARALLEL_WORKSHARE,
EXEC_OMP_SECTIONS, EXEC_OMP_SINGLE, EXEC_OMP_WORKSHARE,
EXEC_OMP_ATOMIC, EXEC_OMP_BARRIER, EXEC_OMP_END_NOWAIT,
- EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT
+ EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT,
+ EXEC_OMP_TASKYIELD
}
gfc_exec_op;
--- gcc/fortran/trans.c (revision 172776)
+++ gcc/fortran/trans.c (working copy)
@@ -1401,6 +1401,7 @@ trans_code (gfc_code * code, tree cond)
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
res = gfc_trans_omp_directive (code);
break;
--- gcc/fortran/frontend-passes.c (revision 172776)
+++ gcc/fortran/frontend-passes.c (working copy)
@@ -810,6 +810,7 @@ gfc_code_walker (gfc_code **c, walk_code
if ((*c)->ext.omp_clauses)
{
WALK_SUBEXPR ((*c)->ext.omp_clauses->if_expr);
+ WALK_SUBEXPR ((*c)->ext.omp_clauses->final_expr);
WALK_SUBEXPR ((*c)->ext.omp_clauses->num_threads);
WALK_SUBEXPR ((*c)->ext.omp_clauses->chunk_size);
}
--- gcc/fortran/resolve.c (revision 172776)
+++ gcc/fortran/resolve.c (working copy)
@@ -8715,6 +8715,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_nam
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
break;
@@ -9274,6 +9275,7 @@ resolve_code (gfc_code *code, gfc_namesp
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
gfc_resolve_omp_directive (code, ns);
break;
--- gcc/fortran/st.c (revision 172776)
+++ gcc/fortran/st.c (working copy)
@@ -206,6 +206,7 @@ gfc_free_statement (gfc_code *p)
case EXEC_OMP_ORDERED:
case EXEC_OMP_END_NOWAIT:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
break;
default:
--- gcc/fortran/match.h (revision 172776)
+++ gcc/fortran/match.h (working copy)
@@ -136,6 +136,7 @@ match gfc_match_omp_sections (void);
match gfc_match_omp_single (void);
match gfc_match_omp_task (void);
match gfc_match_omp_taskwait (void);
+match gfc_match_omp_taskyield (void);
match gfc_match_omp_threadprivate (void);
match gfc_match_omp_workshare (void);
match gfc_match_omp_end_nowait (void);
--- gcc/fortran/parse.c (revision 173032)
+++ gcc/fortran/parse.c (working copy)
@@ -563,6 +563,7 @@ decode_omp_directive (void)
case 't':
match ("task", gfc_match_omp_task, ST_OMP_TASK);
match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
+ match ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD);
match ("threadprivate", gfc_match_omp_threadprivate,
ST_OMP_THREADPRIVATE);
case 'w':
@@ -953,8 +954,9 @@ next_statement (void)
case ST_POINTER_ASSIGNMENT: case ST_EXIT: case ST_CYCLE: \
case ST_ASSIGNMENT: case ST_ARITHMETIC_IF: case ST_WHERE: case ST_FORALL: \
case ST_LABEL_ASSIGNMENT: case ST_FLUSH: case ST_OMP_FLUSH: \
- case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_ERROR_STOP: \
- case ST_SYNC_ALL: case ST_SYNC_IMAGES: case ST_SYNC_MEMORY
+ case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_OMP_TASKYIELD: \
+ case ST_ERROR_STOP: case ST_SYNC_ALL: case ST_SYNC_IMAGES: \
+ case ST_SYNC_MEMORY
/* Statements that mark other executable statements. */
@@ -1534,6 +1536,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_TASKWAIT:
p = "!$OMP TASKWAIT";
break;
+ case ST_OMP_TASKYIELD:
+ p = "!$OMP TASKYIELD";
+ break;
case ST_OMP_THREADPRIVATE:
p = "!$OMP THREADPRIVATE";
break;
--- gcc/c-typeck.c (revision 172776)
+++ gcc/c-typeck.c (working copy)
@@ -10563,6 +10563,8 @@ c_finish_omp_clauses (tree clauses)
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_FINAL:
+ case OMP_CLAUSE_MERGEABLE:
pc = &OMP_CLAUSE_CHAIN (c);
continue;
--- gcc/gimplify.c (revision 172823)
+++ gcc/gimplify.c (working copy)
@@ -5904,6 +5904,7 @@ gimplify_scan_omp_clauses (tree *list_p,
}
break;
+ case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
OMP_CLAUSE_OPERAND (c, 0)
= gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
@@ -5920,6 +5921,7 @@ gimplify_scan_omp_clauses (tree *list_p,
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_MERGEABLE:
break;
case OMP_CLAUSE_DEFAULT:
@@ -6060,6 +6062,8 @@ gimplify_adjust_omp_clauses (tree *list_
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_FINAL:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
--- gcc/tree-nested.c (revision 172776)
+++ gcc/tree-nested.c (working copy)
@@ -1097,6 +1097,7 @@ convert_nonlocal_omp_clauses (tree *pcla
if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
break;
/* FALLTHRU */
+ case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
wi->val_only = true;
@@ -1111,6 +1112,7 @@ convert_nonlocal_omp_clauses (tree *pcla
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
@@ -1594,6 +1596,7 @@ convert_local_omp_clauses (tree *pclause
if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
break;
/* FALLTHRU */
+ case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
wi->val_only = true;
@@ -1608,6 +1611,7 @@ convert_local_omp_clauses (tree *pclause
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_MERGEABLE:
break;
default:
--- gcc/omp-builtins.def (revision 172776)
+++ gcc/omp-builtins.def (working copy)
@@ -37,6 +37,8 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER,
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT, "GOMP_taskwait",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKYIELD, "GOMP_taskyield",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_START, "GOMP_critical_start",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_END, "GOMP_critical_end",
--- gcc/c-parser.c (revision 173035)
+++ gcc/c-parser.c (working copy)
@@ -1156,6 +1156,7 @@ static void c_parser_omp_threadprivate (
static void c_parser_omp_barrier (c_parser *);
static void c_parser_omp_flush (c_parser *);
static void c_parser_omp_taskwait (c_parser *);
+static void c_parser_omp_taskyield (c_parser *);
enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context);
@@ -8205,6 +8206,17 @@ c_parser_pragma (c_parser *parser, enum
c_parser_omp_taskwait (parser);
return false;
+ case PRAGMA_OMP_TASKYIELD:
+ if (context != pragma_compound)
+ {
+ if (context == pragma_stmt)
+ c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
+ "used in compound statements");
+ goto bad_stmt;
+ }
+ c_parser_omp_taskyield (parser);
+ return false;
+
case PRAGMA_OMP_THREADPRIVATE:
c_parser_omp_threadprivate (parser);
return false;
@@ -8320,13 +8332,19 @@ c_parser_omp_clause_name (c_parser *pars
result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
break;
case 'f':
- if (!strcmp ("firstprivate", p))
+ if (!strcmp ("final", p))
+ result = PRAGMA_OMP_CLAUSE_FINAL;
+ else if (!strcmp ("firstprivate", p))
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
break;
case 'l':
if (!strcmp ("lastprivate", p))
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
break;
+ case 'm':
+ if (!strcmp ("mergeable", p))
+ result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+ break;
case 'n':
if (!strcmp ("nowait", p))
result = PRAGMA_OMP_CLAUSE_NOWAIT;
@@ -8568,6 +8586,31 @@ c_parser_omp_clause_firstprivate (c_pars
return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
}
+/* OpenMP 3.1:
+ final ( expression ) */
+
+static tree
+c_parser_omp_clause_final (c_parser *parser, tree list)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ tree t = c_parser_paren_condition (parser);
+ tree c;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
+
+ c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
+ OMP_CLAUSE_FINAL_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+ else
+ c_parser_error (parser, "expected %<(%>");
+
+ return list;
+}
+
/* OpenMP 2.5:
if ( expression ) */
@@ -8602,6 +8645,24 @@ c_parser_omp_clause_lastprivate (c_parse
return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
}
+/* OpenMP 3.1:
+ mergeable */
+
+static tree
+c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+ tree c;
+
+ /* FIXME: Should we allow duplicates? */
+ check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
+
+ c = build_omp_clause (c_parser_peek_token (parser)->location,
+ OMP_CLAUSE_MERGEABLE);
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
/* OpenMP 2.5:
nowait */
@@ -8940,6 +9001,10 @@ c_parser_omp_all_clauses (c_parser *pars
clauses = c_parser_omp_clause_firstprivate (parser, clauses);
c_name = "firstprivate";
break;
+ case PRAGMA_OMP_CLAUSE_FINAL:
+ clauses = c_parser_omp_clause_final (parser, clauses);
+ c_name = "final";
+ break;
case PRAGMA_OMP_CLAUSE_IF:
clauses = c_parser_omp_clause_if (parser, clauses);
c_name = "if";
@@ -8948,6 +9013,10 @@ c_parser_omp_all_clauses (c_parser *pars
clauses = c_parser_omp_clause_lastprivate (parser, clauses);
c_name = "lastprivate";
break;
+ case PRAGMA_OMP_CLAUSE_MERGEABLE:
+ clauses = c_parser_omp_clause_mergeable (parser, clauses);
+ c_name = "mergeable";
+ break;
case PRAGMA_OMP_CLAUSE_NOWAIT:
clauses = c_parser_omp_clause_nowait (parser, clauses);
c_name = "nowait";
@@ -9958,7 +10027,9 @@ c_parser_omp_single (location_t loc, c_p
| (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
| (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+ | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (1u << PRAGMA_OMP_CLAUSE_FINAL) \
+ | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
static tree
c_parser_omp_task (location_t loc, c_parser *parser)
@@ -9987,6 +10058,20 @@ c_parser_omp_taskwait (c_parser *parser)
c_finish_omp_taskwait (loc);
}
+/* OpenMP 3.1:
+ # pragma omp taskyield new-line
+*/
+
+static void
+c_parser_omp_taskyield (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_pragma (parser);
+ c_parser_skip_to_pragma_eol (parser);
+
+ c_finish_omp_taskyield (loc);
+}
+
/* Main entry point to parsing most OpenMP pragmas. */
static void
--- libgomp/libgomp_g.h (revision 172776)
+++ libgomp/libgomp_g.h (working copy)
@@ -158,11 +158,12 @@ extern void GOMP_ordered_end (void);
extern void GOMP_parallel_start (void (*) (void *), void *, unsigned);
extern void GOMP_parallel_end (void);
-/* team.c */
+/* task.c */
extern void GOMP_task (void (*) (void *), void *, void (*) (void *, void *),
long, long, bool, unsigned);
extern void GOMP_taskwait (void);
+extern void GOMP_taskyield (void);
/* sections.c */
--- libgomp/libgomp.map (revision 172776)
+++ libgomp/libgomp.map (working copy)
@@ -179,3 +179,8 @@ GOMP_2.0 {
GOMP_loop_ull_static_next;
GOMP_loop_ull_static_start;
} GOMP_1.0;
+
+GOMP_3.0 {
+ global:
+ GOMP_taskyield;
+} GOMP_2.0;
--- libgomp/libgomp.h (revision 172776)
+++ libgomp/libgomp.h (working copy)
@@ -253,6 +253,7 @@ struct gomp_task
enum gomp_task_kind kind;
bool in_taskwait;
bool in_tied_task;
+ bool final_task;
gomp_sem_t taskwait_sem;
};
--- libgomp/task.c (revision 172776)
+++ libgomp/task.c (working copy)
@@ -41,6 +41,7 @@ gomp_init_task (struct gomp_task *task,
task->kind = GOMP_TASK_IMPLICIT;
task->in_taskwait = false;
task->in_tied_task = false;
+ task->final_task = false;
task->children = NULL;
gomp_sem_init (&task->taskwait_sem, 0);
}
@@ -77,8 +78,7 @@ gomp_clear_parent (struct gomp_task *chi
void
GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
- long arg_size, long arg_align, bool if_clause,
- unsigned flags __attribute__((unused)))
+ long arg_size, long arg_align, bool if_clause, unsigned flags)
{
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
@@ -95,12 +95,14 @@ GOMP_task (void (*fn) (void *), void *da
#endif
if (!if_clause || team == NULL
+ || (thr->task && thr->task->final_task)
|| team->task_count > 64 * team->nthreads)
{
struct gomp_task task;
gomp_init_task (&task, thr->task, gomp_icv (false));
task.kind = GOMP_TASK_IFFALSE;
+ task.final_task = (thr->task && thr->task->final_task) || (flags & 2);
if (thr->task)
task.in_tied_task = thr->task->in_tied_task;
thr->task = &task;
@@ -145,6 +147,7 @@ GOMP_task (void (*fn) (void *), void *da
task->fn = fn;
task->fn_data = arg;
task->in_tied_task = true;
+ task->final_task = (flags & 2) >> 1;
gomp_mutex_lock (&team->task_lock);
if (parent->children)
{
@@ -363,10 +366,20 @@ GOMP_taskwait (void)
}
}
+/* Called when encountering a taskyield directive. */
+
+void
+GOMP_taskyield (void)
+{
+ /* Nothing at the moment. */
+}
+
int
omp_in_final (void)
{
- return false; /* FIXME */
+ struct gomp_thread *thr = gomp_thread ();
+ return thr->task && (thr->task->kind == GOMP_TASK_IFFALSE
+ || thr->task->final_task);
}
ialias (omp_in_final)
--- libgomp/testsuite/libgomp.c++/task-8.C (revision 0)
+++ libgomp/testsuite/libgomp.c++/task-8.C (revision 0)
@@ -0,0 +1,44 @@
+// { dg-do run }
+
+#include <omp.h>
+#include <cstdlib>
+
+int err;
+
+int
+main ()
+{
+ int e;
+#pragma omp parallel shared(err)
+ {
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ {
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ #pragma omp task final (1) shared(err)
+ {
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp taskyield
+ #pragma omp taskwait
+ #pragma omp task shared(err)
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ }
+ #pragma omp atomic read
+ e = err;
+ if (e)
+ abort ();
+}
--- libgomp/testsuite/libgomp.fortran/task3.f90 (revision 0)
+++ libgomp/testsuite/libgomp.fortran/task3.f90 (revision 0)
@@ -0,0 +1,43 @@
+! { dg-do run }
+
+ use omp_lib
+ integer :: err, e
+
+!$omp parallel shared(err) private(e)
+ if (omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp task if (.false.) shared(err)
+ if (.not.omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp task if (.false.) shared(err)
+ if (.not.omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp end task
+!$omp end task
+!$omp atomic read
+ e = err
+!$omp task final (e .eq. 0) shared(err)
+ if (.not.omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp taskyield
+!$omp taskwait
+!$omp task shared(err)
+ if (.not.omp_in_final ()) then
+!$omp atomic write
+ err = 1
+ endif
+!$omp end task
+!$omp end task
+!$omp end parallel
+!$omp atomic read
+ e = err
+ if (e .ne. 0) call abort
+end
--- libgomp/testsuite/libgomp.c/task-5.c (revision 0)
+++ libgomp/testsuite/libgomp.c/task-5.c (revision 0)
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+int err;
+
+int
+main ()
+{
+ int e;
+#pragma omp parallel shared(err)
+ {
+ if (omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ {
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp task if (0) shared(err)
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ #pragma omp task final (1) shared(err)
+ {
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ #pragma omp taskyield
+ #pragma omp taskwait
+ #pragma omp task shared(err)
+ if (!omp_in_final ())
+ #pragma omp atomic write
+ err = 1;
+ }
+ }
+ #pragma omp atomic read
+ e = err;
+ if (e)
+ abort ();
+ return 0;
+}
Jakub
More information about the Gcc-patches
mailing list