public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: gcc-patches@gcc.gnu.org
Subject: [committed] openmp: Add support for omp attributes section and scan directives
Date: Mon, 26 Jul 2021 09:24:48 +0200	[thread overview]
Message-ID: <20210726072448.GS2380545@tucnak> (raw)

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


                 reply	other threads:[~2021-07-26  7:24 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210726072448.GS2380545@tucnak \
    --to=jakub@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).