]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Implement OpenMP 5.1 scope construct
authorJakub Jelinek <jakub@redhat.com>
Tue, 17 Aug 2021 13:44:56 +0000 (15:44 +0200)
committerTobias Burnus <tobias@codesourcery.com>
Tue, 17 Aug 2021 13:44:56 +0000 (15:44 +0200)
This patch implements the OpenMP 5.1 scope construct, which is similar
to worksharing constructs in many regards, but isn't one of them.
The body of the construct is encountered by all threads though, it can
be nested in itself or intermixed with taskgroup and worksharing etc.
constructs can appear inside of it (but it can't be nested in
worksharing etc. constructs).  The main purpose of the construct
is to allow reductions (normal and task ones) without the need to
close the parallel and reopen another one.

If it doesn't have task reductions, it can be implemented without
any new library support, with nowait it just does the privatizations
at the start if any and reductions before the end of the body, with
without nowait emits a normal GOMP_barrier{,_cancel} at the end too.

For task reductions, we need to ensure only one thread initializes
the task reduction library data structures and other threads copy from that,
so a new GOMP_scope_start routine is added to the library for that.
It acts as if the start of the scope construct is a nowait worksharing
construct (that is ok, it can't be nested in other worksharing
constructs and all threads need to encounter the start in the same
order) which does the task reduction initialization, but as the body
can have other scope constructs and/or worksharing constructs, that is
all where we use this dummy worksharing construct.  With task reductions,
the construct must not have nowait and ends with a GOMP_barrier{,_cancel},
followed by task reductions followed by GOMP_workshare_task_reduction_unregister.

Only C/C++ FE support is done.

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

gcc/
* tree.def (OMP_SCOPE): New tree code.
* tree.h (OMP_SCOPE_BODY, OMP_SCOPE_CLAUSES): Define.
* tree-nested.c (convert_nonlocal_reference_stmt,
convert_local_reference_stmt, convert_gimple_call): Handle
GIMPLE_OMP_SCOPE.
* tree-pretty-print.c (dump_generic_node): Handle OMP_SCOPE.
* gimple.def (GIMPLE_OMP_SCOPE): New gimple code.
* gimple.c (gimple_build_omp_scope): New function.
(gimple_copy): Handle GIMPLE_OMP_SCOPE.
* gimple.h (gimple_build_omp_scope): Declare.
(gimple_has_substatements): Handle GIMPLE_OMP_SCOPE.
(gimple_omp_scope_clauses, gimple_omp_scope_clauses_ptr,
gimple_omp_scope_set_clauses): New inline functions.
(CASE_GIMPLE_OMP): Add GIMPLE_OMP_SCOPE.
* gimple-pretty-print.c (dump_gimple_omp_scope): New function.
(pp_gimple_stmt_1): Handle GIMPLE_OMP_SCOPE.
* gimple-walk.c (walk_gimple_stmt): Likewise.
* gimple-low.c (lower_stmt): Likewise.
* gimplify.c (is_gimple_stmt): Handle OMP_MASTER.
(gimplify_scan_omp_clauses): For task reductions, handle OMP_SCOPE
like ORT_WORKSHARE constructs.  Adjust diagnostics for %<scope%>
allowing task reductions.  Reject inscan reductions on scope.
(omp_find_stores_stmt): Handle GIMPLE_OMP_SCOPE.
(gimplify_omp_workshare, gimplify_expr): Handle OMP_SCOPE.
* tree-inline.c (remap_gimple_stmt): Handle GIMPLE_OMP_SCOPE.
(estimate_num_insns): Likewise.
* omp-low.c (build_outer_var_ref): Look through GIMPLE_OMP_SCOPE
contexts if var isn't privatized there.
(check_omp_nesting_restrictions): Handle GIMPLE_OMP_SCOPE.
(scan_omp_1_stmt): Likewise.
(maybe_add_implicit_barrier_cancel): Look through outer
scope constructs.
(lower_omp_scope): New function.
(lower_omp_task_reductions): Handle OMP_SCOPE.
(lower_omp_1): Handle GIMPLE_OMP_SCOPE.
(diagnose_sb_1, diagnose_sb_2): Likewise.
* omp-expand.c (expand_omp_single): Support also GIMPLE_OMP_SCOPE.
(expand_omp): Handle GIMPLE_OMP_SCOPE.
(omp_make_gimple_edges): Likewise.
* omp-builtins.def (BUILT_IN_GOMP_SCOPE_START): New built-in.
gcc/c-family/
* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCOPE.
* c-pragma.c (omp_pragmas): Add scope construct.
* c-omp.c (omp_directives): Uncomment scope directive entry.
gcc/c/
* c-parser.c (OMP_SCOPE_CLAUSE_MASK): Define.
(c_parser_omp_scope): New function.
(c_parser_omp_construct): Handle PRAGMA_OMP_SCOPE.
gcc/cp/
* parser.c (OMP_SCOPE_CLAUSE_MASK): Define.
(cp_parser_omp_scope): New function.
(cp_parser_omp_construct, cp_parser_pragma): Handle PRAGMA_OMP_SCOPE.
* pt.c (tsubst_expr): Handle OMP_SCOPE.
gcc/testsuite/
* c-c++-common/gomp/nesting-2.c (foo): Add scope and masked
construct tests.
* c-c++-common/gomp/scan-1.c (f3): Add scope construct test..
* c-c++-common/gomp/cancel-1.c (f2): Add scope and masked
construct tests.
* c-c++-common/gomp/reduction-task-2.c (bar): Add scope construct
test.  Adjust diagnostics for the addition of scope.
* c-c++-common/gomp/loop-1.c (f5): Add master, masked and scope
construct tests.
* c-c++-common/gomp/clause-dups-1.c (f1): Add scope construct test.
* gcc.dg/gomp/nesting-1.c (f1, f2, f3): Add scope construct tests.
* c-c++-common/gomp/scope-1.c: New test.
* c-c++-common/gomp/scope-2.c: New test.
* g++.dg/gomp/attrs-1.C (bar): Add scope construct tests.
* g++.dg/gomp/attrs-2.C (bar): Likewise.
* gfortran.dg/gomp/reduction4.f90: Adjust expected diagnostics.
* gfortran.dg/gomp/reduction7.f90: Likewise.
libgomp/
* Makefile.am (libgomp_la_SOURCES): Add scope.c
* Makefile.in: Regenerated.
* libgomp_g.h (GOMP_scope_start): Declare.
* libgomp.map: Add GOMP_scope_start@@GOMP_5.1.
* scope.c: New file.
* testsuite/libgomp.c-c++-common/scope-1.c: New test.
* testsuite/libgomp.c-c++-common/task-reduction-16.c: New test.

(cherry picked from commit e45483c7c4badc4bf2d6ced22360ce1ab172967f)

47 files changed:
gcc/ChangeLog.omp
gcc/c-family/ChangeLog.omp
gcc/c-family/c-omp.c
gcc/c-family/c-pragma.c
gcc/c-family/c-pragma.h
gcc/c/ChangeLog.omp
gcc/c/c-parser.c
gcc/cp/ChangeLog.omp
gcc/cp/parser.c
gcc/cp/pt.c
gcc/gimple-low.c
gcc/gimple-pretty-print.c
gcc/gimple-walk.c
gcc/gimple.c
gcc/gimple.def
gcc/gimple.h
gcc/gimplify.c
gcc/omp-builtins.def
gcc/omp-expand.c
gcc/omp-low.c
gcc/testsuite/ChangeLog.omp
gcc/testsuite/c-c++-common/gomp/cancel-1.c
gcc/testsuite/c-c++-common/gomp/clause-dups-1.c
gcc/testsuite/c-c++-common/gomp/loop-1.c
gcc/testsuite/c-c++-common/gomp/nesting-2.c
gcc/testsuite/c-c++-common/gomp/reduction-task-2.c
gcc/testsuite/c-c++-common/gomp/scan-1.c
gcc/testsuite/c-c++-common/gomp/scope-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/scope-2.c [new file with mode: 0644]
gcc/testsuite/g++.dg/gomp/attrs-1.C
gcc/testsuite/g++.dg/gomp/attrs-2.C
gcc/testsuite/gcc.dg/gomp/nesting-1.c
gcc/testsuite/gfortran.dg/gomp/reduction4.f90
gcc/testsuite/gfortran.dg/gomp/reduction7.f90
gcc/tree-inline.c
gcc/tree-nested.c
gcc/tree-pretty-print.c
gcc/tree.def
gcc/tree.h
libgomp/ChangeLog.omp
libgomp/Makefile.am
libgomp/Makefile.in
libgomp/libgomp.map
libgomp/libgomp_g.h
libgomp/scope.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c-c++-common/scope-1.c [new file with mode: 0644]
libgomp/testsuite/libgomp.c-c++-common/task-reduction-16.c [new file with mode: 0644]

