diff mbox series

openmp: Add support for OpenMP 5.1 structured-block-sequences

Message ID 20211008161449.GH304296@tucnak
State New
Headers show
Series openmp: Add support for OpenMP 5.1 structured-block-sequences | expand

Commit Message

Jakub Jelinek Oct. 8, 2021, 4:14 p.m. UTC
Hi!

Related to this is the addition of structured-block-sequence in OpenMP 5.1,
which doesn't change anything for Fortran, but for C/C++ allows multiple
statements instead of just one possibly compound around the separating
directives (section and scan).

The following patch implements that, will commit to trunk if it passes
bootstrap/regtest.

I've also made some updates to the OpenMP 5.1 support list in libgomp.texi.

2021-10-08  Jakub Jelinek  <jakub@redhat.com>

gcc/c/
	* c-parser.c (c_parser_omp_structured_block_sequence): New function.
	(c_parser_omp_scan_loop_body): Use it.
	(c_parser_omp_sections_scope): Likewise.
gcc/cp/
	* parser.c (cp_parser_omp_structured_block): Remove disallow_omp_attrs
	argument.
	(cp_parser_omp_structured_block_sequence): New function.
	(cp_parser_omp_scan_loop_body): Use it.
	(cp_parser_omp_sections_scope): Likewise.
gcc/testsuite/
	* c-c++-common/gomp/sections1.c (foo): Don't expect errors on
	multiple statements in between section directive(s).  Add testcases
	for invalid no statements in between section directive(s).
	* gcc.dg/gomp/sections-2.c (foo): Don't expect errors on
	multiple statements in between section directive(s).
	* g++.dg/gomp/sections-2.C (foo): Likewise.
	* g++.dg/gomp/attrs-6.C (foo): Add testcases for multiple
	statements in between section directive(s).
	(bar): Add testcases for multiple statements in between scan
	directive.
	* g++.dg/gomp/attrs-7.C (bar): Adjust expected error recovery.
libgomp/
	* libgomp.texi (OpenMP 5.1): Mention implemented support for
	structured block sequences in C/C++.  Mention support for
	unconstrained/reproducible modifiers on order clause.
	Mention partial (C/C++ only) support of extentensions to atomics
	construct.  Mention partial (C/C++ on clause only) support of
	align/allocator modifiers on allocate clause.



	Jakub
diff mbox series

Patch

--- gcc/c/c-parser.c.jj	2021-10-07 12:52:34.923913144 +0200
+++ gcc/c/c-parser.c	2021-10-08 13:56:43.989987499 +0200
@@ -18976,6 +18976,31 @@  c_parser_omp_flush (c_parser *parser)
   c_finish_omp_flush (loc, mo);
 }
 
+/* Parse an OpenMP structured block sequence.  KIND is the corresponding
+   separating directive.  */
+
+static tree
+c_parser_omp_structured_block_sequence (c_parser *parser,
+					enum pragma_kind kind)
+{
+  tree stmt = push_stmt_list ();
+  c_parser_statement (parser, NULL);
+  do
+    {
+      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+	break;
+      if (c_parser_next_token_is (parser, CPP_EOF))
+	break;
+
+      if (kind != PRAGMA_NONE
+	  && c_parser_peek_token (parser)->pragma_kind == kind)
+	break;
+      c_parser_statement (parser, NULL);
+    }
+  while (1);
+  return pop_stmt_list (stmt);
+}
+
 /* OpenMP 5.0:
 
    scan-loop-body:
@@ -18997,7 +19022,7 @@  c_parser_omp_scan_loop_body (c_parser *p
       return;
     }
 
-  substmt = c_parser_omp_structured_block (parser, NULL);
+  substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
   substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
   SET_EXPR_LOCATION (substmt, loc);
   add_stmt (substmt);
@@ -19032,7 +19057,7 @@  c_parser_omp_scan_loop_body (c_parser *p
     error ("expected %<#pragma omp scan%>");
 
   clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
-  substmt = c_parser_omp_structured_block (parser, NULL);
+  substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
   substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
   SET_EXPR_LOCATION (substmt, loc);
   add_stmt (substmt);
@@ -19860,6 +19885,8 @@  c_parser_omp_ordered (c_parser *parser,
      section-directive[opt] structured-block
      section-sequence section-directive structured-block
 
+   OpenMP 5.1 allows structured-block-sequence instead of structured-block.
+
     SECTIONS_LOC is the location of the #pragma omp sections.  */
 
 static tree
