openmp: Add support for OpenMP 5.1 structured-block-sequences
authorJakub Jelinek <jakub@redhat.com>
Sat, 9 Oct 2021 08:14:36 +0000 (10:14 +0200)
committerJakub Jelinek <jakub@redhat.com>
Sat, 9 Oct 2021 08:14:36 +0000 (10:14 +0200)
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).

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

2021-10-09  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.

gcc/c/c-parser.c
gcc/cp/parser.c
gcc/testsuite/c-c++-common/gomp/sections1.c
gcc/testsuite/g++.dg/gomp/attrs-6.C
gcc/testsuite/g++.dg/gomp/attrs-7.C
gcc/testsuite/g++.dg/gomp/sections-2.C
gcc/testsuite/gcc.dg/gomp/sections-2.c
libgomp/libgomp.texi

index a66f43f..869a811 100644 (file)
@@ -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 *parser, bool open_brace_parsed)
       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 *parser, bool open_brace_parsed)
     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, enum pragma_context context,
      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 sections_loc, c_parser *parser)
 
   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 sections_loc, c_parser *parser)
          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);
index c7005eb..0818d66 100644 (file)
@@ -40136,14 +40136,12 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
 }
 
 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 *parser, const char *directive,
   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 *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 *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 *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 *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);
     }
index 8c8ab91..417d205 100644 (file)
@@ -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" } */
 }
index 30b47e1..af8b973 100644 (file)
@@ -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 *f)
       #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;
 }
index cf84281..900ef66 100644 (file)
@@ -29,29 +29,33 @@ bar (int a, int *c, int *d, int *e, int *f)
     {
       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++)
     {
index aabdfaf..6d8305a 100644 (file)
@@ -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);
     }
 }
index aabdfaf..6d8305a 100644 (file)
@@ -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);
     }
 }
index 02160f8..2f61a22 100644 (file)
@@ -291,7 +291,7 @@ The OpenMP 4.5 specification is fully supported.
 @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 supported.
 @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 supported.
 
 @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