index 3005c0227f156d94f75b6c0f0ce1795561fb7e97..c19452723615c34b5bb46cec6376c4890c9c8141 100644 (file)
@@ -1,3 +1,49 @@
+2021-08-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree.def (OMP_SCOPE): New tree code.
+       * tree.h (OMP_SCOPE_BODY, OMP_SCOPE_CLAUSES): Define.
+       * tree-nested.c (convert_nonlocal_reference_stmt,
+       convert_local_reference_stmt, convert_gimple_call): Handle
+       GIMPLE_OMP_SCOPE.
+       * tree-pretty-print.c (dump_generic_node): Handle OMP_SCOPE.
+       * gimple.def (GIMPLE_OMP_SCOPE): New gimple code.
+       * gimple.c (gimple_build_omp_scope): New function.
+       (gimple_copy): Handle GIMPLE_OMP_SCOPE.
+       * gimple.h (gimple_build_omp_scope): Declare.
+       (gimple_has_substatements): Handle GIMPLE_OMP_SCOPE.
+       (gimple_omp_scope_clauses, gimple_omp_scope_clauses_ptr,
+       gimple_omp_scope_set_clauses): New inline functions.
+       (CASE_GIMPLE_OMP): Add GIMPLE_OMP_SCOPE.
+       * gimple-pretty-print.c (dump_gimple_omp_scope): New function.
+       (pp_gimple_stmt_1): Handle GIMPLE_OMP_SCOPE.
+       * gimple-walk.c (walk_gimple_stmt): Likewise.
+       * gimple-low.c (lower_stmt): Likewise.
+       * gimplify.c (is_gimple_stmt): Handle OMP_MASTER.
+       (gimplify_scan_omp_clauses): For task reductions, handle OMP_SCOPE
+       like ORT_WORKSHARE constructs.  Adjust diagnostics for %<scope%>
+       allowing task reductions.  Reject inscan reductions on scope.
+       (omp_find_stores_stmt): Handle GIMPLE_OMP_SCOPE.
+       (gimplify_omp_workshare, gimplify_expr): Handle OMP_SCOPE.
+       * tree-inline.c (remap_gimple_stmt): Handle GIMPLE_OMP_SCOPE.
+       (estimate_num_insns): Likewise.
+       * omp-low.c (build_outer_var_ref): Look through GIMPLE_OMP_SCOPE
+       contexts if var isn't privatized there.
+       (check_omp_nesting_restrictions): Handle GIMPLE_OMP_SCOPE.
+       (scan_omp_1_stmt): Likewise.
+       (maybe_add_implicit_barrier_cancel): Look through outer
+       scope constructs.
+       (lower_omp_scope): New function.
+       (lower_omp_task_reductions): Handle OMP_SCOPE.
+       (lower_omp_1): Handle GIMPLE_OMP_SCOPE.
+       (diagnose_sb_1, diagnose_sb_2): Likewise.
+       * omp-expand.c (expand_omp_single): Support also GIMPLE_OMP_SCOPE.
+       (expand_omp): Handle GIMPLE_OMP_SCOPE.
+       (omp_make_gimple_edges): Likewise.
+       * omp-builtins.def (BUILT_IN_GOMP_SCOPE_START): New built-in.
+
 2021-08-16  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 31b8534d8f2e16be9f8da8c33e960fcafb9e3846..2258b025529f6ec7bab22c992fb6f2cc2ca48231 100644 (file)
@@ -1,3 +1,12 @@
+2021-08-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCOPE.
+       * c-pragma.c (omp_pragmas): Add scope construct.
+       * c-omp.c (omp_directives): Uncomment scope directive entry.
+
 2021-08-16  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index a70aec9f151f41d8a854e675283cd763300af41b..5dce7fb988c10fc7efa4c8629939a16c2a4b1a21 100644 (file)
@@ -3802,8 +3802,8 @@ static const struct c_omp_directive omp_directives[] = {
     C_OMP_DIR_INFORMATIONAL, false },
   { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
     C_OMP_DIR_CONSTRUCT, true },
-  /* { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
-    C_OMP_DIR_CONSTRUCT, false },  */
+  { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
+    C_OMP_DIR_CONSTRUCT, false },
   { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
     C_OMP_DIR_CONSTRUCT, false },
   { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
index 338c56fbd3a6839d5128073c1cff6525c3de1f87..9c555855dc4b5341a274b401d805fa02c7f5f6f1 100644 (file)
@@ -1319,6 +1319,7 @@ static const struct omp_pragma_def omp_pragmas[] = {
   { "end", PRAGMA_OMP_END_DECLARE_TARGET },
   { "flush", PRAGMA_OMP_FLUSH },
   { "requires", PRAGMA_OMP_REQUIRES },
+  { "scope", PRAGMA_OMP_SCOPE },
   { "section", PRAGMA_OMP_SECTION },
   { "sections", PRAGMA_OMP_SECTIONS },
   { "single", PRAGMA_OMP_SINGLE },
index b7ec6e5d5474f11fcd9c34ff6c645babda11ad9d..2b9e5eac675a5af98f76f3dd996c5775a2e5ef94 100644 (file)
@@ -63,6 +63,7 @@ enum pragma_kind {
   PRAGMA_OMP_PARALLEL,
   PRAGMA_OMP_REQUIRES,
   PRAGMA_OMP_SCAN,
+  PRAGMA_OMP_SCOPE,
   PRAGMA_OMP_SECTION,
   PRAGMA_OMP_SECTIONS,
   PRAGMA_OMP_SIMD,
index 56004986d44ba1ab7818250df40e18a182372568..3b6bd7bdfc2684854cd1bc39101be97f3b9ab021 100644 (file)
@@ -1,3 +1,12 @@
+2021-08-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-parser.c (OMP_SCOPE_CLAUSE_MASK): Define.
+       (c_parser_omp_scope): New function.
+       (c_parser_omp_construct): Handle PRAGMA_OMP_SCOPE.
+
 2021-08-16  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index c4dc5f83c12223a4d3b9591a65eaeacad1bab426..249d88eb945fc0247affcd24f83129587535aaa2 100644 (file)
@@ -19511,6 +19511,33 @@ c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
   return add_stmt (stmt);
 }
 
+/* OpenMP 5.1:
+   # pragma omp scope scope-clause[optseq] new-line
+     structured-block
+
+   LOC is the location of the #pragma.
+*/
+
+#define OMP_SCOPE_CLAUSE_MASK                                  \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
+{
+  tree stmt = make_node (OMP_SCOPE);
+  SET_EXPR_LOCATION (stmt, loc);
+  TREE_TYPE (stmt) = void_type_node;
+
+  OMP_SCOPE_CLAUSES (stmt)
+    = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
+                               "#pragma omp scope");
+  OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
+
+  return add_stmt (stmt);
+}
+
 /* OpenMP 3.0:
    # pragma omp task task-clause[optseq] new-line
 
@@ -21979,6 +22006,9 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
       strcpy (p_name, "#pragma omp");
       stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
       break;
+    case PRAGMA_OMP_SCOPE:
+      stmt = c_parser_omp_scope (loc, parser, if_p);
+      break;
     case PRAGMA_OMP_SECTIONS:
       strcpy (p_name, "#pragma omp");
       stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
index 0df480e861bb04b41ddfef4db2cf12ee774df1fa..8a367bfc84ed44c179a05a847f642a0668b113e2 100644 (file)
@@ -1,3 +1,13 @@
+2021-08-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * parser.c (OMP_SCOPE_CLAUSE_MASK): Define.
+       (cp_parser_omp_scope): New function.
+       (cp_parser_omp_construct, cp_parser_pragma): Handle PRAGMA_OMP_SCOPE.
+       * pt.c (tsubst_expr): Handle OMP_SCOPE.
+
 2021-08-16  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 83eabf1793cc58c2a375669a9c286b8bde22a2e1..15f9cc76dddd5e65c28e49abd167691fe6dc142a 100644 (file)
@@ -42327,6 +42327,30 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
   return add_stmt (stmt);
 }
 
+/* OpenMP 5.1:
+   # pragma omp scope scope-clause[optseq] new-line
+     structured-block  */
+
+#define OMP_SCOPE_CLAUSE_MASK                                  \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+cp_parser_omp_scope (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
+{
+  tree stmt = make_node (OMP_SCOPE);
+  TREE_TYPE (stmt) = void_type_node;
+  SET_EXPR_LOCATION (stmt, pragma_tok->location);
+
+  OMP_SCOPE_CLAUSES (stmt)
+    = cp_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
+                                "#pragma omp scope", pragma_tok);
+  OMP_SCOPE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
+
+  return add_stmt (stmt);
+}
+
 /* OpenMP 3.0:
    # pragma omp task task-clause[optseq] new-line
      structured-block  */
@@ -45765,6 +45789,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
       stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL,
                                     if_p);
       break;
+    case PRAGMA_OMP_SCOPE:
+      stmt = cp_parser_omp_scope (parser, pragma_tok, if_p);
+      break;
     case PRAGMA_OMP_SECTIONS:
       strcpy (p_name, "#pragma omp");
       stmt = cp_parser_omp_sections (parser, pragma_tok, p_name, mask, NULL);
@@ -46398,6 +46425,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
     case PRAGMA_OMP_MASKED:
     case PRAGMA_OMP_MASTER:
     case PRAGMA_OMP_PARALLEL:
+    case PRAGMA_OMP_SCOPE:
     case PRAGMA_OMP_SECTIONS:
     case PRAGMA_OMP_SIMD:
     case PRAGMA_OMP_SINGLE:
index c1daada0a1b456b6b31e993195674f4a4f98de97..0e87e346e45617baf389ba1af927080e9614d104 100644 (file)
@@ -18863,6 +18863,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       omp_parallel_combined_clauses = NULL;
       /* FALLTHRU */
     case OMP_SINGLE:
