[gomp5] Parse task modifier of reduction clauses

Message ID 20180801141955.GR17988@tucnak
State New
Headers show
Series
  • [gomp5] Parse task modifier of reduction clauses
Related show

Commit Message

Jakub Jelinek Aug. 1, 2018, 2:19 p.m.
Hi!

This patch adds just the parsing and diagnostics of task reduction modifier.
Such reductions behave then differently, like task_reduction clause on
taskgroup construct when used on parallel or for/sections.

Tested on x86_64-linux, committed to gomp-5_0-branch.

2018-08-01  Jakub Jelinek  <jakub@redhat.com>

	* tree.h (OMP_CLAUSE_REDUCTION_TASK, OMP_CLAUSE_REDUCTION_INSCAN):
	Define.
	* tree-pretty-print.c (dump_omp_clause): Print reduction modifiers.
	* gimplify.c (gimplify_scan_omp_clauses): Handle
	OMP_CLAUSE_REDUCTION_TASK diagnostics.
gcc/c-family/
	* c-omp.c (c_omp_split_clauses): Handle OMP_CLAUSE_REDUCTION_TASK.
gcc/c/
	* c-parser.c (c_parser_omp_clause_reduction): Add IS_OMP argument,
	parse reduction modifiers.
	(c_parser_oacc_all_clauses, c_parser_omp_all_clauses): Adjust
	c_parser_omp_clause_reduction callers.
gcc/cp/
	* parser.c (cp_parser_omp_clause_reduction): Add IS_OMP argument,
	parse reduction modifiers.
	(cp_parser_oacc_all_clauses, cp_parser_omp_all_clauses): Adjust
	cp_parser_omp_clause_reduction callers.
gcc/testsuite/
	* c-c++-common/gomp/reduction-task-1.c: New test.
	* c-c++-common/gomp/reduction-task-2.c: New test.


	Jakub

Patch

--- gcc/tree.h.jj	2018-07-17 17:24:39.972318592 +0200
+++ gcc/tree.h	2018-07-30 16:18:35.928699592 +0200
@@ -1614,6 +1614,14 @@  extern tree maybe_wrap_with_location (tr
   (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
 			   OMP_CLAUSE_IN_REDUCTION)->base.public_flag)
 
+/* True if a REDUCTION clause has task reduction-modifier.  */
+#define OMP_CLAUSE_REDUCTION_TASK(NODE) \
+  TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION))
+
+/* True if a REDUCTION clause has inscan reduction-modifier.  */
+#define OMP_CLAUSE_REDUCTION_INSCAN(NODE) \
+  TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION))
+
 /* True if a LINEAR clause doesn't need copy in.  True for iterator vars which
    are always initialized inside of the loop construct, false otherwise.  */
 #define OMP_CLAUSE_LINEAR_NO_COPYIN(NODE) \