@@ -19881,7 +19908,8 @@  c_parser_omp_sections_scope (location_t
 
   if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
     {
-      substmt = c_parser_omp_structured_block (parser, NULL);
+      substmt = c_parser_omp_structured_block_sequence (parser,
+							PRAGMA_OMP_SECTION);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       SET_EXPR_LOCATION (substmt, loc);
       add_stmt (substmt);
@@ -19907,7 +19935,8 @@  c_parser_omp_sections_scope (location_t
 	  error_suppress = true;
 	}
 
-      substmt = c_parser_omp_structured_block (parser, NULL);
+      substmt = c_parser_omp_structured_block_sequence (parser,
+							PRAGMA_OMP_SECTION);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       SET_EXPR_LOCATION (substmt, loc);
       add_stmt (substmt);
--- gcc/cp/parser.c.jj	2021-10-08 10:58:48.974436064 +0200
+++ gcc/cp/parser.c	2021-10-08 14:07:21.179102547 +0200
@@ -40136,14 +40136,12 @@  cp_parser_end_omp_structured_block (cp_p
 }
 
 static tree
-cp_parser_omp_structured_block (cp_parser *parser, bool *if_p,
-				bool disallow_omp_attrs = true)
+cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
 {
   tree stmt = begin_omp_structured_block ();
   unsigned int save = cp_parser_begin_omp_structured_block (parser);
 
-  if (disallow_omp_attrs)
-    parser->omp_attrs_forbidden_p = true;
+  parser->omp_attrs_forbidden_p = true;
   cp_parser_statement (parser, NULL_TREE, false, if_p);
 
   cp_parser_end_omp_structured_block (parser, save);
@@ -42001,6 +41999,43 @@  cp_parser_omp_section_scan (cp_parser *p
   return true;
 }
 
+/* Parse an OpenMP structured block sequence.  KIND is the corresponding
+   separating directive.  */
+
+static tree
+cp_parser_omp_structured_block_sequence (cp_parser *parser,
+					 enum pragma_kind kind)
+{
+  tree stmt = begin_omp_structured_block ();
+  unsigned int save = cp_parser_begin_omp_structured_block (parser);
+
+  cp_parser_statement (parser, NULL_TREE, false, NULL);
+  while (true)
+    {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+      if (token->type == CPP_CLOSE_BRACE
+	  || token->type == CPP_EOF
+	  || token->type == CPP_PRAGMA_EOL
+	  || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END)
+	  || (kind != PRAGMA_NONE
+	      && cp_parser_pragma_kind (token) == kind))
+	break;
+
+      if (kind != PRAGMA_NONE
+	  && cp_parser_omp_section_scan (parser,
+					 kind == PRAGMA_OMP_SCAN
+					 ? "scan" : "section", false))
+	break;
+
+      cp_parser_statement (parser, NULL_TREE, false, NULL);
+    }
+
+  cp_parser_end_omp_structured_block (parser, save);
+  return finish_omp_structured_block (stmt);
+}
+
+
 /* OpenMP 5.0:
 
    scan-loop-body:
@@ -42015,11 +42050,10 @@  cp_parser_omp_scan_loop_body (cp_parser
   if (!braces.require_open (parser))
     return;
 
-  substmt = cp_parser_omp_structured_block (parser, NULL, false);
+  substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
   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)
     {
@@ -42055,7 +42089,7 @@  cp_parser_omp_scan_loop_body (cp_parser
     error ("expected %<#pragma omp scan%>");
 
   clauses = finish_omp_clauses (clauses, C_ORT_OMP);
-  substmt = cp_parser_omp_structured_block (parser, NULL, false);
+  substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
   substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
 			clauses);
   add_stmt (substmt);
@@ -42924,7 +42958,8 @@  cp_parser_omp_sections_scope (cp_parser
       != PRAGMA_OMP_SECTION
       && !cp_parser_omp_section_scan (parser, "section", true))
     {
-      substmt = cp_parser_omp_structured_block (parser, NULL, false);
+      substmt = cp_parser_omp_structured_block_sequence (parser,
+							 PRAGMA_OMP_SECTION);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
@@ -42951,7 +42986,8 @@  cp_parser_omp_sections_scope (cp_parser
 	  error_suppress = true;
 	}
 
-      substmt = cp_parser_omp_structured_block (parser, NULL, false);
+      substmt = cp_parser_omp_structured_block_sequence (parser,
+							 PRAGMA_OMP_SECTION);
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
--- gcc/testsuite/c-c++-common/gomp/sections1.c.jj	2020-01-12 11:54:37.016404311 +0100
+++ gcc/testsuite/c-c++-common/gomp/sections1.c	2021-10-08 16:10:27.711160436 +0200
@@ -50,7 +50,7 @@  foo ()
   #pragma omp sections
   {
     bar (12);
-    bar (13);			/* { dg-error "pragma omp section" } */
+    bar (13);
     #pragma omp section
     bar (14);
   }
@@ -63,11 +63,29 @@  foo ()
     bar (15);
     #pragma omp section
     bar (16);
-    bar (17);			/* { dg-error "pragma omp section" } */
+    bar (17);
   }
   #pragma omp sections
   {
     bar (18);
     #pragma omp section
   }				/* { dg-error "expression before" } */