+    case OMP_SCOPE:
     case OMP_TEAMS:
     case OMP_CRITICAL:
     case OMP_TASKGROUP:
index 832d5c3721c8cf01cb3c4a101af8473a059c0faf..7e39c22df4411db5cb2dfb9d54b8f57f9960b595 100644 (file)
@@ -329,6 +329,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
     case GIMPLE_LABEL:
     case GIMPLE_EH_MUST_NOT_THROW:
     case GIMPLE_OMP_FOR:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SECTIONS_SWITCH:
     case GIMPLE_OMP_SECTION:
index 80aca691f6b846d3175ee9f23f6819318d8ca344..c38a016fa29035454467d94bb9bb64f4bed89496 100644 (file)
@@ -1686,6 +1686,35 @@ dump_gimple_omp_masked (pretty_printer *buffer, const gimple *gs,
     }
 }
 
+/* Dump a GIMPLE_OMP_SCOPE tuple on the pretty_printer BUFFER.  */
+
+static void
+dump_gimple_omp_scope (pretty_printer *buffer, const gimple *gs,
+                      int spc, dump_flags_t flags)
+{
+  if (flags & TDF_RAW)
+    {
+      dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
+                      gimple_omp_body (gs));
+      dump_omp_clauses (buffer, gimple_omp_scope_clauses (gs), spc, flags);
+      dump_gimple_fmt (buffer, spc, flags, " >");
+    }
+  else
+    {
+      pp_string (buffer, "#pragma omp scope");
+      dump_omp_clauses (buffer, gimple_omp_scope_clauses (gs), spc, flags);
+      if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+       {
+         newline_and_indent (buffer, spc + 2);
+         pp_left_brace (buffer);
+         pp_newline (buffer);
+         dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+         newline_and_indent (buffer, spc + 2);
+         pp_right_brace (buffer);
+       }
+    }
+}
+
 /* Dump a GIMPLE_OMP_TARGET tuple on the pretty_printer BUFFER.  */
 
 static void
@@ -2742,6 +2771,10 @@ pp_gimple_stmt_1 (pretty_printer *buffer, const gimple *gs, int spc,
       dump_gimple_omp_masked (buffer, gs, spc, flags);
       break;
 
+    case GIMPLE_OMP_SCOPE:
+      dump_gimple_omp_scope (buffer, gs, spc, flags);
+      break;
+
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_SECTION:
       dump_gimple_omp_block (buffer, gs, spc, flags);
index 7ba458c54fcd0900ba577d1348aafab12a51b6e9..cd287860994e90d0b06861bda632f25bb80d3aa2 100644 (file)
@@ -689,6 +689,7 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
     case GIMPLE_OMP_TARGET:
index e9892d6ae1806d438f9298a9b61aeeeecbd5cfc9..e6c52f013cd26ed4b9ddfc383b64bbdaa7972bb7 100644 (file)
@@ -1185,6 +1185,24 @@ gimple_build_omp_single (gimple_seq body, tree clauses)
 }
 
 
+/* Build a GIMPLE_OMP_SCOPE statement.
+
+   BODY is the sequence of statements that will be executed once.
+   CLAUSES are any of the OMP scope construct's clauses: private, reduction,
+   nowait.  */
+
+gimple *
+gimple_build_omp_scope (gimple_seq body, tree clauses)
+{
+  gimple *p = gimple_alloc (GIMPLE_OMP_SCOPE, 0);
+  gimple_omp_scope_set_clauses (p, clauses);
+  if (body)
+    gimple_omp_set_body (p, body);
+
+  return p;
+}
+
+
 /* Build a GIMPLE_OMP_TARGET statement.
 
    BODY is the sequence of statements that will be executed.
@@ -2020,6 +2038,11 @@ gimple_copy (gimple *stmt)
          }
          goto copy_omp_body;
 
+       case GIMPLE_OMP_SCOPE:
+         t = unshare_expr (gimple_omp_scope_clauses (stmt));
+         gimple_omp_scope_set_clauses (copy, t);
+         goto copy_omp_body;
+
        case GIMPLE_OMP_TARGET:
          {
            gomp_target *omp_target_stmt = as_a <gomp_target *> (stmt);
index e66546c6be3d1e5f2d9c9467bb5ee59bfb35e12e..193b2506523dff716cfca5e297064e3e5d729b53 100644 (file)
@@ -340,6 +340,11 @@ DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
    CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
 DEFGSCODE(GIMPLE_OMP_SCAN, "gimple_omp_scan", GSS_OMP_SINGLE_LAYOUT)
 
+/* GIMPLE_OMP_SCOPE <BODY, CLAUSES> represents #pragma omp scope
+   BODY is the sequence of statements inside the single section.
+   CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
+DEFGSCODE(GIMPLE_OMP_SCOPE, "gimple_omp_scope", GSS_OMP_SINGLE_LAYOUT)
+
 /* OMP_SECTION <BODY> represents #pragma omp section.
    BODY is the sequence of statements in the section body.  */
 DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_omp_section", GSS_OMP)
index 5ba7f14221cb781c4f80eb46a2fd867a2f7eba2f..b85bc0b504fd45f933cdead0fadb018dc36148f9 100644 (file)
@@ -741,7 +741,7 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
 };
 
 /* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP,
-   GIMPLE_OMP_SCAN.  */
+   GIMPLE_OMP_SCAN, GIMPLE_OMP_MASKED, GIMPLE_OMP_SCOPE.  */
 
 struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
   gimple_statement_omp_single_layout : public gimple_statement_omp
@@ -1558,6 +1558,7 @@ gomp_parallel *gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
 gomp_task *gimple_build_omp_task (gimple_seq, tree, tree, tree, tree,
                                       tree, tree);
 gimple *gimple_build_omp_section (gimple_seq);
+gimple *gimple_build_omp_scope (gimple_seq, tree);
 gimple *gimple_build_omp_master (gimple_seq);
 gimple *gimple_build_omp_masked (gimple_seq, tree);
 gimple *gimple_build_omp_taskgroup (gimple_seq, tree);
@@ -1824,6 +1825,7 @@ gimple_has_substatements (gimple *g)
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
     case GIMPLE_OMP_TARGET:
@@ -5185,7 +5187,7 @@ gimple_omp_taskgroup_set_clauses (gimple *gs, tree clauses)
 }
 
 
-/* Return the clauses associated with OMP_MASTER statement GS.  */
+/* Return the clauses associated with OMP_MASKED statement GS.  */
 
 static inline tree
 gimple_omp_masked_clauses (const gimple *gs)
@@ -5219,6 +5221,40 @@ gimple_omp_masked_set_clauses (gimple *gs, tree clauses)
 }
 
 
+/* Return the clauses associated with OMP_SCOPE statement GS.  */
+
+static inline tree
+gimple_omp_scope_clauses (const gimple *gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_OMP_SCOPE);
+  return
+    static_cast <const gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP scope statement
+   GS.  */
+
+static inline tree *
+gimple_omp_scope_clauses_ptr (gimple *gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_OMP_SCOPE);
+  return &static_cast <gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP scope statement
+   GS.  */
+
+static inline void
+gimple_omp_scope_set_clauses (gimple *gs, tree clauses)
+{
+  GIMPLE_CHECK (gs, GIMPLE_OMP_SCOPE);
+  static_cast <gimple_statement_omp_single_layout *> (gs)->clauses
+    = clauses;
+}
+
+
 /* Return the kind of the OMP_FOR statemement G.  */
 
 static inline int
@@ -6505,6 +6541,7 @@ gimple_return_set_retval (greturn *gs, tree retval)
     case GIMPLE_OMP_SINGLE:                    \
     case GIMPLE_OMP_TARGET:                    \
     case GIMPLE_OMP_TEAMS:                     \
+    case GIMPLE_OMP_SCOPE:                     \
     case GIMPLE_OMP_SECTION:                   \
     case GIMPLE_OMP_MASTER:                    \
     case GIMPLE_OMP_MASKED:                    \
index be2fd03a46f9d9aeb0f717da970bf3e1867dd716..4e16a8f1390d11fd2a951ca308fb7d0844822d20 100644 (file)
@@ -5669,6 +5669,7 @@ is_gimple_stmt (tree t)
     case OMP_LOOP:
     case OACC_LOOP:
     case OMP_SCAN:
+    case OMP_SCOPE:
     case OMP_SECTIONS:
     case OMP_SECTION:
     case OMP_SINGLE:
@@ -9632,7 +9633,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
        case OMP_CLAUSE_REDUCTION:
          if (OMP_CLAUSE_REDUCTION_TASK (c))
            {
-             if (region_type == ORT_WORKSHARE)
+             if (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
                {
                  if (nowait == -1)
                    nowait = omp_find_clause (*list_p,
@@ -9651,8 +9652,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
                {
                  error_at (OMP_CLAUSE_LOCATION (c),
                            "invalid %<task%> reduction modifier on construct "
-                           "other than %<parallel%>, %qs or %<sections%>",
-                           lang_GNU_Fortran () ? "do" : "for");
+                           "other than %<parallel%>, %qs, %<sections%> or "
+                           "%<scope%>", lang_GNU_Fortran () ? "do" : "for");
                  OMP_CLAUSE_REDUCTION_TASK (c) = 0;
                }
            }
@@ -9683,6 +9684,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
                          "%qs construct", "taskloop");
                OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
                break;
+             case OMP_SCOPE:
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%<inscan%> %<reduction%> clause on "
+                         "%qs construct", "scope");
+               OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+               break;
              default:
                break;
              }
