public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] openmp: Add support for omp attributes section and scan directives
@ 2021-07-26  7:24 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2021-07-26  7:24 UTC (permalink / raw)
  To: gcc-patches

Hi!

This patch adds support for expressing the section and scan directives
using the attribute syntax and additionally fixes some bugs in the attribute
syntax directive handling.
For now it requires that the scan and section directives appear as the only
attribute, not combined with other OpenMP or non-OpenMP attributes on the same
statement.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2021-07-26  Jakub Jelinek  <jakub@redhat.com>

	* parser.h (struct cp_lexer): Add orphan_p member.
	* parser.c (cp_parser_statement): Don't change in_omp_attribute_pragma
	upon restart from CPP_PRAGMA handling.  Fix up condition when a lexer
	should be destroyed and adjust saved_tokens if it records tokens from
	the to be destroyed lexer.
	(cp_parser_omp_section_scan): New function.
	(cp_parser_omp_scan_loop_body): Use it.  If
	parser->lexer->in_omp_attribute_pragma, allow optional comma
	after scan.
	(cp_parser_omp_sections_scope): Use cp_parser_omp_section_scan.

	* g++.dg/gomp/attrs-1.C: Use attribute syntax even for section
	and scan directives.
	* g++.dg/gomp/attrs-2.C: Likewise.
	* g++.dg/gomp/attrs-6.C: New test.
	* g++.dg/gomp/attrs-7.C: New test.
	* g++.dg/gomp/attrs-8.C: New test.

--- gcc/cp/parser.h.jj	2021-07-23 09:37:23.615877596 +0200
+++ gcc/cp/parser.h	2021-07-23 19:17:58.125904410 +0200
@@ -117,6 +117,10 @@ struct GTY (()) cp_lexer {
   /* True if we're in the context of OpenMP directives written as C++11
      attributes turned into pragma.  */
   bool in_omp_attribute_pragma;
+
+  /* True for in_omp_attribute_pragma lexer that should be destroyed
+     when it is no longer in use.  */
+  bool orphan_p;
 };
 
 
