diff mbox

[gomp4.1] Parsing of critical construct with hint, and some locks with hint library changes

Message ID 20150612161705.GZ10247@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek June 12, 2015, 4:17 p.m. UTC
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  <jakub@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.


	Jakub
diff mbox

Patch

--- 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