@@ -11066,6 +11073,7 @@ omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
     case GIMPLE_OMP_TASK:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_TARGET:
     case GIMPLE_OMP_TEAMS:
     case GIMPLE_OMP_CRITICAL:
@@ -14240,6 +14248,9 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
     case OMP_SINGLE:
       ort = ORT_WORKSHARE;
       break;
+    case OMP_SCOPE:
+      ort = ORT_TASKGROUP;
+      break;
     case OMP_TARGET:
       ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET;
       break;
@@ -14357,6 +14368,9 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
     case OMP_SINGLE:
       stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
       break;
+    case OMP_SCOPE:
+      stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
+      break;
     case OMP_TARGET:
       stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
                                      OMP_CLAUSES (expr));
@@ -15626,6 +15640,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        case OACC_KERNELS:
        case OACC_PARALLEL:
        case OACC_SERIAL:
+       case OMP_SCOPE:
        case OMP_SECTIONS:
        case OMP_SINGLE:
        case OMP_TARGET:
@@ -16058,7 +16073,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  && code != OMP_SCAN
                  && code != OMP_SECTIONS
                  && code != OMP_SECTION
-                 && code != OMP_SINGLE);
+                 && code != OMP_SINGLE
+                 && code != OMP_SCOPE);
     }
 #endif
 
index c6d7a4749b11e73819956da3bc46d18c85edeb6c..48b1c475de2af7dbcb3f46dd35a0e13087162917 100644 (file)
@@ -414,6 +414,8 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_START, "GOMP_single_copy_start",
                  BT_FN_PTR, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_END, "GOMP_single_copy_end",
                  BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SCOPE_START, "GOMP_scope_start",
+                 BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOACC_BUILTIN (BUILT_IN_GOACC_SINGLE_START, "GOACC_single_start",
                   BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOACC_BUILTIN (BUILT_IN_GOACC_SINGLE_COPY_START, "GOACC_single_copy_start",
index 98133d0fe68994d994058ae61550e4500ccdf73e..252ca2c2c0521e329065aec4f52b37e435c47c6d 100644 (file)
@@ -8464,7 +8464,7 @@ expand_omp_sections (struct omp_region *region)
   set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
 }
 
-/* Expand code for an OpenMP single directive.  We've already expanded
+/* Expand code for an OpenMP single or scope directive.  We've already expanded
    much of the code, here we simply place the GOMP_barrier call.  */
 
 static void
@@ -8477,7 +8477,8 @@ expand_omp_single (struct omp_region *region)
   exit_bb = region->exit;
 
   si = gsi_last_nondebug_bb (entry_bb);
-  gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
+  gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
+             || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SCOPE);
   gsi_remove (&si, true);
   single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
 
@@ -9991,6 +9992,7 @@ expand_omp (struct omp_region *region)
          break;
 
        case GIMPLE_OMP_SINGLE:
+       case GIMPLE_OMP_SCOPE:
          expand_omp_single (region);
          break;
 
@@ -10331,6 +10333,7 @@ omp_make_gimple_edges (basic_block bb, struct omp_region **region,
     case GIMPLE_OMP_TEAMS:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_MASKED:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_OMP_SECTION:
index 77bac25148898bdb4a56fd7833dcae7ce6459564..a6dee01d6b5f55c129bb3840871c66fff49c9c62 100644 (file)
@@ -665,8 +665,15 @@ build_outer_var_ref (tree var, omp_context *ctx,
 {
   tree x;
   omp_context *outer = ctx->outer;
-  while (outer && gimple_code (outer->stmt) == GIMPLE_OMP_TASKGROUP)
-    outer = outer->outer;
+  for (; outer; outer = outer->outer)
+    {
+      if (gimple_code (outer->stmt) == GIMPLE_OMP_TASKGROUP)
+       continue;
+      if (gimple_code (outer->stmt) == GIMPLE_OMP_SCOPE
+         && !maybe_lookup_decl (var, outer))
+       continue;
+      break;
+    }
 
   if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
     x = var;
@@ -3745,6 +3752,40 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
            break;
          }
       break;
+    case GIMPLE_OMP_SCOPE:
+      for (; ctx != NULL; ctx = ctx->outer)
+       switch (gimple_code (ctx->stmt))
+         {
+         case GIMPLE_OMP_FOR:
+           if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
+               && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
+             break;
+           /* FALLTHRU */
+         case GIMPLE_OMP_SECTIONS:
+         case GIMPLE_OMP_SINGLE:
+         case GIMPLE_OMP_TASK:
+         case GIMPLE_OMP_CRITICAL:
+         case GIMPLE_OMP_ORDERED:
+         case GIMPLE_OMP_MASTER:
+         case GIMPLE_OMP_MASKED:
+           error_at (gimple_location (stmt),
+                     "%<scope%> region may not be closely nested inside "
+                     "of work-sharing, %<loop%>, explicit %<task%>, "
+                     "%<taskloop%>, %<critical%>, %<ordered%>, %<master%>, "
+                     "or %<masked%> region");
+           return false;
+         case GIMPLE_OMP_PARALLEL:
+         case GIMPLE_OMP_TEAMS:
+           return true;
+         case GIMPLE_OMP_TARGET:
+           if (gimple_omp_target_kind (ctx->stmt)
+               == GF_OMP_TARGET_KIND_REGION)
+             return true;
+           break;
+         default:
+           break;
+         }
+      break;
     case GIMPLE_OMP_TASK:
       for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
        if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
@@ -4321,6 +4362,12 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
        scan_omp_for (as_a <gomp_for *> (stmt), ctx);
       break;
 
+    case GIMPLE_OMP_SCOPE:
+      ctx = new_omp_context (stmt, ctx);
+      scan_sharing_clauses (gimple_omp_scope_clauses (stmt), ctx);
+      scan_omp (gimple_omp_body_ptr (stmt), ctx);
+      break;
+
     case GIMPLE_OMP_SECTIONS:
       scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
       break;
@@ -8608,7 +8655,8 @@ maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple *omp_return,
        gimple_seq_add_stmt (body, g);
        gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
       }
-    else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP)
+    else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
+            && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
       return;
 }
 
@@ -8947,6 +8995,97 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 }
 
 
+/* Lower code for an OMP scope directive.  */
+
+static void
+lower_omp_scope (gimple_stmt_iterator *gsi_p, omp_context *ctx)
+{
+  tree block;
+  gimple *scope_stmt = gsi_stmt (*gsi_p);
+  gbind *bind;
+  gimple_seq bind_body, bind_body_tail = NULL, dlist;
+  gimple_seq tred_dlist = NULL;
+
+  push_gimplify_context ();
+
+  block = make_node (BLOCK);
+  bind = gimple_build_bind (NULL, NULL, block);
+  gsi_replace (gsi_p, bind, true);
+  bind_body = NULL;
+  dlist = NULL;
+
+  tree rclauses
+    = omp_task_reductions_find_first (gimple_omp_scope_clauses (scope_stmt),
+                                     OMP_SCOPE, OMP_CLAUSE_REDUCTION);
+  if (rclauses)
+    {
+      tree type = build_pointer_type (pointer_sized_int_node);
+      tree temp = create_tmp_var (type);
+      tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
+      OMP_CLAUSE_DECL (c) = temp;
+      OMP_CLAUSE_CHAIN (c) = gimple_omp_scope_clauses (scope_stmt);
+      gimple_omp_scope_set_clauses (scope_stmt, c);
+      lower_omp_task_reductions (ctx, OMP_SCOPE,
+                                gimple_omp_scope_clauses (scope_stmt),
+                                &bind_body, &tred_dlist);
+      rclauses = c;
+      tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_SCOPE_START);
+      gimple *stmt = gimple_build_call (fndecl, 1, temp);
+      gimple_seq_add_stmt (&bind_body, stmt);
+    }
+
+  lower_rec_input_clauses (gimple_omp_scope_clauses (scope_stmt),
+                          &bind_body, &dlist, ctx, NULL);
+  lower_omp (gimple_omp_body_ptr (scope_stmt), ctx);
+
+  gimple_seq_add_stmt (&bind_body, scope_stmt);
+
+  gimple_seq_add_seq (&bind_body, gimple_omp_body (scope_stmt));
+
+  gimple_omp_set_body (scope_stmt, NULL);
+
+  gimple_seq clist = NULL;
+  lower_reduction_clauses (gimple_omp_scope_clauses (scope_stmt),
+                          &bind_body, &clist, ctx);
+  if (clist)
+    {
+      tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+      gcall *g = gimple_build_call (fndecl, 0);
+      gimple_seq_add_stmt (&bind_body, g);
+      gimple_seq_add_seq (&bind_body, clist);
+      fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+      g = gimple_build_call (fndecl, 0);
+      gimple_seq_add_stmt (&bind_body, g);
+    }
+
+  gimple_seq_add_seq (&bind_body, dlist);
+
+  bind_body = maybe_catch_exception (bind_body);
+
+  bool nowait = omp_find_clause (gimple_omp_scope_clauses (scope_stmt),
+                                OMP_CLAUSE_NOWAIT) != NULL_TREE;
+  gimple *g = gimple_build_omp_return (nowait);
+  gimple_seq_add_stmt (&bind_body_tail, g);
+  gimple_seq_add_seq (&bind_body_tail, tred_dlist);
+  maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
+  if (ctx->record_type)
+    {
+      gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
+      tree clobber = build_clobber (ctx->record_type);
+      gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
+                                                  clobber), GSI_SAME_STMT);
+    }
+  gimple_seq_add_seq (&bind_body, bind_body_tail);
+
+  gimple_bind_set_body (bind, bind_body);
+
+  pop_gimplify_context (bind);
+
+  gimple_bind_append_vars (bind, ctx->block_vars);
+  BLOCK_VARS (block) = ctx->block_vars;
+  if (BLOCK_VARS (block))
+    TREE_USED (block) = 1;
+}
 /* Expand code for an OpenMP master or masked directive.  */
 
 static void