--- gcc/tree-pretty-print.c.jj	2018-07-10 11:32:22.271156564 +0200
+++ gcc/tree-pretty-print.c	2018-07-30 18:22:56.159264665 +0200
@@ -477,6 +477,13 @@  dump_omp_clause (pretty_printer *pp, tre
       /* FALLTHRU */
     case OMP_CLAUSE_REDUCTION:
       pp_string (pp, "reduction(");
+      if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION)
+	{
+	  if (OMP_CLAUSE_REDUCTION_TASK (clause))
+	    pp_string (pp, "task,");
+	  else if (OMP_CLAUSE_REDUCTION_INSCAN (clause))
+	    pp_string (pp, "inscan,");
+	}
       if (OMP_CLAUSE_REDUCTION_CODE (clause) != ERROR_MARK)
 	{
 	  pp_string (pp,
--- gcc/gimplify.c.jj	2018-07-25 17:40:05.967970906 +0200
+++ gcc/gimplify.c	2018-08-01 14:34:53.945975952 +0200
@@ -7960,6 +7960,7 @@  gimplify_scan_omp_clauses (tree *list_p,
   hash_map<tree, tree> *struct_map_to_clause = NULL;
   tree *prev_list_p = NULL;
   int handled_depend_iterators = -1;
+  int nowait = -1;
 
   ctx = new_omp_context (region_type);
   outer_ctx = ctx->outer_context;
@@ -8113,6 +8114,32 @@  gimplify_scan_omp_clauses (tree *list_p,
 	    }
 	  goto do_add;
 	case OMP_CLAUSE_REDUCTION:
+	  if (OMP_CLAUSE_REDUCTION_TASK (c))
+	    {
+	      if (region_type == ORT_WORKSHARE)
+		{
+		  if (nowait == -1)
+		    nowait = omp_find_clause (*list_p,
+					      OMP_CLAUSE_NOWAIT) != NULL_TREE;
+		  if (nowait
+		      && (outer_ctx == NULL
+			  || outer_ctx->region_type != ORT_COMBINED_PARALLEL))
+		    {
+		      error_at (OMP_CLAUSE_LOCATION (c),
+				"%<task%> reduction modifier on a construct "
+				"with a %<nowait%> clause");
+		      OMP_CLAUSE_REDUCTION_TASK (c) = 0;
+		    }
+		}
+	      else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL)
+		{
+		  error_at (OMP_CLAUSE_LOCATION (c),
+			    "invalid %<task%> reduction modifier on construct "
+			    "other than %<parallel%>, %<for%> or %<sections%>");
+		  OMP_CLAUSE_REDUCTION_TASK (c) = 0;
+		}
+	    }
+	  /* FALLTHRU */
 	case OMP_CLAUSE_IN_REDUCTION:
 	case OMP_CLAUSE_TASK_REDUCTION:
 	  flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
@@ -9016,6 +9043,9 @@  gimplify_scan_omp_clauses (tree *list_p,
 	  break;
 
 	case OMP_CLAUSE_NOWAIT:
+	  nowait = 1;
+	  break;
+
 	case OMP_CLAUSE_ORDERED:
 	case OMP_CLAUSE_UNTIED:
 	case OMP_CLAUSE_COLLAPSE:
--- gcc/c-family/c-omp.c.jj	2018-07-17 17:24:39.973318593 +0200
+++ gcc/c-family/c-omp.c	2018-08-01 14:04:30.178369000 +0200
@@ -1590,6 +1590,28 @@  c_omp_split_clauses (location_t loc, enu
 	   Duplicate it on all of them, but omit on for or sections if
 	   parallel is present.  */
 	case OMP_CLAUSE_REDUCTION:
+	  if (OMP_CLAUSE_REDUCTION_TASK (clauses))
+	    {
+	      if (code == OMP_SIMD /* || code == OMP_LOOP */)
+		{
+		  error_at (OMP_CLAUSE_LOCATION (clauses),
+			    "invalid %<task%> reduction modifier on construct "
+			    "combined with %<simd%>" /* or %<loop%> */);
+		  OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
+		}
+	      else if (code != OMP_SECTIONS
+		       && (mask & (OMP_CLAUSE_MASK_1
+				   << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0
+		       && (mask & (OMP_CLAUSE_MASK_1
+				   << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0)
+		{
+		  error_at (OMP_CLAUSE_LOCATION (clauses),
+			    "invalid %<task%> reduction modifier on construct "
+			    "not combined with %<parallel%>, %<for%> or "
+			    "%<sections%>");
+		  OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
+		}
+	    }
 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
 	    {
 	      if (code == OMP_SIMD)
@@ -1618,9 +1640,9 @@  c_omp_split_clauses (location_t loc, enu
 		    = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
 		  OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
 		    = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
-		  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
-		  cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
-		  s = C_OMP_CLAUSE_SPLIT_TEAMS;
+		  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+		  cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
+		  s = C_OMP_CLAUSE_SPLIT_PARALLEL;
 		}
 	      else if ((mask & (OMP_CLAUSE_MASK_1
 				<< PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
--- gcc/c/c-parser.c.jj	2018-07-24 18:19:26.526677938 +0200
+++ gcc/c/c-parser.c	2018-07-31 13:53:31.320112896 +0200
@@ -13076,20 +13076,48 @@  c_parser_omp_clause_private (c_parser *p
      identifier
 
    OpenMP 5.0:
+   reduction ( reduction-modifier, reduction-operator : variable-list )
    in_reduction ( reduction-operator : variable-list )
    task_reduction ( reduction-operator : variable-list )  */
 
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
-			       tree list)
+			       bool is_omp, tree list)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
   matching_parens parens;
   if (parens.require_open (parser))
     {
+      bool task = false;
+      bool inscan = false;
       enum tree_code code = ERROR_MARK;
       tree reduc_id = NULL_TREE;
 
+      if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+	{
+	  if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+	      && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
+	    {
+	      c_parser_consume_token (parser);
+	      c_parser_consume_token (parser);
+	    }
+	  else if (c_parser_next_token_is (parser, CPP_NAME)
+		   && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
+	    {
+	      const char *p
+		= IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+	      if (strcmp (p, "task") == 0)
+		task = true;
+	      else if (strcmp (p, "inscan") == 0)
+		inscan = true;
+	      if (task || inscan)
+		{
+		  c_parser_consume_token (parser);
+		  c_parser_consume_token (parser);
+		}
+	    }
+	}
+
       switch (c_parser_peek_token (parser)->type)
 	{
 	case CPP_PLUS:
@@ -13171,6 +13199,10 @@  c_parser_omp_clause_reduction (c_parser
 	      while (TREE_CODE (type) == ARRAY_TYPE)
 		type = TREE_TYPE (type);
 	      OMP_CLAUSE_REDUCTION_CODE (c) = code;
+	      if (task)
+		OMP_CLAUSE_REDUCTION_TASK (c) = 1;
+	      else if (inscan)
+		OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
 	      if (code == ERROR_MARK
 		  || !(INTEGRAL_TYPE_P (type)
 		       || TREE_CODE (type) == REAL_TYPE
@@ -14452,12 +14484,12 @@  c_parser_oacc_all_clauses (c_parser *par
 	case PRAGMA_OACC_CLAUSE_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					     clauses);
+					     false, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OACC_CLAUSE_SEQ:
 	  clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_SEQ,
-						clauses);
+						 clauses);
 	  c_name = "seq";
 	  break;
 	case PRAGMA_OACC_CLAUSE_TILE:
@@ -14581,7 +14613,7 @@  c_parser_omp_all_clauses (c_parser *pars
 	case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
-					     clauses);
+					     true, clauses);
 	  c_name = "in_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -14619,7 +14651,7 @@  c_parser_omp_all_clauses (c_parser *pars
 	case PRAGMA_OMP_CLAUSE_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					     clauses);
+					     true, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -14633,7 +14665,7 @@  c_parser_omp_all_clauses (c_parser *pars
 	case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
-					     clauses);
+					     true, clauses);
 	  c_name = "task_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
--- gcc/cp/parser.c.jj	2018-07-25 11:42:54.123510698 +0200
+++ gcc/cp/parser.c	2018-07-31 13:56:33.842637416 +0200
@@ -32931,19 +32931,47 @@  cp_parser_omp_clause_ordered (cp_parser
      id-expression
 
    OpenMP 5.0:
+   reduction ( reduction-modifier, reduction-operator : variable-list )
    in_reduction ( reduction-operator : variable-list )
    task_reduction ( reduction-operator : variable-list )  */
 
 static tree
 cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
-				tree list)
+				bool is_omp, tree list)
 {
   enum tree_code code = ERROR_MARK;
   tree nlist, c, id = NULL_TREE;
+  bool task = false;
+  bool inscan = false;
 
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
+  if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+    {
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT)
+	  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  cp_lexer_consume_token (parser->lexer);
+	}
+      else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+	       && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
+	{
+	  tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+	  const char *p = IDENTIFIER_POINTER (id);
+	  if (strcmp (p, "task") == 0)
+	    task = true;
+	  else if (strcmp (p, "inscan") == 0)
+	    inscan = true;
+	  if (task || inscan)
+	    {
+	      cp_lexer_consume_token (parser->lexer);
+	      cp_lexer_consume_token (parser->lexer);
+	    }
+	}
+    }
+
   switch (cp_lexer_peek_token (parser->lexer)->type)
     {
     case CPP_PLUS: code = PLUS_EXPR; break;
@@ -33021,6 +33049,10 @@  cp_parser_omp_clause_reduction (cp_parse
   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
     {
       OMP_CLAUSE_REDUCTION_CODE (c) = code;
+      if (task)
+	OMP_CLAUSE_REDUCTION_TASK (c) = 1;
+      else if (inscan)
+	OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
       OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = id;
     }
 
@@ -34272,7 +34304,7 @@  cp_parser_oacc_all_clauses (cp_parser *p
 	case PRAGMA_OACC_CLAUSE_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					      clauses);
+					      false, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OACC_CLAUSE_SEQ:
@@ -34422,7 +34454,7 @@  cp_parser_omp_all_clauses (cp_parser *pa
 	case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
-					      clauses);
+					      true, clauses);
 	  c_name = "in_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -34466,7 +34498,7 @@  cp_parser_omp_all_clauses (cp_parser *pa
 	case PRAGMA_OMP_CLAUSE_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					      clauses);
+					      true, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -34483,7 +34515,7 @@  cp_parser_omp_all_clauses (cp_parser *pa
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser,
 					      OMP_CLAUSE_TASK_REDUCTION,
-					      clauses);
+					      true, clauses);
 	  c_name = "task_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
--- gcc/testsuite/c-c++-common/gomp/reduction-task-1.c.jj	2018-08-01 15:14:14.318166966 +0200
+++ gcc/testsuite/c-c++-common/gomp/reduction-task-1.c	2018-07-31 16:06:16.951634432 +0200
@@ -0,0 +1,86 @@ 
+int v;
+extern void foo (int);
+
+void
+bar (void)
+{
+  int i;
+  #pragma omp for reduction (task, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp sections reduction (task, +: v)
+  {
+    foo (-2);
+    #pragma omp section
+    foo (-3);
+  }
+  #pragma omp parallel reduction (task, +: v)
+  foo (-1);
+  #pragma omp parallel for reduction (task, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp parallel sections reduction (task, +: v)
+  {
+    foo (-2);
+    #pragma omp section
+    foo (-3);
+  }
+  #pragma omp teams distribute parallel for reduction (task, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp for reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp sections reduction (default, +: v)
+  {
+    foo (-2);
+    #pragma omp section
+    foo (-3);
+  }
+  #pragma omp parallel reduction (default, +: v)
+  foo (-1);
+  #pragma omp parallel for reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp parallel sections reduction (default, +: v)
+  {
+    foo (-2);
+    #pragma omp section
+    foo (-3);
+  }
+  #pragma omp teams distribute parallel for reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp for reduction (default, +: v) nowait
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp sections nowait reduction (default, +: v)
+  {
+    foo (-2);
+    #pragma omp section
+    foo (-3);
+  }
+  #pragma omp simd reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp for simd reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp parallel for simd reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp teams distribute parallel for simd reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp taskloop reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp taskloop simd reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp teams reduction (default, +: v)
+  foo (i);
+  #pragma omp teams distribute reduction (default, +: v)
+  for (i = 0; i < 64; i++)
+    foo (i);
+}
--- gcc/testsuite/c-c++-common/gomp/reduction-task-2.c.jj	2018-08-01 15:14:18.040177038 +0200
+++ gcc/testsuite/c-c++-common/gomp/reduction-task-2.c	2018-08-01 14:27:51.320913239 +0200
@@ -0,0 +1,40 @@ 
+int v;
+extern void foo (int);
+
+void
+bar (void)
+{
+  int i;
+  #pragma omp for reduction (task, +: v) nowait	/* { dg-error "'task' reduction modifier on a construct with a 'nowait' clause" } */
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp sections nowait reduction (task, +: v)	/* { dg-error "'task' reduction modifier on a construct with a 'nowait' clause" } */
+  {
+    foo (-2);
+    #pragma omp section
+    foo (-3);
+  }
+  #pragma omp simd reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp for simd reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp parallel for simd reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp teams distribute parallel for simd reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp taskloop reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */
+  for (i = 0; i < 64; i++)
+    foo (i);
+  #pragma omp taskloop simd reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */
+  for (i = 0; i < 64; i++)
+    v++;
+  #pragma omp teams reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */
+  foo (i);
+  #pragma omp teams distribute reduction (task, +: v)	/* { dg-error "invalid 'task' reduction modifier on construct not combined with 'parallel', 'for' or 'sections'" } */
+  for (i = 0; i < 64; i++)
+    foo (i);
+}