public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/omp/gcc-11] openmp: Add support for omp attributes section and scan directives
@ 2021-07-26  8:54 Tobias Burnus
  0 siblings, 0 replies; only message in thread
From: Tobias Burnus @ 2021-07-26  8:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:96bc2486de67841dc80abcd03f15f8ca80396b15

commit 96bc2486de67841dc80abcd03f15f8ca80396b15
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Mon Jul 26 10:46:54 2021 +0200

    openmp: Add support for omp attributes section and scan directives
    
    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.
    
    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.
    
    (cherry picked from commit acf9d1fd806fabf62dfe232439b11263c191e32d)

Diff:
---
 gcc/cp/ChangeLog.omp                |  16 ++++++
 gcc/cp/parser.c                     | 105 ++++++++++++++++++++++++++++++++++--
 gcc/cp/parser.h                     |   4 ++
 gcc/testsuite/ChangeLog.omp         |  12 +++++
 gcc/testsuite/g++.dg/gomp/attrs-1.C |  12 ++---
 gcc/testsuite/g++.dg/gomp/attrs-2.C |  12 ++---
 gcc/testsuite/g++.dg/gomp/attrs-6.C |  50 +++++++++++++++++
 gcc/testsuite/g++.dg/gomp/attrs-7.C |  64 ++++++++++++++++++++++
 gcc/testsuite/g++.dg/gomp/attrs-8.C |  10 ++++
 9 files changed, 268 insertions(+), 17 deletions(-)

diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp
index 9460749112f..9db3e4f26e5 100644
--- a/gcc/cp/ChangeLog.omp
+++ b/gcc/cp/ChangeLog.omp
@@ -1,3 +1,19 @@
+2021-07-26  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backported from master:
+	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.
+
 2021-07-23  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backported from master:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9255bd3519e..955677e15cb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11875,10 +11875,9 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
   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.  */
@@ -11925,6 +11924,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 	     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:
@@ -12008,6 +12008,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
 	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  in_compound = false;
+	  in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
 	  goto restart;
 	}
     }
@@ -12032,13 +12033,28 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 	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)
+      if (parser->lexer != lexer
+	  && lexer->in_omp_attribute_pragma
+	  && (!in_omp_attribute_pragma || lexer->orphan_p))
 	{
-	  gcc_assert (parser->lexer != lexer);
+	  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)
@@ -40672,6 +40688,77 @@ cp_finish_omp_range_for (tree orig, tree begin)
     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:
@@ -40690,6 +40777,7 @@ cp_parser_omp_scan_loop_body (cp_parser *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)
     {
@@ -40697,6 +40785,10 @@ cp_parser_omp_scan_loop_body (cp_parser *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;
@@ -41518,7 +41610,8 @@ cp_parser_omp_sections_scope (cp_parser *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);
@@ -41533,6 +41626,8 @@ cp_parser_omp_sections_scope (cp_parser *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);
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 6fdd214788a..e62742db95d 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -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;
 };
 
 
diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp
index 3a24de74f19..3a1d393c202 100644
--- a/gcc/testsuite/ChangeLog.omp
+++ b/gcc/testsuite/ChangeLog.omp
@@ -1,3 +1,15 @@
+2021-07-26  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backported from master:
+	2021-07-26  Jakub Jelinek  <jakub@redhat.com>
+
+	* 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.
+
 2021-07-23  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backported from master:
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C
index c2734a17c5a..6bbdcac7fba 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-1.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C
@@ -146,17 +146,17 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
     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, int *f)
   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;
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C
index 1eb626330c4..189dc6b1859 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-2.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C
@@ -146,17 +146,17 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
     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, int *f)
   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;
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-6.C b/gcc/testsuite/g++.dg/gomp/attrs-6.C
new file mode 100644
index 00000000000..30b47e1ac15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-6.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-7.C b/gcc/testsuite/g++.dg/gomp/attrs-7.C
new file mode 100644
index 00000000000..598c32ae03f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-7.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-8.C b/gcc/testsuite/g++.dg/gomp/attrs-8.C
new file mode 100644
index 00000000000..30cfe998dcf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-8.C
@@ -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))]];
+}


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

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

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-26  8:54 [gcc/devel/omp/gcc-11] openmp: Add support for omp attributes section and scan directives Tobias Burnus

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