--- gcc/cp/parser.c.jj	2021-07-23 09:37:23.619877539 +0200
+++ gcc/cp/parser.c	2021-07-23 19:31:58.739126553 +0200
@@ -11901,10 +11901,9 @@ cp_parser_statement (cp_parser* parser,
   tree statement, std_attrs = NULL_TREE;
   cp_token *token;
   location_t statement_location, attrs_loc;
-  bool in_omp_attribute_pragma;
+  bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
 
  restart:
-  in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
   if (if_p != NULL)
     *if_p = false;
   /* There is no statement yet.  */
@@ -11951,6 +11950,7 @@ cp_parser_statement (cp_parser* parser,
 	     the statement.  */
 	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  in_compound = false;
+	  in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
 	  goto restart;
 
 	case RID_IF:
@@ -12034,6 +12034,7 @@ cp_parser_statement (cp_parser* parser,
 
 	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  in_compound = false;
+	  in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
 	  goto restart;
 	}
     }
@@ -12058,13 +12059,28 @@ cp_parser_statement (cp_parser* parser,
 	cp_parser_pragma (parser, pragma_compound, if_p);
       else if (!cp_parser_pragma (parser, pragma_stmt, if_p))
 	do_restart = true;
-      if (lexer->in_omp_attribute_pragma && !in_omp_attribute_pragma)
-	{
-	  gcc_assert (parser->lexer != lexer);
+      if (parser->lexer != lexer
+	  && lexer->in_omp_attribute_pragma
+	  && (!in_omp_attribute_pragma || lexer->orphan_p))
+	{
+	  if (saved_tokens.lexer == lexer)
+	    {
+	      if (saved_tokens.commit)
+		cp_lexer_commit_tokens (lexer);
+	      gcc_assert (lexer->saved_tokens.length () == saved_tokens.len);
+	      saved_tokens.lexer = parser->lexer;
+	      saved_tokens.commit = false;
+	      saved_tokens.len = parser->lexer->saved_tokens.length ();
+	    }
 	  cp_lexer_destroy (lexer);
+	  lexer = parser->lexer;
 	}
       if (do_restart)
 	goto restart;
+      if (parser->lexer == lexer
+	  && lexer->in_omp_attribute_pragma
+	  && !in_omp_attribute_pragma)
+	parser->lexer->orphan_p = true;
       return;
     }
   else if (token->type == CPP_EOF)
@@ -40775,6 +40791,77 @@ cp_finish_omp_range_for (tree orig, tree
     cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
 }
 
+/* Return true if next tokens contain a standard attribute that contains
+   omp::directive (DIRECTIVE).  */
+
+static bool
+cp_parser_omp_section_scan (cp_parser *parser, const char *directive,
+			    bool tentative)
+{
+  size_t n = cp_parser_skip_attributes_opt (parser, 1), i;
+  if (n < 10)
+    return false;
+  for (i = 5; i < n - 4; i++)
+    if (cp_lexer_nth_token_is (parser->lexer, i, CPP_NAME)
+	&& cp_lexer_nth_token_is (parser->lexer, i + 1, CPP_OPEN_PAREN)
+	&& cp_lexer_nth_token_is (parser->lexer, i + 2, CPP_NAME))
+      {
+	tree first = cp_lexer_peek_nth_token (parser->lexer, i)->u.value;
+	tree second = cp_lexer_peek_nth_token (parser->lexer, i + 2)->u.value;
+	if (strcmp (IDENTIFIER_POINTER (first), "directive"))
+	  continue;
+	if (strcmp (IDENTIFIER_POINTER (second), directive) == 0)
+	  break;
+      }
+  if (i == n - 4)
+    return false;
+  cp_parser_parse_tentatively (parser);
+  location_t first_loc = cp_lexer_peek_token (parser->lexer)->location;
+  location_t last_loc
+    = cp_lexer_peek_nth_token (parser->lexer, n - 1)->location;
+  location_t middle_loc = UNKNOWN_LOCATION;
+  tree std_attrs = cp_parser_std_attribute_spec_seq (parser);
+  int cnt = 0;
+  bool seen = false;
+  for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))
+    if (get_attribute_namespace (attr) == omp_identifier
+	&& is_attribute_p ("directive", get_attribute_name (attr)))
+      {
+	for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a))
+	  {
+	    tree d = TREE_VALUE (a);
+	    gcc_assert (TREE_CODE (d) == DEFERRED_PARSE);
+	    cp_token *first = DEFPARSE_TOKENS (d)->first;
+	    cnt++;
+	    if (first->type == CPP_NAME
+		&& strcmp (IDENTIFIER_POINTER (first->u.value),
+			   directive) == 0)
+	      {
+		seen = true;
+		if (middle_loc == UNKNOWN_LOCATION)
+		  middle_loc = first->location;
+	      }
+	  }
+      }
+  if (!seen || tentative)
+    {
+      cp_parser_abort_tentative_parse (parser);
+      return seen;
+    }
+  if (cnt != 1 || TREE_CHAIN (std_attrs))
+    {
+      error_at (make_location (first_loc, last_loc, middle_loc),
+		"%<[[omp::directive(%s)]]%> must be the only specified "
+		"attribute on a statement", directive);
+      cp_parser_abort_tentative_parse (parser);
+      return false;
+    }
+  if (!cp_parser_parse_definitely (parser))
+    return false;
+  cp_parser_handle_statement_omp_attributes (parser, std_attrs);
+  return true;
+}
+
 /* OpenMP 5.0:
 
    scan-loop-body:
@@ -40793,6 +40880,7 @@ cp_parser_omp_scan_loop_body (cp_parser
   substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
   add_stmt (substmt);
 
+  cp_parser_omp_section_scan (parser, "scan", false);
   cp_token *tok = cp_lexer_peek_token (parser->lexer);
   if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
     {
@@ -40800,6 +40888,10 @@ cp_parser_omp_scan_loop_body (cp_parser
 
       cp_lexer_consume_token (parser->lexer);
 
+      if (parser->lexer->in_omp_attribute_pragma
+	  && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+	cp_lexer_consume_token (parser->lexer);
+
       if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
 	{
 	  tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -41623,7 +41715,8 @@ cp_parser_omp_sections_scope (cp_parser
   stmt = push_stmt_list ();
 
   if (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer))
-      != PRAGMA_OMP_SECTION)
+      != PRAGMA_OMP_SECTION
+      && !cp_parser_omp_section_scan (parser, "section", true))
     {
       substmt = cp_parser_omp_structured_block (parser, NULL, false);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
@@ -41638,6 +41731,8 @@ cp_parser_omp_sections_scope (cp_parser
       if (tok->type == CPP_EOF)
 	break;
 
+      if (cp_parser_omp_section_scan (parser, "section", false))
+	tok = cp_lexer_peek_token (parser->lexer);
       if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SECTION)
 	{
 	  cp_lexer_consume_token (parser->lexer);
--- gcc/testsuite/g++.dg/gomp/attrs-1.C.jj	2021-07-02 21:59:12.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-1.C	2021-07-23 16:08:44.127837193 +0200
@@ -146,17 +146,17 @@ bar (int d, int m, int i1, int i2, int i
     private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread)
     lastprivate (l) allocate (f))]]
   {
-    #pragma omp section
+    [[omp::directive (section)]]
     {}
-    #pragma omp section
+    [[omp::sequence (omp::directive (section))]]
     {}
   }
   [[omp::directive (sections private (p) firstprivate (f) reduction(+:r) lastprivate (l) allocate (f) nowait)]]
   {
     ;
-    #pragma omp section
+    [[omp::sequence (sequence (directive (section)))]]
     ;
-    #pragma omp section
+    [[omp::directive (section)]]
     {}
   }
   [[omp::directive (barrier)]];
@@ -539,14 +539,14 @@ garply (int a, int *c, int *d, int *e, i
   for (i = 0; i < 64; i++)
     {
       d[i] = a;
-      #pragma omp scan exclusive (a)
+      [[omp::directive (scan exclusive (a))]]
       a += c[i];
     }
   [[omp::directive (simd reduction (inscan, +: a))]]
   for (i = 0; i < 64; i++)
     {
       a += c[i];
-      #pragma omp scan inclusive (a)
+      [[omp::sequence (omp::sequence (omp::directive (scan inclusive (a))))]]
       d[i] = a;
     }
   return a;
--- gcc/testsuite/g++.dg/gomp/attrs-2.C.jj	2021-07-02 21:59:12.360171614 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-2.C	2021-07-23 16:22:33.067502407 +0200
@@ -146,17 +146,17 @@ bar (int d, int m, int i1, int i2, int i
     private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread),
     lastprivate (l),allocate (f))]]
   {
-    #pragma omp section
+    [[using omp:directive (section)]]
     {}
-    #pragma omp section
+    [[omp::sequence (omp::directive (section))]]
     {}
   }
   [[omp::directive (sections, private (p),firstprivate (f),reduction(+:r),lastprivate (l),allocate (f),nowait)]]
   {
     ;
-    #pragma omp section
+    [[omp::sequence (sequence (directive (section)))]]
     ;
-    #pragma omp section
+    [[omp::directive (section)]]
     {}
   }
   [[omp::directive (barrier)]];
@@ -539,14 +539,14 @@ garply (int a, int *c, int *d, int *e, i
   for (i = 0; i < 64; i++)
     {
       d[i] = a;
-      #pragma omp scan exclusive (a)
+      [[omp::directive (scan, exclusive (a))]]
       a += c[i];
     }
   [[omp::directive (simd, reduction (inscan, +: a))]]
   for (i = 0; i < 64; i++)
     {
       a += c[i];
-      #pragma omp scan inclusive (a)
+      [[using omp : sequence (sequence (directive (scan inclusive (a))))]]
       d[i] = a;
     }
   return a;
--- gcc/testsuite/g++.dg/gomp/attrs-6.C.jj	2021-07-23 16:32:01.317725952 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-6.C	2021-07-23 16:31:56.084797574 +0200
@@ -0,0 +1,50 @@
+// { dg-do compile { target c++11 } }
+
+void
+foo ()
+{
+  int a[10] = {};
+  #pragma omp parallel sections
+  {
+    #pragma omp section
+    a[0]++;
+    [[omp::directive (section)]] {
+    a[1]++;
+    } [[omp::directive (section)]]
+    a[2]++;
+    #pragma omp section
+    { a[3]++; }
+  }
+  [[omp::directive (parallel sections)]]
+  {
+    #pragma omp section
+    a[0]++;
+    [[omp::directive (section)]] {
+    a[1]++;
+    } [[omp::directive (section)]]
+    a[2]++;
+    #pragma omp section
+    { a[3]++; }
+  }
+}
+
+int
+bar (int a, int *c, int *d, int *e, int *f)
+{
+  int i;
+  #pragma omp simd reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      [[omp::directive (scan, exclusive (a))]]
+      a += c[i];
+    }
+  [[omp::directive (simd reduction (inscan, +: a))]]
+  for (i = 0; i < 64; i++)
+    {
+      a += c[i];
+      #pragma omp scan inclusive (a)
+      d[i] = a;
+    }
+  return a;
+}
--- gcc/testsuite/g++.dg/gomp/attrs-7.C.jj	2021-07-23 16:35:59.784462163 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-7.C	2021-07-23 19:45:29.817340912 +0200
@@ -0,0 +1,64 @@
+// { dg-do compile { target c++11 } }
+
+void
+foo ()
+{
+
+  [[omp::directive (parallel sections)]]
+  {
+    [[omp::directive (parallel)]];
+    [[omp::sequence (directive (section), directive (flush))]];		// { dg-error "must be the only specified attribute on a statement" }
+									// { dg-error "#pragma omp section" "" { target *-*-* } .-1 }
+									// { dg-error "#pragma omp flush" "" { target *-*-* } .-2 }
+    [[omp::sequence (directive (flush), omp::directive (section))]];	// { dg-error "must be the only specified attribute on a statement" }
+									// { dg-error "#pragma omp section" "" { target *-*-* } .-1 }
+									// { dg-error "#pragma omp flush" "" { target *-*-* } .-2 }
+    [[gnu::cold, omp::directive (section)]];				// { dg-error "must be the only specified attribute on a statement" }
+									// { dg-error "#pragma omp section" "" { target *-*-* } .-1 }
+    [[omp::directive (section)]] [[gnu::cold]];				// { dg-error "must be the only specified attribute on a statement" }
+									// { dg-error "#pragma omp section" "" { target *-*-* } .-1 }
+    [[omp::directive (section foo)]];					// { dg-error "expected end of line before 'foo'" }
+  }
+}
+
+int
+bar (int a, int *c, int *d, int *e, int *f)
+{
+  int i;
+  [[omp::directive (parallel for reduction (inscan, +: a))]]				// { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      [[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]]	// { dg-error "must be the only specified attribute on a statement" }
+      a += c[i];									// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+    }
+  [[omp::directive (parallel for reduction (inscan, +: a))]]				// { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
+  for (i = 0; i < 64; i++)
+    {
+      a += c[i];
+      [[omp::sequence (directive (scan inclusive (a)), directive (critical))]]		// { dg-error "must be the only specified attribute on a statement" }
+      d[i] = a;										// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+    }
+  [[omp::directive (parallel for reduction (inscan, +: a))]]				// { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      [[gnu::cold]] [[omp::directive (scan, exclusive (a))]]				// { dg-error "must be the only specified attribute on a statement" }
+      a += c[i];									// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+    }
+  [[omp::directive (parallel for reduction (inscan, +: a))]]				// { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      [[omp::directive (scan, exclusive (a)), gnu::cold]]				// { dg-error "must be the only specified attribute on a statement" }
+      a += c[i];									// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+    }
+  [[omp::directive (parallel for reduction (inscan, +: a))]]				// { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" }
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      [[omp::directive (scan)]]								// { dg-error "expected 'inclusive' or 'exclusive' clause before end of line" }
+      a += c[i];
+    }
+  return a;
+}
--- gcc/testsuite/g++.dg/gomp/attrs-8.C.jj	2021-07-23 17:43:03.524318758 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-8.C	2021-07-23 17:44:13.698356914 +0200
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+
+void
+foo ()
+{
+  // Unsure if this shouldn't be invalid, whether we shouldn't require
+  // that each standalone directive sits on its own empty statement.
+  [[omp::sequence (omp::directive (barrier), omp::directive (barrier))]];
+  [[omp::sequence (omp::directive (taskyield), omp::directive (taskwait))]];
+}

	Jakub


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-26  7:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-26  7:24 [committed] openmp: Add support for omp attributes section and scan directives Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).