@@ -1144,6 +1144,12 @@ DEFTREECODE (OMP_SECTIONS, "omp_sections
Operand 1: OMP_ORDERED_CLAUSES: List of clauses. */
DEFTREECODE (OMP_ORDERED, "omp_ordered", tcc_statement, 2)
+/* OpenMP - #pragma omp critical [name]
+ Operand 0: OMP_CRITICAL_BODY: Critical section body.
+ Operand 1: OMP_CRITICAL_CLAUSES: List of clauses.
+ Operand 2: OMP_CRITICAL_NAME: Identifier for critical section. */
+DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 3)
+
/* OpenMP - #pragma omp single
Operand 0: OMP_SINGLE_BODY: Single section body.
Operand 1: OMP_SINGLE_CLAUSES: List of clauses. */
@@ -1161,11 +1167,6 @@ DEFTREECODE (OMP_MASTER, "omp_master", t
Operand 0: OMP_TASKGROUP_BODY: Taskgroup body. */
DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 1)
-/* OpenMP - #pragma omp critical [name]
- Operand 0: OMP_CRITICAL_BODY: Critical section body.
- Operand 1: OMP_CRITICAL_NAME: Identifier for critical section. */
-DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 2)
-
/* OpenACC - #pragma acc cache (variable1 ... variableN)
Operand 0: OACC_CACHE_CLAUSES: List of variables (transformed into
OMP_CLAUSE__CACHE_ clauses). */
@@ -388,6 +388,9 @@ enum omp_clause_code {
/* OpenMP clause: simd. */
OMP_CLAUSE_SIMD,
+ /* OpenMP clause: hint (integer-expression). */
+ OMP_CLAUSE_HINT,
+
/* Internally used only clause, holding SIMD uid. */
OMP_CLAUSE__SIMDUID_,
@@ -1200,7 +1200,7 @@ extern void protected_set_expr_location
/* Generic accessors for OMP nodes that keep the body as operand 0, and clauses
as operand 1. */
#define OMP_BODY(NODE) \
- TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_CRITICAL), 0)
+ TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_TASKGROUP), 0)
#define OMP_CLAUSES(NODE) \
TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_SINGLE), 1)
@@ -1277,7 +1277,8 @@ extern void protected_set_expr_location
#define OMP_ORDERED_CLAUSES(NODE) TREE_OPERAND (OMP_ORDERED_CHECK (NODE), 1)
#define OMP_CRITICAL_BODY(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 0)
-#define OMP_CRITICAL_NAME(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 1)
+#define OMP_CRITICAL_CLAUSES(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 1)
+#define OMP_CRITICAL_NAME(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 2)
#define OMP_TEAMS_BODY(NODE) TREE_OPERAND (OMP_TEAMS_CHECK (NODE), 0)
#define OMP_TEAMS_CLAUSES(NODE) TREE_OPERAND (OMP_TEAMS_CHECK (NODE), 1)
@@ -1381,7 +1382,9 @@ extern void protected_set_expr_location
#define OMP_CLAUSE_SCHEDULE_CHUNK_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SCHEDULE), 0)
#define OMP_CLAUSE_NUM_TASKS_EXPR(NODE) \
- OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TASKS),0)
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TASKS), 0)
+#define OMP_CLAUSE_HINT_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_HINT), 0)
#define OMP_CLAUSE_GRAINSIZE_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_GRAINSIZE),0)
@@ -369,6 +369,7 @@ unsigned const char omp_clause_num_ops[]
0, /* OMP_CLAUSE_NOGROUP */
0, /* OMP_CLAUSE_THREADS */
0, /* OMP_CLAUSE_SIMD */
+ 1, /* OMP_CLAUSE_HINT */
1, /* OMP_CLAUSE__SIMDUID_ */
1, /* OMP_CLAUSE__CILK_FOR_COUNT_ */
0, /* OMP_CLAUSE_INDEPENDENT */
@@ -434,6 +435,7 @@ const char * const omp_clause_code_name[
"nogroup",
"threads",
"simd",
+ "hint",
"_simduid_",
"_Cilk_for_count_",
"independent",
@@ -11305,6 +11307,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
+ case OMP_CLAUSE_HINT:
case OMP_CLAUSE__LOOPTEMP_:
case OMP_CLAUSE__SIMDUID_:
case OMP_CLAUSE__CILK_FOR_COUNT_:
@@ -741,6 +741,13 @@ dump_omp_clause (pretty_printer *pp, tre
pp_right_paren (pp);
break;
+ case OMP_CLAUSE_HINT:
+ pp_string (pp, "hint(");
+ dump_generic_node (pp, OMP_CLAUSE_HINT_EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ break;
+
case OMP_CLAUSE__SIMDUID_:
pp_string (pp, "_simduid_(");
dump_generic_node (pp, OMP_CLAUSE__SIMDUID__DECL (clause),
@@ -2867,6 +2874,7 @@ dump_generic_node (pretty_printer *pp, t
flags, false);
pp_right_paren (pp);
}
+ dump_omp_clauses (pp, OMP_CRITICAL_CLAUSES (node), spc, flags);
goto dump_omp_body;
case OMP_ATOMIC:
@@ -516,7 +516,10 @@ struct GTY((tag("GSS_OMP_CRITICAL")))
{
/* [ WORD 1-7 ] : base class */
- /* [ WORD 8 ]
+ /* [ WORD 8 ] */
+ tree clauses;
+
+ /* [ WORD 9 ]
Critical section name. */
tree name;
};
@@ -1340,7 +1343,7 @@ gdebug *gimple_build_debug_bind_stat (tr
gdebug *gimple_build_debug_source_bind_stat (tree, tree, gimple MEM_STAT_DECL);
#define gimple_build_debug_source_bind(var,val,stmt) \
gimple_build_debug_source_bind_stat ((var), (val), (stmt) MEM_STAT_INFO)
-gomp_critical *gimple_build_omp_critical (gimple_seq, tree);
+gomp_critical *gimple_build_omp_critical (gimple_seq, tree, tree);
gomp_for *gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq);
gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
gomp_task *gimple_build_omp_task (gimple_seq, tree, tree, tree, tree,
@@ -4403,7 +4406,8 @@ gimple_omp_critical_name (const gomp_cri
}
-/* Return a pointer to the name associated with OMP critical statement GS. */
+/* Return a pointer to the name associated with OMP critical statement
+ CRIT_STMT. */
static inline tree *
gimple_omp_critical_name_ptr (gomp_critical *crit_stmt)
@@ -4412,7 +4416,8 @@ gimple_omp_critical_name_ptr (gomp_criti
}
-/* Set NAME to be the name associated with OMP critical statement GS. */
+/* Set NAME to be the name associated with OMP critical statement
+ CRIT_STMT. */
static inline void
gimple_omp_critical_set_name (gomp_critical *crit_stmt, tree name)
@@ -4421,6 +4426,35 @@ gimple_omp_critical_set_name (gomp_criti
}
+/* Return the clauses associated with OMP_CRITICAL statement CRIT_STMT. */
+
+static inline tree
+gimple_omp_critical_clauses (const gomp_critical *crit_stmt)
+{
+ return crit_stmt->clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP critical statement
+ CRIT_STMT. */
+
+static inline tree *
+gimple_omp_critical_clauses_ptr (gomp_critical *crit_stmt)
+{
+ return &crit_stmt->clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP critical statement
+ CRIT_STMT. */
+
+static inline void
+gimple_omp_critical_set_clauses (gomp_critical *crit_stmt, tree clauses)
+{
+ crit_stmt->clauses = clauses;
+}
+
+
/* Return the kind of the OMP_FOR statemement G. */
static inline int
@@ -855,14 +855,16 @@ gimple_build_debug_source_bind_stat (tre
/* Build a GIMPLE_OMP_CRITICAL statement.
BODY is the sequence of statements for which only one thread can execute.
- NAME is optional identifier for this critical block. */
+ NAME is optional identifier for this critical block.
+ CLAUSES are clauses for this critical block. */
gomp_critical *
-gimple_build_omp_critical (gimple_seq body, tree name)
+gimple_build_omp_critical (gimple_seq body, tree name, tree clauses)
{
gomp_critical *p
= as_a <gomp_critical *> (gimple_alloc (GIMPLE_OMP_CRITICAL, 0));
gimple_omp_critical_set_name (p, name);
+ gimple_omp_critical_set_clauses (p, clauses);
if (body)
gimple_omp_set_body (p, body);
@@ -1810,9 +1812,12 @@ gimple_copy (gimple stmt)
goto copy_omp_body;
case GIMPLE_OMP_CRITICAL:
- t = unshare_expr (gimple_omp_critical_name (
- as_a <gomp_critical *> (stmt)));
+ t = unshare_expr (gimple_omp_critical_name
+ (as_a <gomp_critical *> (stmt)));
gimple_omp_critical_set_name (as_a <gomp_critical *> (copy), t);
+ t = unshare_expr (gimple_omp_critical_clauses
+ (as_a <gomp_critical *> (stmt)));
+ gimple_omp_critical_set_clauses (as_a <gomp_critical *> (copy), t);
goto copy_omp_body;
case GIMPLE_OMP_SECTIONS:
@@ -1549,6 +1549,7 @@ dump_gimple_omp_critical (pretty_printer
flags, false);
pp_right_paren (buffer);
}
+ dump_omp_clauses (buffer, gimple_omp_critical_clauses (gs), spc, flags);
if (!gimple_seq_empty_p (gimple_omp_body (gs)))
{
newline_and_indent (buffer, spc + 2);
@@ -332,6 +332,10 @@ walk_gimple_op (gimple stmt, walk_tree_f
callback_op, wi, pset);
if (ret)
return ret;
+ ret = walk_tree (gimple_omp_critical_clauses_ptr (omp_stmt),
+ callback_op, wi, pset);
+ if (ret)
+ return ret;
}
break;
@@ -6570,6 +6570,7 @@ gimplify_scan_omp_clauses (tree *list_p,
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
+ case OMP_CLAUSE_HINT:
case OMP_CLAUSE__CILK_FOR_COUNT_:
case OMP_CLAUSE_ASYNC:
case OMP_CLAUSE_WAIT:
@@ -6964,6 +6965,7 @@ gimplify_adjust_omp_clauses (gimple_seq
case OMP_CLAUSE_NOGROUP:
case OMP_CLAUSE_THREADS:
case OMP_CLAUSE_SIMD:
+ case OMP_CLAUSE_HINT:
case OMP_CLAUSE__CILK_FOR_COUNT_:
case OMP_CLAUSE_ASYNC:
case OMP_CLAUSE_WAIT:
@@ -8935,8 +8937,13 @@ gimplify_expr (tree *expr_p, gimple_seq
g = gimple_build_omp_ordered (body);
break;
case OMP_CRITICAL:
+ gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
+ pre_p, ORT_WORKSHARE);
+ gimplify_adjust_omp_clauses (pre_p,
+ &OMP_CRITICAL_CLAUSES (*expr_p));
g = gimple_build_omp_critical (body,
- OMP_CRITICAL_NAME (*expr_p));
+ OMP_CRITICAL_NAME (*expr_p),
+ OMP_CRITICAL_CLAUSES (*expr_p));
break;
default:
gcc_unreachable ();
@@ -1545,8 +1545,10 @@ remap_gimple_stmt (gimple stmt, copy_bod
case GIMPLE_OMP_CRITICAL:
s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
copy = gimple_build_omp_critical (s1,
- gimple_omp_critical_name (
- as_a <gomp_critical *> (stmt)));
+ gimple_omp_critical_name
+ (as_a <gomp_critical *> (stmt)),
+ gimple_omp_critical_clauses
+ (as_a <gomp_critical *> (stmt)));
break;
case GIMPLE_TRANSACTION:
@@ -1149,6 +1149,7 @@ convert_nonlocal_omp_clauses (tree *pcla
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
+ case OMP_CLAUSE_HINT:
case OMP_CLAUSE__CILK_FOR_COUNT_:
wi->val_only = true;
wi->is_lhs = false;
@@ -1795,6 +1796,7 @@ convert_local_omp_clauses (tree *pclause
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
+ case OMP_CLAUSE_HINT:
case OMP_CLAUSE__CILK_FOR_COUNT_:
wi->val_only = true;
wi->is_lhs = false;
@@ -1242,7 +1242,7 @@ enum c_omp_clause_split
extern tree c_finish_omp_master (location_t, tree);
extern tree c_finish_omp_taskgroup (location_t, tree);
-extern tree c_finish_omp_critical (location_t, tree, tree);
+extern tree c_finish_omp_critical (location_t, tree, tree, tree);
extern tree c_finish_omp_ordered (location_t, tree, tree);
extern void c_finish_omp_barrier (location_t);
extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
@@ -108,12 +108,13 @@ c_finish_omp_taskgroup (location_t loc,
if it was omitted. LOC is the location of the #pragma. */
tree
-c_finish_omp_critical (location_t loc, tree body, tree name)
+c_finish_omp_critical (location_t loc, tree body, tree name, tree clauses)
{
tree stmt = make_node (OMP_CRITICAL);
TREE_TYPE (stmt) = void_type_node;
OMP_CRITICAL_BODY (stmt) = body;
OMP_CRITICAL_NAME (stmt) = name;
+ OMP_CRITICAL_CLAUSES (stmt) = clauses;
SET_EXPR_LOCATION (stmt, loc);
return add_stmt (stmt);
}
@@ -94,6 +94,7 @@ typedef enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_FOR,
PRAGMA_OMP_CLAUSE_FROM,
PRAGMA_OMP_CLAUSE_GRAINSIZE,
+ PRAGMA_OMP_CLAUSE_HINT,
PRAGMA_OMP_CLAUSE_IF,
PRAGMA_OMP_CLAUSE_INBRANCH,
PRAGMA_OMP_CLAUSE_LASTPRIVATE,
@@ -9941,7 +9941,9 @@ c_parser_omp_clause_name (c_parser *pars
result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
break;
case 'h':
- if (!strcmp ("host", p))
+ if (!strcmp ("hint", p))
+ result = PRAGMA_OMP_CLAUSE_HINT;
+ else if (!strcmp ("host", p))
result = PRAGMA_OACC_CLAUSE_HOST;
break;
case 'i':
@@ -10710,7 +10712,7 @@ c_parser_omp_clause_num_threads (c_parse
static tree
c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
{
- location_t num_threads_loc = c_parser_peek_token (parser)->location;
+ location_t num_tasks_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
@@ -10739,7 +10741,7 @@ c_parser_omp_clause_num_tasks (c_parser
check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TASKS, "num_tasks");
- c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_TASKS);
+ c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
@@ -10754,7 +10756,7 @@ c_parser_omp_clause_num_tasks (c_parser
static tree
c_parser_omp_clause_grainsize (c_parser *parser, tree list)
{
- location_t num_threads_loc = c_parser_peek_token (parser)->location;
+ location_t grainsize_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
@@ -10783,7 +10785,7 @@ c_parser_omp_clause_grainsize (c_parser
check_no_duplicate_clause (list, OMP_CLAUSE_GRAINSIZE, "grainsize");
- c = build_omp_clause (num_threads_loc, OMP_CLAUSE_GRAINSIZE);
+ c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
@@ -10798,7 +10800,7 @@ c_parser_omp_clause_grainsize (c_parser
static tree
c_parser_omp_clause_priority (c_parser *parser, tree list)
{
- location_t num_threads_loc = c_parser_peek_token (parser)->location;
+ location_t priority_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
@@ -10828,7 +10830,7 @@ c_parser_omp_clause_priority (c_parser *
check_no_duplicate_clause (list, OMP_CLAUSE_PRIORITY, "priority");
- c = build_omp_clause (num_threads_loc, OMP_CLAUSE_PRIORITY);
+ c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
OMP_CLAUSE_PRIORITY_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
@@ -10837,6 +10839,38 @@ c_parser_omp_clause_priority (c_parser *
return list;
}
+/* OpenMP 4.1:
+ hint ( expression ) */
+
+static tree
+c_parser_omp_clause_hint (c_parser *parser, tree list)
+{
+ location_t hint_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ tree c, t = c_parser_expression (parser).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint");
+
+ c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
+ OMP_CLAUSE_HINT_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
/* OpenACC:
num_workers ( expression ) */
@@ -12179,6 +12213,10 @@ c_parser_omp_all_clauses (c_parser *pars
clauses = c_parser_omp_clause_grainsize (parser, clauses);
c_name = "grainsize";
break;
+ case PRAGMA_OMP_CLAUSE_HINT:
+ clauses = c_parser_omp_clause_hint (parser, clauses);
+ c_name = "hint";
+ break;
case PRAGMA_OMP_CLAUSE_IF:
clauses = c_parser_omp_clause_if (parser, clauses);
c_name = "if";
@@ -13171,12 +13209,18 @@ c_parser_omp_barrier (c_parser *parser)
# pragma omp critical [(name)] new-line
structured-block
+ OpenMP 4.1:
+ # pragma omp critical [(name) [hint(expression)]] new-line
+
LOC is the location of the #pragma itself. */
+#define OMP_CRITICAL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
+
static tree
c_parser_omp_critical (location_t loc, c_parser *parser)
{
- tree stmt, name = NULL;
+ tree stmt, name = NULL_TREE, clauses = NULL_TREE;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
@@ -13189,13 +13233,20 @@ c_parser_omp_critical (location_t loc, c
}
else
c_parser_error (parser, "expected identifier");
+
+ clauses = c_parser_omp_all_clauses (parser,
+ OMP_CRITICAL_CLAUSE_MASK,
+ "#pragma omp critical");
+ }
+ else
+ {
+ if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ c_parser_error (parser, "expected %<(%> or end of line");
+ c_parser_skip_to_pragma_eol (parser);
}
- else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- c_parser_error (parser, "expected %<(%> or end of line");
- c_parser_skip_to_pragma_eol (parser);
stmt = c_parser_omp_structured_block (parser);
- return c_finish_omp_critical (loc, stmt, name);
+ return c_finish_omp_critical (loc, stmt, name, clauses);
}
/* OpenMP 2.5:
@@ -12629,6 +12629,7 @@ c_finish_omp_clauses (tree clauses)
case OMP_CLAUSE_NOGROUP:
case OMP_CLAUSE_THREADS:
case OMP_CLAUSE_SIMD:
+ case OMP_CLAUSE_HINT:
case OMP_CLAUSE__CILK_FOR_COUNT_:
case OMP_CLAUSE_NUM_GANGS:
case OMP_CLAUSE_NUM_WORKERS:
@@ -27639,7 +27639,9 @@ cp_parser_omp_clause_name (cp_parser *pa
result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
break;
case 'h':
- if (!strcmp ("host", p))
+ if (!strcmp ("hint", p))
+ result = PRAGMA_OMP_CLAUSE_HINT;
+ else if (!strcmp ("host", p))
result = PRAGMA_OACC_CLAUSE_HOST;
break;
case 'i':
@@ -28508,6 +28510,35 @@ cp_parser_omp_clause_priority (cp_parser
return c;
}
+/* OpenMP 4.1:
+ hint ( expression ) */
+
+static tree
+cp_parser_omp_clause_hint (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_expression (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_HINT, "hint", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_HINT);
+ OMP_CLAUSE_HINT_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
/* OpenACC:
num_workers ( expression ) */
@@ -29648,6 +29679,11 @@ cp_parser_omp_all_clauses (cp_parser *pa
token->location);
c_name = "grainsize";
break;
+ case PRAGMA_OMP_CLAUSE_HINT:
+ clauses = cp_parser_omp_clause_hint (parser, clauses,
+ token->location);
+ c_name = "hint";
+ break;
case PRAGMA_OMP_CLAUSE_IF:
clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
c_name = "if";
@@ -30360,12 +30396,19 @@ cp_parser_omp_barrier (cp_parser *parser
/* OpenMP 2.5:
# pragma omp critical [(name)] new-line
+ structured-block
+
+ OpenMP 4.1:
+ # pragma omp critical [(name) [hint(expression)]] new-line
structured-block */
+#define OMP_CRITICAL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
+
static tree
cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
{
- tree stmt, name = NULL;
+ tree stmt, name = NULL_TREE, clauses = NULL_TREE;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
@@ -30380,11 +30423,16 @@ cp_parser_omp_critical (cp_parser *parse
/*consume_paren=*/true);
if (name == error_mark_node)
name = NULL;
+
+ clauses = cp_parser_omp_all_clauses (parser,
+ OMP_CRITICAL_CLAUSE_MASK,
+ "#pragma omp critical", pragma_tok);
}
- cp_parser_require_pragma_eol (parser, pragma_tok);
+ else
+ cp_parser_require_pragma_eol (parser, pragma_tok);
stmt = cp_parser_omp_structured_block (parser);
- return c_finish_omp_critical (input_location, stmt, name);
+ return c_finish_omp_critical (input_location, stmt, name, clauses);
}
/* OpenMP 2.5:
@@ -14287,6 +14287,7 @@ tsubst_expr (tree t, tree args, tsubst_f
case OMP_SECTIONS:
case OMP_SINGLE:
case OMP_TEAMS:
+ case OMP_CRITICAL:
r = push_omp_privatization_clauses ();
tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false, true,
args, complain, in_decl);
@@ -14326,7 +14327,6 @@ tsubst_expr (tree t, tree args, tsubst_f
break;
case OMP_SECTION:
- case OMP_CRITICAL:
case OMP_MASTER:
case OMP_TASKGROUP:
case OMP_ORDERED:
@@ -6278,6 +6278,28 @@ finish_omp_clauses (tree clauses, bool a
}
break;
+ case OMP_CLAUSE_HINT:
+ t = OMP_CLAUSE_HINT_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<num_tasks%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ {
+ t = maybe_constant_value (t);
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ OMP_CLAUSE_HINT_EXPR (c) = t;
+ }
+ break;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
@@ -3105,7 +3105,8 @@ gfc_trans_omp_critical (gfc_code *code)
if (code->ext.omp_name != NULL)
name = get_identifier (code->ext.omp_name);
stmt = gfc_trans_code (code->block->next);
- return build2_loc (input_location, OMP_CRITICAL, void_type_node, stmt, name);
+ return build3_loc (input_location, OMP_CRITICAL, void_type_node, stmt,
+ NULL_TREE, name);
}
typedef struct dovar_init_d {
@@ -62,6 +62,15 @@ typedef enum omp_proc_bind_t
omp_proc_bind_spread = 4
} omp_proc_bind_t;
+typedef enum omp_lock_hint_t
+{
+ omp_lock_hint_none = 0,
+ omp_lock_hint_uncontended = 1,
+ omp_lock_hint_contended = 2,
+ omp_lock_hint_nonspeculative = 4,
+ omp_lock_hint_speculative = 8,
+} omp_lock_hint_t;
+
#ifdef __cplusplus
extern "C" {
# define __GOMP_NOTHROW throw ()
@@ -84,12 +93,16 @@ extern void omp_set_nested (int) __GOMP_
extern int omp_get_nested (void) __GOMP_NOTHROW;
extern void omp_init_lock (omp_lock_t *) __GOMP_NOTHROW;
+extern void omp_init_lock_with_hint (omp_lock_t *, omp_lock_hint_t)
+ __GOMP_NOTHROW;
extern void omp_destroy_lock (omp_lock_t *) __GOMP_NOTHROW;
extern void omp_set_lock (omp_lock_t *) __GOMP_NOTHROW;
extern void omp_unset_lock (omp_lock_t *) __GOMP_NOTHROW;
extern int omp_test_lock (omp_lock_t *) __GOMP_NOTHROW;
extern void omp_init_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
+extern void omp_init_nest_lock_with_hint (omp_lock_t *, omp_lock_hint_t)
+ __GOMP_NOTHROW;
extern void omp_destroy_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
extern void omp_set_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
extern void omp_unset_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
@@ -29,15 +29,31 @@
integer, parameter :: omp_nest_lock_kind = @OMP_NEST_LOCK_KIND@
integer, parameter :: omp_sched_kind = 4
integer, parameter :: omp_proc_bind_kind = 4
+ integer, parameter :: omp_lock_hint_kind = 4
integer (omp_sched_kind), parameter :: omp_sched_static = 1
integer (omp_sched_kind), parameter :: omp_sched_dynamic = 2
integer (omp_sched_kind), parameter :: omp_sched_guided = 3
integer (omp_sched_kind), parameter :: omp_sched_auto = 4
- integer (omp_proc_bind_kind), parameter :: omp_proc_bind_false = 0
- integer (omp_proc_bind_kind), parameter :: omp_proc_bind_true = 1
- integer (omp_proc_bind_kind), parameter :: omp_proc_bind_master = 2
- integer (omp_proc_bind_kind), parameter :: omp_proc_bind_close = 3
- integer (omp_proc_bind_kind), parameter :: omp_proc_bind_spread = 4
+ integer (omp_proc_bind_kind), &
+ parameter :: omp_proc_bind_false = 0
+ integer (omp_proc_bind_kind), &
+ parameter :: omp_proc_bind_true = 1
+ integer (omp_proc_bind_kind), &
+ parameter :: omp_proc_bind_master = 2
+ integer (omp_proc_bind_kind), &
+ parameter :: omp_proc_bind_close = 3
+ integer (omp_proc_bind_kind), &
+ parameter :: omp_proc_bind_spread = 4
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_none = 0
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_uncontended = 1
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_contended = 2
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_nonspeculative = 4
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_speculative = 8
end module
module omp_lib
@@ -53,6 +69,14 @@
end interface
interface
+ subroutine omp_init_lock_with_hint (svar, hint)
+ use omp_lib_kinds
+ integer (omp_lock_kind), intent (out) :: svar
+ integer (omp_lock_hint_kind), intent (in) :: hint
+ end subroutine omp_init_lock_with_hint
+ end interface
+
+ interface
subroutine omp_init_nest_lock (nvar)
use omp_lib_kinds
integer (omp_nest_lock_kind), intent (out) :: nvar
@@ -60,6 +84,14 @@
end interface
interface
+ subroutine omp_init_nest_lock_with_hint (nvar, hint)
+ use omp_lib_kinds
+ integer (omp_nest_lock_kind), intent (out) :: nvar
+ integer (omp_lock_hint_kind), intent (in) :: hint
+ end subroutine omp_init_nest_lock_with_hint
+ end interface
+
+ interface
subroutine omp_destroy_lock (svar)
use omp_lib_kinds
integer (omp_lock_kind), intent (inout) :: svar
@@ -46,9 +46,23 @@
parameter (omp_proc_bind_master = 2)
parameter (omp_proc_bind_close = 3)
parameter (omp_proc_bind_spread = 4)
+ integer omp_lock_hint_kind
+ parameter (omp_lock_hint_kind = 4)
+ integer (omp_lock_hint_kind) omp_lock_hint_none
+ integer (omp_lock_hint_kind) omp_lock_hint_uncontended
+ integer (omp_lock_hint_kind) omp_lock_hint_contended
+ integer (omp_lock_hint_kind) omp_lock_hint_nonspeculative
+ integer (omp_lock_hint_kind) omp_lock_hint_speculative
+ parameter (omp_lock_hint_none = 0)
+ parameter (omp_lock_hint_uncontended = 1)
+ parameter (omp_lock_hint_contended = 2)
+ parameter (omp_lock_hint_nonspeculative = 4)
+ parameter (omp_lock_hint_speculative = 8)
parameter (openmp_version = 201307)
external omp_init_lock, omp_init_nest_lock
+ external omp_init_lock_with_hint
+ external omp_init_nest_lock_with_hint
external omp_destroy_lock, omp_destroy_nest_lock
external omp_set_lock, omp_set_nest_lock
external omp_unset_lock, omp_unset_nest_lock