@@ -9052,7 +9191,7 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
   clauses = omp_task_reductions_find_first (clauses, code, ccode);
   if (clauses == NULL_TREE)
     return;
-  if (code == OMP_FOR || code == OMP_SECTIONS)
+  if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
     {
       for (omp_context *outer = ctx->outer; outer; outer = outer->outer)
        if (gimple_code (outer->stmt) == GIMPLE_OMP_PARALLEL
@@ -9061,7 +9200,8 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
            cancellable = error_mark_node;
            break;
          }
-       else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP)
+       else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
+                && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
          break;
     }
   tree record_type = lang_hooks.types.make_type (RECORD_TYPE);
@@ -9177,11 +9317,11 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
   tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
   tree lab3 = NULL_TREE, lab7 = NULL_TREE;
   gimple *g;
-  if (code == OMP_FOR || code == OMP_SECTIONS)
+  if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
     {
-      /* For worksharing constructs, only perform it in the master thread,
-        with the exception of cancelled implicit barriers - then only handle
-        the current thread.  */
+      /* For worksharing constructs or scope, only perform it in the master
+        thread, with the exception of cancelled implicit barriers - then only
+        handle the current thread.  */
       tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
       t = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
       tree thr_num = create_tmp_var (integer_type_node);
@@ -9196,8 +9336,10 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
          lab3 = create_artificial_label (UNKNOWN_LOCATION);
          if (code == OMP_FOR)
            c = gimple_omp_for_clauses (ctx->stmt);
-         else /* if (code == OMP_SECTIONS) */
+         else if (code == OMP_SECTIONS)
            c = gimple_omp_sections_clauses (ctx->stmt);
+         else /* if (code == OMP_SCOPE) */
+           c = gimple_omp_scope_clauses (ctx->stmt);
          c = OMP_CLAUSE_DECL (omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_));
          cancellable = c;
          g = gimple_build_cond (NE_EXPR, c, build_zero_cst (TREE_TYPE (c)),
@@ -9332,8 +9474,11 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
 
          tree bfield = DECL_CHAIN (field);
          tree cond;
-         if (code == OMP_PARALLEL || code == OMP_FOR || code == OMP_SECTIONS)
-           /* In parallel or worksharing all threads unconditionally
+         if (code == OMP_PARALLEL
+             || code == OMP_FOR
+             || code == OMP_SECTIONS
+             || code == OMP_SCOPE)
+           /* In parallel, worksharing or scope all threads unconditionally
               initialize all their task reduction private variables.  */
            cond = boolean_true_node;
          else if (TREE_TYPE (ptr) == ptr_type_node)
@@ -9574,6 +9719,8 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
        c = gimple_omp_for_clauses (ctx->stmt);
       else if (code == OMP_SECTIONS)
        c = gimple_omp_sections_clauses (ctx->stmt);
+      else if (code == OMP_SCOPE)
+       c = gimple_omp_scope_clauses (ctx->stmt);
       else
        c = gimple_omp_taskreg_clauses (ctx->stmt);
       c = omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_);
@@ -9588,7 +9735,7 @@ lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
   g = gimple_build_cond (NE_EXPR, idx, num_thr_sz, lab1, lab2);
   gimple_seq_add_stmt (end, g);
   gimple_seq_add_stmt (end, gimple_build_label (lab2));
-  if (code == OMP_FOR || code == OMP_SECTIONS)
+  if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
     {
       enum built_in_function bfn
        = BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER;
@@ -14168,6 +14315,11 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
        ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
       lower_omp_sections (gsi_p, ctx);
       break;
+    case GIMPLE_OMP_SCOPE:
+      ctx = maybe_lookup_ctx (stmt);
+      gcc_assert (ctx);
+      lower_omp_scope (gsi_p, ctx);
+      break;
     case GIMPLE_OMP_SINGLE:
       ctx = maybe_lookup_ctx (stmt);
       gcc_assert (ctx);
@@ -14279,6 +14431,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
          if (gimple_code (up->stmt) == GIMPLE_OMP_ORDERED
              || gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL
              || gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP
+             || gimple_code (up->stmt) == GIMPLE_OMP_SCOPE
              || gimple_code (up->stmt) == GIMPLE_OMP_SECTION
              || gimple_code (up->stmt) == GIMPLE_OMP_SCAN
              || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
@@ -14548,6 +14701,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
 
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
     case GIMPLE_OMP_SECTION:
@@ -14610,6 +14764,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
 
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
     case GIMPLE_OMP_SECTION:
index 07e04127abe55bf7c7aa4ba192318670a9df72ac..4b91bed40500b1c0616395c17314ba992db01302 100644 (file)
@@ -1,3 +1,26 @@
+2021-08-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-c++-common/gomp/nesting-2.c (foo): Add scope and masked
+       construct tests.
+       * c-c++-common/gomp/scan-1.c (f3): Add scope construct test..
+       * c-c++-common/gomp/cancel-1.c (f2): Add scope and masked
+       construct tests.
+       * c-c++-common/gomp/reduction-task-2.c (bar): Add scope construct
+       test.  Adjust diagnostics for the addition of scope.
+       * c-c++-common/gomp/loop-1.c (f5): Add master, masked and scope
+       construct tests.
+       * c-c++-common/gomp/clause-dups-1.c (f1): Add scope construct test.
+       * gcc.dg/gomp/nesting-1.c (f1, f2, f3): Add scope construct tests.
+       * c-c++-common/gomp/scope-1.c: New test.
+       * c-c++-common/gomp/scope-2.c: New test.
+       * g++.dg/gomp/attrs-1.C (bar): Add scope construct tests.
+       * g++.dg/gomp/attrs-2.C (bar): Likewise.
+       * gfortran.dg/gomp/reduction4.f90: Adjust expected diagnostics.
+       * gfortran.dg/gomp/reduction7.f90: Likewise.
+
 2021-08-16  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 5255dd3e2a5178f26cef08440cff611de9f7e248..5d68cd3ed6d23f6ca4a5649607f9090c97ac887c 100644 (file)
@@ -39,6 +39,28 @@ f2 (void)
       #pragma omp cancellation point sections  /* { dg-error "not closely nested inside" } */
       #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
     }
+    #pragma omp masked
+    {
+      #pragma omp cancel parallel              /* { dg-error "not closely nested inside" } */
+      #pragma omp cancel for                   /* { dg-error "not closely nested inside" } */
+      #pragma omp cancel sections              /* { dg-error "not closely nested inside" } */
+      #pragma omp cancel taskgroup             /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point parallel  /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point for       /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point sections  /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+    }
+    #pragma omp scope
+    {
+      #pragma omp cancel parallel              /* { dg-error "not closely nested inside" } */
+      #pragma omp cancel for                   /* { dg-error "not closely nested inside" } */
+      #pragma omp cancel sections              /* { dg-error "not closely nested inside" } */
+      #pragma omp cancel taskgroup             /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point parallel  /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point for       /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point sections  /* { dg-error "not closely nested inside" } */
+      #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+    }
     #pragma omp single
     {
       #pragma omp cancel parallel              /* { dg-error "not closely nested inside" } */
index 7b71ad37f9c7742c5ec26d62edac80add524771f..604caf0ba918a6db7c8930337aa1ec5ebeb0c356 100644 (file)
@@ -205,6 +205,8 @@ f1 (int *p)
   i = p[0]++;
   #pragma omp masked filter (0) filter (0)                     /* { dg-error "too many 'filter' clauses" } */
   f0 ();
+  #pragma omp scope nowait nowait                              /* { dg-error "too many 'nowait' clauses" } */
+  ;
 }
 
 #pragma omp declare simd simdlen (4) simdlen (4)               /* { dg-error "too many 'simdlen' clauses" } */
index 4fb995c02a770ef6674891dbf59dc13f47f5f30e..3454fa802e33e8ae780d1d9ffd109c0b0aef4d2e 100644 (file)
@@ -182,6 +182,24 @@ f5 (int *a)
       v = a[i];                                /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" "" { target c } } */
     }
   #pragma omp loop
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp master               /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */
+      foo ();
+    }
+  #pragma omp loop
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp masked               /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */
+      foo ();
+    }
+  #pragma omp loop
+  for (i = 0; i < 64; i++)
+    {
+      #pragma omp scope                        /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */
+      foo ();
+    }
+  #pragma omp loop
   for (i = 0; i < 64; i++)
     a[i] += omp_get_thread_num ();     /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */
   #pragma omp loop
index 7a03430311df77d7f6bda9463189e337751a47a1..420cfd3cfa6add8acf9f229ffc343fce67aaea7e 100644 (file)
@@ -19,6 +19,10 @@ foo (void)
       #pragma omp barrier              /* { dg-error "region may not be closely nested inside of" } */
       #pragma omp master               /* { dg-error "region may not be closely nested inside of" } */
       ;