+  #pragma omp sections
+  {
+    #pragma omp section
+    #pragma omp section		/* { dg-error "may only be used in" } */
+    bar (19);
+  }
+  #pragma omp sections
+  {
+    bar (20);
+    #pragma omp section
+    #pragma omp section		/* { dg-error "may only be used in" } */
+    bar (21);
+  }
+  #pragma omp sections
+  {
+    bar (22);
+    #pragma omp section
+  }				/* { dg-error "expression before" } */
 }
--- gcc/testsuite/gcc.dg/gomp/sections-2.c.jj	2020-01-11 16:31:55.148291802 +0100
+++ gcc/testsuite/gcc.dg/gomp/sections-2.c	2021-10-08 14:21:41.218108482 +0200
@@ -19,11 +19,11 @@  void foo(void)
     {
     #pragma omp section
       bar(2);
-      bar(3);		// { dg-error "expected" }
+      bar(3);
       bar(4);
     #pragma omp section
       bar(5);
-      bar(6);		// { dg-error "expected" }
+      bar(6);
       bar(7);
     }
 }
--- gcc/testsuite/g++.dg/gomp/sections-2.C.jj	2020-01-11 16:31:54.712298338 +0100
+++ gcc/testsuite/g++.dg/gomp/sections-2.C	2021-10-08 14:45:36.474085819 +0200
@@ -19,11 +19,11 @@  void foo(void)
     {
     #pragma omp section
       bar(2);
-      bar(3);		// { dg-error "expected" }
+      bar(3);
       bar(4);
     #pragma omp section
       bar(5);
-      bar(6);		// { dg-error "expected" }
+      bar(6);
       bar(7);
     }
 }
--- gcc/testsuite/g++.dg/gomp/attrs-6.C.jj	2021-07-27 09:47:44.222778645 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-6.C	2021-10-08 16:07:32.030598778 +0200
@@ -26,6 +26,41 @@  foo ()
     #pragma omp section
     { a[3]++; }
   }
