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

Reply via email to