+      #pragma omp masked               /* { dg-error "region may not be closely nested inside of" } */
+      ;
+      #pragma omp scope                        /* { dg-error "region may not be closely nested inside of" } */
+      ;
       #pragma omp ordered              /* { dg-error "region may not be closely nested inside of" } */
       ;
       #pragma omp ordered threads      /* { dg-error "region may not be closely nested inside of" } */
@@ -55,6 +59,10 @@ foo (void)
       #pragma omp barrier
       #pragma omp master
       ;
+      #pragma omp masked
+      ;
+      #pragma omp scope
+      ;
       #pragma omp ordered              /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
       ;
       #pragma omp ordered threads      /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
@@ -89,6 +97,10 @@ foo (void)
       #pragma omp barrier
       #pragma omp master
       ;
+      #pragma omp masked
+      ;
+      #pragma omp scope
+      ;
       #pragma omp ordered              /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
       ;
       #pragma omp ordered threads      /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
index 1e262d325d4e42482e90bcec8d7d893abd2df90e..225abed1bc60cbfa61df061fc14e5d5aa40d6e35 100644 (file)
@@ -14,7 +14,9 @@ bar (void)
     #pragma omp section
     foo (-3);
   }
-  #pragma omp simd reduction (task, +: v)      /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */
+  #pragma omp scope reduction (task, +: v) nowait      /* { dg-error "'task' reduction modifier on a construct with a 'nowait' clause" } */
+  foo (-4);
+  #pragma omp simd reduction (task, +: v)      /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for', 'sections' or 'scope'" } */
   for (i = 0; i < 64; i++)
     v++;
   #pragma omp for simd reduction (task, +: v)  /* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */
@@ -26,13 +28,13 @@ bar (void)
   #pragma omp teams distribute parallel for simd reduction (task, +: v)        /* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */
   for (i = 0; i < 64; i++)
     v++;
-  #pragma omp taskloop reduction (task, +: v)  /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */
+  #pragma omp taskloop reduction (task, +: v)  /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for', 'sections' or 'scope'" } */
   for (i = 0; i < 64; i++)
     foo (i);
   #pragma omp taskloop simd reduction (task, +: v)     /* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */
   for (i = 0; i < 64; i++)
     v++;
-  #pragma omp teams reduction (task, +: v)     /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */
+  #pragma omp teams reduction (task, +: v)     /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for', 'sections' or 'scope'" } */
   foo (i);
   #pragma omp teams distribute reduction (task, +: v)  /* { dg-error "invalid 'task' reduction modifier on construct not combined with 'parallel', 'for' or 'sections'" } */
   for (i = 0; i < 64; i++)
index 17804e34ba9983834cad8aa16bc720094c8b6eeb..95b46cbb71b8bd1ca6ddf4716724b9fcd2c06525 100644 (file)
@@ -89,6 +89,8 @@ f3 (int *c, int *d)
     #pragma omp section
     ;
   }
+  #pragma omp scope reduction (inscan, +: a)   /* { dg-error "'inscan' 'reduction' clause on 'scope' construct" } */
+  ;
   #pragma omp target parallel for reduction (inscan, +: a) map (c[:64], d[:64])        /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
   for (i = 0; i < 64; i++)
     {
diff --git a/gcc/testsuite/c-c++-common/gomp/scope-1.c b/gcc/testsuite/c-c++-common/gomp/scope-1.c
new file mode 100644 (file)
index 0000000..ab7a778
--- /dev/null
@@ -0,0 +1,39 @@
+int r, r2, r3;
+
+void
+foo (void)
+{
+  int i = 0, j = 0, k = 0;
+  #pragma omp scope private (i) reduction (+:r) nowait
+  {
+    i = 1;
+    r++;
+  }
+  #pragma omp scope private (i) reduction (task, +:r)
+  #pragma omp scope private (j) reduction (task, +:r2)
+  #pragma omp scope private (k) reduction (task, +:r3)
+  {
+    i = 1;
+    j = 2;
+    k = 3;
+    r++;
+    r2++;
+    r3++;
+  }
+  #pragma omp parallel
+  {
+    #pragma omp scope reduction (+:r) private (i) nowait
+    {
+      #pragma omp scope reduction (+:r2) private (j) nowait
+      {
+       #pragma omp single
+       {
+         i = 1;
+         j = 2;
+         r++;
+         r2++;
+       }
+      }
+    }
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scope-2.c b/gcc/testsuite/c-c++-common/gomp/scope-2.c
new file mode 100644 (file)
index 0000000..58517be
--- /dev/null
@@ -0,0 +1,41 @@
+int r, r2, r3 = 1;
+int bar (void);
+
+void
+foo (void)
+{
+  int i = 0, j = 0, k = 0;
+  #pragma omp parallel
+  {
+    if (bar ())
+      {
+       #pragma omp cancel parallel
+      }
+    #pragma omp scope reduction (+:r) private (i)
+    {
+      #pragma omp scope reduction (+:r2) private (j)
+      {
+       #pragma omp single nowait
+       {
+         i = 1;
+         j = 2;
+         r++;
+         r2++;
+       }
+      }
+    }
+  }
+  #pragma omp parallel
+  {
+    if (bar ())
+      {
+       #pragma omp cancel parallel
+      }
+    #pragma omp scope reduction (task, +:r) private (i)
+    #pragma omp scope reduction (task, *:r3)
+    {
+      r++;
+      r3++;
+    }
+  }
+}
index c3483756dd6edff68c2d805f7c276f933571f543..686acf5042fe82d18db4ed077f148cfba2af6098 100644 (file)
@@ -554,6 +554,10 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
       [[omp::directive (cancellation point parallel)]];
     }
   }
+  [[omp::directive (scope private (p) reduction(+:r) nowait)]]
+    ;
+  [[omp::directive (scope private (p) reduction(task, +:r))]]
+    ;
   extern int t2;
   [[omp::directive (threadprivate (t2))]];
   extern int t2;
index b2fba21d71ab6060582b4b7d4a57069e536fbec8..2190457c877966e1af2bdaa09c9a6fb7e0bb25ae 100644 (file)
@@ -554,6 +554,10 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
       [[omp::directive (cancellation point, parallel)]];
     }
   }
+  [[omp::directive (scope, private (p), reduction(+:r), nowait)]]
+    ;
+  [[using omp:directive (scope, private (p), reduction(task, +:r))]]
+    ;
   extern int t2;
   [[omp::directive (threadprivate (t2))]];
   extern int t2;
index 4a471c8fbb69702120a7910f1286d4ecf7e67732..ed457ced44cef400f3d04a979d88d9e3403efd9b 100644 (file)
@@ -24,6 +24,8 @@ f1 (void)
       #pragma omp masked       /* { dg-error "may not be closely nested" } */
        ;
       #pragma omp barrier      /* { dg-error "may not be closely nested" } */
+      #pragma omp scope                /* { dg-error "may not be closely nested" } */
+       ;
     }
   #pragma omp sections
   {
@@ -56,6 +58,11 @@ f1 (void)
       ;
   }
   #pragma omp sections
+  {
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
+  }
+  #pragma omp sections
   {
     #pragma omp section
       ;
@@ -92,6 +99,12 @@ f1 (void)
     #pragma omp masked         /* { dg-error "may not be closely nested" } */
       ;
   }
+  #pragma omp sections
+  {
+    #pragma omp section
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
+  }
   #pragma omp single
   {
     #pragma omp for            /* { dg-error "may not be closely nested" } */
@@ -110,6 +123,8 @@ f1 (void)
     #pragma omp masked         /* { dg-error "may not be closely nested" } */
       ;
     #pragma omp barrier                /* { dg-error "may not be closely nested" } */
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
   }
   #pragma omp master
   {
@@ -127,6 +142,8 @@ f1 (void)
     #pragma omp master
       ;
     #pragma omp barrier                /* { dg-error "may not be closely nested" } */
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
   }
   #pragma omp masked filter (1)
   {
@@ -144,6 +161,8 @@ f1 (void)
     #pragma omp master
       ;
     #pragma omp barrier                /* { dg-error "may not be closely nested" } */
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
   }
   #pragma omp task
   {
@@ -163,6 +182,8 @@ f1 (void)
     #pragma omp masked         /* { dg-error "may not be closely nested" } */
       ;
     #pragma omp barrier                /* { dg-error "may not be closely nested" } */
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
   }
   #pragma omp parallel
   {
@@ -182,6 +203,39 @@ f1 (void)
     #pragma omp masked
       ;
     #pragma omp barrier
+    #pragma omp scope
+      ;
+    #pragma omp scope
+    {
+      #pragma omp scope
+      ;
+    }
+  }
+  #pragma omp scope
+  {
+    #pragma omp for
+    for (j = 0; j < 3; j++)
+      ;
+    #pragma omp sections
+    {
+      ;
+    #pragma omp section
+      ;
+    }
+    #pragma omp single
+      ;
+    #pragma omp master
+      ;
+    #pragma omp masked
+      ;
+    #pragma omp barrier
+    #pragma omp scope
+      ;
+    #pragma omp scope
+    {
+      #pragma omp scope
+      ;
+    }
   }
 }
 