+  #pragma omp parallel sections
+  {
+    #pragma omp section
+    a[0]++;
+    a[4]++;
+    l1: a[5]++;
+    if (a[5] == 42) goto l1;
+    [[omp::directive (section)]] {
+    a[1]++;
+    a[6]++;
+    } [[omp::directive (section)]]
+    a[2]++;
+    a[7]++;
+    #pragma omp section
+    { a[3]++; }
+    a[8]++;
+  }
+  [[omp::directive (parallel sections)]]
+  {
+    #pragma omp section
+    a[0]++;
+    a[4]++;
+    [[omp::directive (section)]] {
+    a[1]++;
+    a[5]++;
+    } [[omp::directive (section)]]
+    a[2]++;
+    l2: a[6]++;
+    if (a[6] == 42)
+      goto l2;
+    a[7]++;
+    #pragma omp section
+    a[8]++;
+    { a[3]++; }
+  }
 }
 
 int
@@ -46,5 +81,23 @@  bar (int a, int *c, int *d, int *e, int
       #pragma omp scan inclusive (a)
       d[i] = a;
     }
+  #pragma omp simd reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      int t = a;
+      d[i] = t;
+      [[omp::directive (scan, exclusive (a))]]
+      int u = c[i];
+      a += u;
+    }
+  [[omp::directive (simd reduction (inscan, +: a))]]
+  for (i = 0; i < 64; i++)
+    {
+      int t = c[i];
+      a += t;
+      #pragma omp scan inclusive (a)
+      int u = a;
+      d[i] = u;
+    }
   return a;
 }
--- gcc/testsuite/g++.dg/gomp/attrs-7.C.jj	2021-08-19 11:42:27.432421468 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-7.C	2021-10-08 17:31:48.432307745 +0200
@@ -29,29 +29,33 @@  bar (int a, int *c, int *d, int *e, int
     {
       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 }
-    }
+											// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+      a += c[i];									// { dg-error "expected" }
+    }											// { dg-error "expected" }
   [[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 }
-    }
+											// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+      d[i] = a;										// { dg-error "expected" }
+    }											// { dg-error "expected" }
   [[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 }
-    }
+											// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+      a += c[i];									// { dg-error "expected" }
+    }											// { dg-error "expected" }
   [[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 }
-    }
+											// { dg-error "#pragma omp scan" "" { target *-*-* } .-1 }
+      a += c[i];									// { dg-error "expected" }
+    }											// { dg-error "expected" }
   [[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++)
     {
--- libgomp/libgomp.texi.jj	2021-09-30 17:12:15.238586878 +0200
+++ libgomp/libgomp.texi	2021-10-08 17:46:36.021964258 +0200
@@ -291,7 +291,7 @@  The OpenMP 4.5 specification is fully su
 @item @code{strict} modifier in the @code{grainsize} and @code{num_tasks}
       clauses of the taskloop construct @tab Y @tab
 @item @code{align} clause/modifier in @code{allocate} directive/clause
-      and @code{allocator} directive @tab N @tab
+      and @code{allocator} directive @tab P @tab C/C++ on clause only
 @item @code{thread_limit} clause to @code{target} construct @tab N @tab
 @item @code{has_device_addr} clause to @code{target} construct @tab N @tab
 @item iterators in @code{target update} motion clauses and @code{map}
@@ -301,7 +301,7 @@  The OpenMP 4.5 specification is fully su
 @item @code{interop} directive @tab N @tab
 @item @code{omp_interop_t} object support in runtime routines @tab N @tab
 @item @code{nowait} clause in @code{taskwait} directive @tab N @tab
-@item Extensions to the @code{atomic} directive @tab N @tab
+@item Extensions to the @code{atomic} directive @tab P @tab C/C++ only
 @item @code{seq_cst} clause on a @code{flush} construct @tab Y @tab
 @item @code{inoutset} argument to the @code{depend} clause @tab N @tab
 @item @code{private} and @code{firstprivate} argument to @code{default}
@@ -337,7 +337,10 @@  The OpenMP 4.5 specification is fully su
 
 @multitable @columnfractions .60 .10 .25
 @headitem Description @tab Status @tab Comments
-@item Suppport of strictly structured blocks in Fortran @tab N @tab
+@item Support of strictly structured blocks in Fortran @tab N @tab
+@item Support of structured block sequences in C/C++ @tab Y @tab
+@item @code{unconstrained} and @code{reproducible} modifiers on @code{order}
+      clause @tab Y @tab
 @end multitable