Hi! I've committed following parsing support for #pragma omp criticial (foobar) hint (omp_lock_hint_uncontended) and a header only change in libgomp for the omp_init*lock_with_hint APIs.
We'll need to decide if we want to implement the hinted locks and how first I guess (I believe Intel is using HLE (or HTM?) for the omp_lock_hint_speculative, and I bet for omp_lock_hint_uncontended simple spinlock without futex, or at least for a while). Next issue is that omp_lock_t right now is just 32-bit and omp_nest_lock_t is 64-bit, I guess we can increase it with symbol versioning another set of lock entrypoints, but the question is what exactly we want to store (just the current 32-bit lock, for nested locks 32-bit counter and 32-bit hint, something else?). There is another issue, because e.g. on 32-bit arches only kind=4 and kind=8 are supported, so I'm afraid at least for nest locks we'll need to malloc something (unless we decide to ignore the hints for now). 2015-06-12 Jakub Jelinek <ja...@redhat.com> * tree.def (OMP_CRITICAL): Move before OMP_SINGLE. Add OMP_CRITICAL_CLAUSES operand. * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_HINT. * tree.h (OMP_BODY): Replace OMP_CRITICAL with OMP_TASKGROUP. (OMP_CRITICAL_CLAUSES): Define. (OMP_CRITICAL_NAME): Adjust to be 3rd operand instead of 2nd. (OMP_CLAUSE_NUM_TASKS_EXPR): Formatting fix. (OMP_CLAUSE_HINT_EXPR): Define. * tree.c (omp_clause_num_ops): Add entry for OMP_CLAUSE_HINT. (omp_clause_code_name): Likewise. (walk_tree_1): Handle OMP_CLAUSE_HINT clause. * tree-pretty-print.c (dump_omp_clause): Likewise. (dump_generic_node): Dump OMP_CRITICAL_CLAUSES for OMP_CRITICAL. * gimple.h (gomp_critical): Add clauses field before name. (gimple_build_omp_critical): Adjust prototype. (gimple_omp_critical_name_ptr, gimple_omp_critical_set_name): Fix up function comments. (gimple_omp_critical_clauses, gimple_omp_critical_clauses_ptr, gimple_omp_critical_set_clauses): New functions. * gimple.c (gimple_build_omp_critical): Add CLAUSES argument, set it. (gimple_copy): Unshare and copy gimple_omp_critical_clauses. * gimple-pretty-print.c (dump_gimple_omp_critical): Print gimple_omp_critical_clauses. * gimple-walk.c (walk_gimple_op): Walk gimple_omp_critical_clauses_ptr. * gimplify.c (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_HINT. (gimplify_expr): Gimplify OMP_CRITICAL_CLAUSES, adjust gimple_build_omp_critical caller. * tree-inline.c (remap_gimple_stmt): Adjust gimple_build_omp_critical caller. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Handle OMP_CLAUSE_HINT clause. gcc/c-family/ * c-common.h (c_finish_omp_critical): Add CLAUSES argument to the prototype. * c-omp.c (c_finish_omp_critical): Likewise. Set OMP_CRITICAL_CLAUSES to it. * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_HINT. gcc/c/ * c-parser.c (c_parser_omp_clause_name): Parse hint clause. (c_parser_omp_clause_num_tasks, c_parser_omp_clause_grainsize, c_parser_omp_clause_priority): Fix up pastos in *_loc variable names. (c_parser_omp_clause_hint): New function. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_HINT. (OMP_CRITICAL_CLAUSE_MASK): Define. (c_parser_omp_critical): Parse optional hint clause. Adjust c_finish_omp_critical caller. * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_HINT. gcc/cp/ * parser.c (cp_parser_omp_clause_name): Parse hint clause. (cp_parser_omp_clause_hint): New function. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_HINT. (OMP_CRITICAL_CLAUSE_MASK): Define. (cp_parser_omp_critical): Parse optional hint clause. Adjust c_finish_omp_critical caller. * pt.c (tsubst_expr): Handle OMP_CRITICAL like OMP_SECTIONS. * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_HINT. gcc/fortran/ * trans-openmp.c (gfc_trans_omp_critical): Adjust building OMP_CRITICAL trees. libgomp/ * omp.h.in (omp_lock_hint_t): New type. (omp_init_lock_with_hint, omp_init_nest_lock_with_hint): New prototypes. * omp_lib.f90.in (omp_lock_hint_kind): New kind parameter. (omp_lock_hint_none, omp_lock_hint_uncontended, omp_lock_hint_contended, omp_lock_hint_nonspeculative, omp_lock_hint_speculative): New parameters. (omp_init_lock_with_hint, omp_init_nest_lock_with_hint): New interfaces. * omp_lib.h.in (omp_lock_hint_kind): New kind parameter. (omp_lock_hint_none, omp_lock_hint_uncontended, omp_lock_hint_contended, omp_lock_hint_nonspeculative, omp_lock_hint_speculative): New parameters. (omp_init_lock_with_hint, omp_init_nest_lock_with_hint): New external procedures. --- gcc/tree.def.jj 2015-05-14 09:05:23.000000000 +0200 +++ gcc/tree.def 2015-06-12 16:30:03.412975085 +0200 @@ -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). */ --- gcc/tree-core.h.jj 2015-06-11 14:34:43.000000000 +0200 +++ gcc/tree-core.h 2015-06-12 14:58:27.127001388 +0200 @@ -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_, --- gcc/tree.h.jj 2015-06-11 18:22:28.000000000 +0200 +++ gcc/tree.h 2015-06-12 15:20:47.632902112 +0200 @@ -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) --- gcc/tree.c.jj 2015-06-08 10:49:02.000000000 +0200 +++ gcc/tree.c 2015-06-12 16:42:16.287117923 +0200 @@ -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_: --- gcc/tree-pretty-print.c.jj 2015-06-11 18:25:40.000000000 +0200 +++ gcc/tree-pretty-print.c 2015-06-12 16:42:16.317117479 +0200 @@ -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: --- gcc/gimple.h.jj 2015-05-05 12:59:58.000000000 +0200 +++ gcc/gimple.h 2015-06-12 16:31:59.379257103 +0200 @@ -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 --- gcc/gimple.c.jj 2015-05-14 09:06:20.000000000 +0200 +++ gcc/gimple.c 2015-06-12 16:42:16.304117671 +0200 @@ -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: --- gcc/gimple-pretty-print.c.jj 2015-05-07 17:27:55.000000000 +0200 +++ gcc/gimple-pretty-print.c 2015-06-12 16:42:16.294117820 +0200 @@ -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); --- gcc/gimple-walk.c.jj 2015-05-14 09:03:15.000000000 +0200 +++ gcc/gimple-walk.c 2015-06-12 16:42:16.300117731 +0200 @@ -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; --- gcc/gimplify.c.jj 2015-06-11 12:21:25.000000000 +0200 +++ gcc/gimplify.c 2015-06-12 16:42:16.283117982 +0200 @@ -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 (); --- gcc/tree-inline.c.jj 2015-04-24 12:32:12.000000000 +0200 +++ gcc/tree-inline.c 2015-06-12 16:42:16.314117523 +0200 @@ -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: --- gcc/tree-nested.c.jj 2015-06-08 11:22:30.000000000 +0200 +++ gcc/tree-nested.c 2015-06-12 16:42:16.290117879 +0200 @@ -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; --- gcc/c-family/c-common.h.jj 2015-05-19 18:56:45.000000000 +0200 +++ gcc/c-family/c-common.h 2015-06-12 16:31:13.212941034 +0200 @@ -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, --- gcc/c-family/c-omp.c.jj 2015-06-11 20:07:49.000000000 +0200 +++ gcc/c-family/c-omp.c 2015-06-12 16:42:16.307117627 +0200 @@ -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); } --- gcc/c-family/c-pragma.h.jj 2015-04-29 11:03:04.000000000 +0200 +++ gcc/c-family/c-pragma.h 2015-06-12 15:51:05.233723278 +0200 @@ -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, --- gcc/c/c-parser.c.jj 2015-06-11 18:41:48.000000000 +0200 +++ gcc/c/c-parser.c 2015-06-12 16:42:16.297117775 +0200 @@ -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: --- gcc/c/c-typeck.c.jj 2015-06-10 19:50:26.000000000 +0200 +++ gcc/c/c-typeck.c 2015-06-12 17:37:33.953267337 +0200 @@ -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: --- gcc/cp/parser.c.jj 2015-06-11 18:42:54.000000000 +0200 +++ gcc/cp/parser.c 2015-06-12 16:42:16.276118086 +0200 @@ -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: --- gcc/cp/pt.c.jj 2015-06-02 18:19:13.000000000 +0200 +++ gcc/cp/pt.c 2015-06-12 16:42:16.280118027 +0200 @@ -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: --- gcc/cp/semantics.c.jj 2015-06-11 17:12:29.000000000 +0200 +++ gcc/cp/semantics.c 2015-06-12 17:38:36.301357936 +0200 @@ -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: --- gcc/fortran/trans-openmp.c.jj 2015-05-19 18:57:21.000000000 +0200 +++ gcc/fortran/trans-openmp.c 2015-06-12 16:42:16.311117568 +0200 @@ -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 { --- libgomp/omp.h.in.jj 2015-04-29 11:03:04.000000000 +0200 +++ libgomp/omp.h.in 2015-06-12 16:45:16.611449325 +0200 @@ -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; --- libgomp/omp_lib.f90.in.jj 2015-06-11 10:29:33.000000000 +0200 +++ libgomp/omp_lib.f90.in 2015-06-12 17:34:56.187568487 +0200 @@ -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 --- libgomp/omp_lib.h.in.jj 2015-04-29 11:03:04.000000000 +0200 +++ libgomp/omp_lib.h.in 2015-06-12 17:32:10.319997734 +0200 @@ -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 Jakub