@@ -207,6 +261,8 @@ f2 (void)
     #pragma omp masked
       ;
     #pragma omp barrier                /* { dg-error "may not be closely nested" } */
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
   }
 }
 
@@ -217,6 +273,8 @@ f3 (void)
   {
     #pragma omp ordered                /* { dg-error "may not be closely nested" } */
       ;
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
   }
 }
 
@@ -227,6 +285,8 @@ f4 (void)
   {
     #pragma omp ordered                /* { dg-error "may not be closely nested" } */
       ;
+    #pragma omp scope          /* { dg-error "may not be closely nested" } */
+      ;
   }
 }
 
index 2e8aaa2d54c7c32ca3221efed271c418da80e5fc..52d504bac716cd24ea6f23efa7dd639f12ab5d53 100644 (file)
@@ -40,7 +40,7 @@ do i=1,10
   a = a + 1
 end do
 
-!$omp simd reduction(task,+:a)  ! { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'do' or 'sections'" }
+!$omp simd reduction(task,+:a)  ! { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'do', 'sections' or 'scope'" }
 do i=1,10
   a = a + 1
 end do
index 7dc50e1ac69779101332daa37a057a722a1dd5fe..5f0b7bd02f88b0c84cfef78e361f81cc0693344b 100644 (file)
@@ -2,7 +2,7 @@ implicit none
 integer :: a, b, i
 a = 0
 
-!$omp simd reduction(task,+:a)  ! { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'do' or 'sections'" }
+!$omp simd reduction(task,+:a)  ! { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'do', 'sections' or 'scope'" }
 do i=1,10
   a = a + 1
 end do
index 938a4af3445bab532ae8a09e9b15482b9a3c3730..a5460a4b972bb19d4471f38ffe77167a40657fcd 100644 (file)
@@ -1683,6 +1683,12 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
                   (s1, gimple_omp_masked_clauses (stmt));
          break;
 
+       case GIMPLE_OMP_SCOPE:
+         s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+         copy = gimple_build_omp_scope
+                  (s1, gimple_omp_scope_clauses (stmt));
+         break;
+
        case GIMPLE_OMP_TASKGROUP:
          s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
          copy = gimple_build_omp_taskgroup
@@ -4567,6 +4573,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_MASKED:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
     case GIMPLE_OMP_SCAN:
index d6c8177bcc969d7e40df1658713e2748abc154de..3d41f959e9eb37acf04f83ae0cf9cfb1b9c8fdce 100644 (file)
@@ -1734,6 +1734,14 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->suppress_expansion = save_suppress;
       break;
 
+    case GIMPLE_OMP_SCOPE:
+      save_suppress = info->suppress_expansion;
+      convert_nonlocal_omp_clauses (gimple_omp_scope_clauses_ptr (stmt), wi);
+      walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+                info, gimple_omp_body_ptr (stmt));
+      info->suppress_expansion = save_suppress;
+      break;
+
     case GIMPLE_OMP_TASKGROUP:
       save_suppress = info->suppress_expansion;
       convert_nonlocal_omp_clauses (gimple_omp_taskgroup_clauses_ptr (stmt), wi);
@@ -2455,6 +2463,14 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->suppress_expansion = save_suppress;
       break;
 
+    case GIMPLE_OMP_SCOPE:
+      save_suppress = info->suppress_expansion;
+      convert_local_omp_clauses (gimple_omp_scope_clauses_ptr (stmt), wi);
+      walk_body (convert_local_reference_stmt, convert_local_reference_op,
+                info, gimple_omp_body_ptr (stmt));
+      info->suppress_expansion = save_suppress;
+      break;
+
     case GIMPLE_OMP_TASKGROUP:
       save_suppress = info->suppress_expansion;
       convert_local_omp_clauses (gimple_omp_taskgroup_clauses_ptr (stmt), wi);
@@ -3028,6 +3044,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_SINGLE:
+    case GIMPLE_OMP_SCOPE:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_MASKED:
     case GIMPLE_OMP_TASKGROUP:
index 0c3621f20a43ebc9c7597a3351f9182ade5d8d11..40fd7e3d32ebd8903b2f725d8e7fd393e1b86d41 100644 (file)
@@ -3708,6 +3708,11 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
       dump_omp_clauses (pp, OMP_SINGLE_CLAUSES (node), spc, flags);
       goto dump_omp_body;
 
+    case OMP_SCOPE:
+      pp_string (pp, "#pragma omp scope");
+      dump_omp_clauses (pp, OMP_SCOPE_CLAUSES (node), spc, flags);
+      goto dump_omp_body;
+
     case OMP_CLAUSE:
       /* If we come here, we're dumping something that's not an OMP construct,
         for example, OMP clauses attached to a function's '__attribute__'.
index ff8b5e6503cbf55bb7355603d0c6f3aed462125a..e27bc3e2b1f3f7092d8c18eb62ffde6ff1ff5841 100644 (file)
@@ -1213,6 +1213,11 @@ DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 3)
    Operand 1: OMP_SINGLE_CLAUSES: List of clauses.  */
 DEFTREECODE (OMP_SINGLE, "omp_single", tcc_statement, 2)
 
+/* OpenMP - #pragma omp scope
+   Operand 0: OMP_SCOPE_BODY: Masked section body.
+   Operand 1: OMP_SCOPE_CLAUSES: List of clauses.  */
+DEFTREECODE (OMP_SCOPE, "omp_scope", tcc_statement, 2)
+
 /* OpenMP - #pragma omp taskgroup
    Operand 0: OMP_TASKGROUP_BODY: Taskgroup body.
    Operand 1: OMP_SINGLE_CLAUSES: List of clauses.  */
index 38f299ebe8c938d966ba709b9c1a88b19fb38da2..b5564bf13e9500969e49bbc3b02275c1bdc8d4c1 100644 (file)
@@ -1426,6 +1426,9 @@ class auto_suppress_location_wrappers
 #define OMP_SINGLE_BODY(NODE)     TREE_OPERAND (OMP_SINGLE_CHECK (NODE), 0)
 #define OMP_SINGLE_CLAUSES(NODE)   TREE_OPERAND (OMP_SINGLE_CHECK (NODE), 1)
 
+#define OMP_SCOPE_BODY(NODE)      TREE_OPERAND (OMP_SCOPE_CHECK (NODE), 0)
+#define OMP_SCOPE_CLAUSES(NODE)           TREE_OPERAND (OMP_SCOPE_CHECK (NODE), 1)
+
 #define OMP_MASTER_BODY(NODE)     TREE_OPERAND (OMP_MASTER_CHECK (NODE), 0)
 
 #define OMP_MASKED_BODY(NODE)     TREE_OPERAND (OMP_MASKED_CHECK (NODE), 0)
index bad08432f7725de367e91abad48e837cde61e888..95fc075377d561ceb78660e481d4694bf4731587 100644 (file)
@@ -1,3 +1,16 @@
+2021-08-17  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backported from master:
+       2021-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * Makefile.am (libgomp_la_SOURCES): Add scope.c
+       * Makefile.in: Regenerated.
+       * libgomp_g.h (GOMP_scope_start): Declare.
+       * libgomp.map: Add GOMP_scope_start@@GOMP_5.1.
+       * scope.c: New file.
+       * testsuite/libgomp.c-c++-common/scope-1.c: New test.
+       * testsuite/libgomp.c-c++-common/task-reduction-16.c: New test.
+
 2021-08-16  Tobias Burnus  <tobias@codesourcery.com>
 
        Backported from master:
index 49f29429fccb641b2c5ef296a36ea8f0943dc07f..fa3104f7321e22227b4cc2657fbdf0060bb52490 100644 (file)
@@ -61,12 +61,12 @@ libgomp_la_LINK = $(LINK) $(libgomp_la_LDFLAGS)
 
 libgomp_la_SOURCES = alloc.c atomic.c barrier.c critical.c env.c error.c \
        icv.c icv-device.c iter.c iter_ull.c loop.c loop_ull.c ordered.c \
-       parallel.c sections.c single.c task.c team.c work.c lock.c mutex.c \
-       proc.c sem.c bar.c ptrlock.c time.c fortran.c affinity.c target.c \
-       splay-tree.c libgomp-plugin.c oacc-parallel.c oacc-host.c oacc-init.c \
-       oacc-mem.c oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \
-       affinity-fmt.c teams.c allocator.c oacc-profiling.c oacc-target.c \
-       oacc-profiling-acc_register_library.c
+       parallel.c scope.c sections.c single.c task.c team.c work.c lock.c \
+       mutex.c proc.c sem.c bar.c ptrlock.c time.c fortran.c affinity.c \
+       target.c splay-tree.c libgomp-plugin.c oacc-parallel.c oacc-host.c \
+       oacc-init.c oacc-mem.c oacc-async.c oacc-plugin.c oacc-cuda.c \
+       priority_queue.c affinity-fmt.c teams.c allocator.c oacc-profiling.c \
+       oacc-target.c oacc-profiling-acc_register_library.c
 
 include $(top_srcdir)/plugin/Makefrag.am
 
index 68942ad4ad9018dac37d3ace15d9377853395296..65cbe89fcf936a1835af7c6e8d51dedbbf29d714 100644 (file)
@@ -213,14 +213,14 @@ libgomp_la_LIBADD =
 @USE_FORTRAN_TRUE@am__objects_1 = openacc.lo
 am_libgomp_la_OBJECTS = alloc.lo atomic.lo barrier.lo critical.lo \
        env.lo error.lo icv.lo icv-device.lo iter.lo iter_ull.lo \
-       loop.lo loop_ull.lo ordered.lo parallel.lo sections.lo \
-       single.lo task.lo team.lo work.lo lock.lo mutex.lo proc.lo \
-       sem.lo bar.lo ptrlock.lo time.lo fortran.lo affinity.lo \
-       target.lo splay-tree.lo libgomp-plugin.lo oacc-parallel.lo \
-       oacc-host.lo oacc-init.lo oacc-mem.lo oacc-async.lo \
-       oacc-plugin.lo oacc-cuda.lo priority_queue.lo affinity-fmt.lo \
-       teams.lo allocator.lo oacc-profiling.lo oacc-target.lo \
-       oacc-profiling-acc_register_library.lo $(am__objects_1)
+       loop.lo loop_ull.lo ordered.lo parallel.lo scope.lo \
+       sections.lo single.lo task.lo team.lo work.lo lock.lo mutex.lo \
+       proc.lo sem.lo bar.lo ptrlock.lo time.lo fortran.lo \
+       affinity.lo target.lo splay-tree.lo libgomp-plugin.lo \
+       oacc-parallel.lo oacc-host.lo oacc-init.lo oacc-mem.lo \
+       oacc-async.lo oacc-plugin.lo oacc-cuda.lo priority_queue.lo \
+       affinity-fmt.lo teams.lo allocator.lo oacc-profiling.lo \
+       oacc-target.lo oacc-profiling-acc_register_library.lo $(am__objects_1)
 libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -553,9 +553,9 @@ libgomp_la_DEPENDENCIES = $(libgomp_version_dep)
 libgomp_la_LINK = $(LINK) $(libgomp_la_LDFLAGS)
 libgomp_la_SOURCES = alloc.c atomic.c barrier.c critical.c env.c \
        error.c icv.c icv-device.c iter.c iter_ull.c loop.c loop_ull.c \
-       ordered.c parallel.c sections.c single.c task.c team.c work.c \
-       lock.c mutex.c proc.c sem.c bar.c ptrlock.c time.c fortran.c \
-       affinity.c target.c splay-tree.c libgomp-plugin.c \
+       ordered.c parallel.c scope.c sections.c single.c task.c team.c \
+       work.c lock.c mutex.c proc.c sem.c bar.c ptrlock.c time.c \
+       fortran.c affinity.c target.c splay-tree.c libgomp-plugin.c \
        oacc-parallel.c oacc-host.c oacc-init.c oacc-mem.c \
        oacc-async.c oacc-plugin.c oacc-cuda.c priority_queue.c \
        affinity-fmt.c teams.c allocator.c oacc-profiling.c \
@@ -771,6 +771,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/priority_queue.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptrlock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scope.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sections.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sem.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/single.Plo@am__quote@
index 3859079eb4a21d5a926ef7b230e8b38593300788..ef844ea77e6d1c1a5b025e6fc621618eb385d77b 100644 (file)
@@ -380,6 +380,11 @@ GOMP_5.0.1 {
        GOMP_free;
 } GOMP_5.0;
 
+GOMP_5.1 {
+  global:
+       GOMP_scope_start;
+} GOMP_5.0.1;
+
 OACC_2.0 {
   global:
        acc_get_num_devices;
index 63031501c86e2d16a8e8f0e09829a5202cf3dd20..236bcf3cbd258afed60478d32d75a81d56a1f997 100644 (file)
@@ -332,6 +332,10 @@ extern bool GOMP_single_start (void);
 extern void *GOMP_single_copy_start (void);
 extern void GOMP_single_copy_end (void *);
 
+/* scope.c */
+
+extern void GOMP_scope_start (uintptr_t *);
+
 /* target.c */
 
 extern void GOMP_target (int, void (*) (void *), const void *,
diff --git a/libgomp/scope.c b/libgomp/scope.c
new file mode 100644 (file)
index 0000000..8a4691c
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+   Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+   This file is part of the GNU Offloading and Multi Processing Library
+   (libgomp).
+
+   Libgomp is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+   more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file handles the SCOPE construct with task reductions.  */
+
+#include "libgomp.h"
+#include <string.h>
+
+
+ialias_redirect (GOMP_taskgroup_reduction_register)
+
+/* This routine is called when first encountering a scope construct
+   with task reductions.  While scope is not a work-sharing construct,
+   if it has task reductions on it, we treat it as one, but as if it is
+   nowait, so the work-sharing behavior is done solely to choose which
+   thread does the initial initialization of task reductions and which
+   threads follow.  scope with task reductions must not be nowait,
+   but the barrier and GOMP_workshare_task_reduction_unregister are emitted
+   by the lowered code later.  */
+
+void
+GOMP_scope_start (uintptr_t *reductions)
+{
+  struct gomp_thread *thr = gomp_thread ();
+
+  gomp_workshare_taskgroup_start ();
+  if (gomp_work_share_start (0))
+    {
+      GOMP_taskgroup_reduction_register (reductions);
+      thr->task->taskgroup->workshare = true;
+      thr->ts.work_share->task_reductions = reductions;
+      gomp_work_share_init_done ();
+    }
+  else
+    {
+      uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
+      gomp_workshare_task_reduction_register (reductions,
+                                             first_reductions);
+    }
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/scope-1.c b/libgomp/testsuite/libgomp.c-c++-common/scope-1.c
new file mode 100644 (file)
index 0000000..d262312
--- /dev/null
@@ -0,0 +1,50 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort ();
+
+int
+main ()
+{
+  int a[64] = {};
+  int r = 0, r2 = 0, i;
+  #pragma omp parallel
+  {
+    #pragma omp scope nowait
+    #pragma omp scope nowait
+    #pragma omp for
+    for (i = 0; i < 64; i++)
+      a[i] += 1;
+    #pragma omp scope reduction(+: r) nowait
+    {
+      #pragma omp for nowait
+      for (i = 0; i < 64; i++)
+       {
+         r += i;
+         if (a[i] != 1)
+           abort ();
+       }
+      #pragma omp barrier
+    }
+    #pragma omp barrier
+    if (r != 64 * 63 / 2)
+      abort ();
+    #pragma omp scope nowait private (i)
+    #pragma omp scope reduction(+: r2)
+    {
+      #pragma omp for nowait
+      for (i = 0; i < 64; i++)
+       {
+         r2 += 2 * i;
+         a[i] += i;
+       }
+    }
+    if (r2 != 64 * 63)
+      abort ();
+    #pragma omp for nowait
+    for (i = 0; i < 64; i++)
+      if (a[i] != i + 1)
+       abort ();
+  }
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-16.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-16.c
new file mode 100644 (file)
index 0000000..44d32c7
--- /dev/null
@@ -0,0 +1,76 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+int a, b[3] = { 1, 1, 1 };
+unsigned long int c[2] = { ~0UL, ~0UL };
+
+void
+bar (int i)
+{
+  #pragma omp task in_reduction (*: b[:3]) in_reduction (&: c[1:]) \
+             in_reduction (+: a)
+  {
+    a += 4;
+    b[1] *= 4;
+    c[1] &= ~(1UL << (i + 16));
+  }
+}
+
+void
+foo (int x)
+{
+  #pragma omp scope reduction (task, +: a)
+  {
+    #pragma omp scope reduction (task, *: b)
+    {
+      #pragma omp scope reduction (task, &: c[1:1])
+      {
+       #pragma omp barrier
+       #pragma omp sections
+       {
+         {
+           a++; b[0] *= 2; bar (2); b[2] *= 3; c[1] &= ~(1UL << 2);
+         }
+       #pragma omp section
+       { b[0] *= 2; bar (4); b[2] *= 3; c[1] &= ~(1UL << 4); a++; }
+       #pragma omp section
+       { bar (6); b[2] *= 3; c[1] &= ~(1UL << 6); a++; b[0] *= 2; }
+       #pragma omp section
+       { b[2] *= 3; c[1] &= ~(1UL << 8); a++; b[0] *= 2; bar (8); }
+       #pragma omp section
+       { c[1] &= ~(1UL << 10); a++; b[0] *= 2; bar (10); b[2] *= 3; }
+       #pragma omp section
+       { a++; b[0] *= 2; b[2] *= 3; c[1] &= ~(1UL << 12); bar (12); }
+       #pragma omp section
+       if (x)
+         {
+           a++; b[0] *= 2; b[2] *= 3; bar (14); c[1] &= ~(1UL << 14);
+         }
+       }
+      }
+    }
+  }
+}
+
+int
+main ()
+{
+  volatile int one = 1;
+  foo (!one);
+  if (a != 30 || b[0] != 64 || b[1] != (1 << 12) || b[2] != 3 * 3 * 3 * 3 * 3 * 3
+      || c[0] != ~0UL || c[1] != ~0x15541554UL)
+    abort ();
+  a = 0;
+  b[0] = 1;
+  b[1] = 1;
+  b[2] = 1;
+  c[1] = ~0UL;
+  #pragma omp parallel
+  foo (one);
+  if (a != 35 || b[0] != 128 || b[1] != (1 << 14) || b[2] != 3 * 3 * 3 * 3 * 3 * 3 * 3
+      || c[0] != ~0UL || c[1] != ~0x55545554UL)
+    abort ();
+  return 0;
+}