tree.def (OMP_SCAN): New tree code.
authorJakub Jelinek <jakub@gcc.gnu.org>
Mon, 10 Jun 2019 12:20:30 +0000 (14:20 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 10 Jun 2019 12:20:30 +0000 (14:20 +0200)
* tree.def (OMP_SCAN): New tree code.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_INCLUSIVE and
OMP_CLAUSE_EXCLUSIVE.
* tree.h (OMP_CLAUSES): Use OMP_SCAN instead of OMP_TASKGROUP.
(OMP_SCAN_BODY, OMP_SCAN_CLAUSES): Define.
* tree.c (omp_clause_num_ops, omp_clause_code_name): Add entries for
OMP_CLAUSE_{IN,EX}CLUSIVE.
(walk_tree_1): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
* tree-nested.c (convert_nonlocal_reference_stmt,
convert_local_reference_stmt, convert_gimple_call): Handle
GIMPLE_OMP_SCAN.
* tree-pretty-print.c (dump_omp_clause): Handle
OMP_CLAUSE_{IN,EX}CLUSIVE.
(dump_generic_node): Handle OMP_SCAN.
* gimple.def (GIMPLE_OMP_SCAN): New gimple code.
* gimple.h (gomp_scan): New type.
(is_a_helper <gomp_scan *>::test,
is_a_helper <const gomp_scan *>::test): New templates.
(gimple_build_omp_scan): Declare.
(gimple_omp_scan_clauses, gimple_omp_scan_clauses_ptr,
gimple_omp_scan_set_clauses): New inline functions.
(CASE_GIMPLE_OMP): Add case GIMPLE_OMP_SCAN:.
* gimple.c (gimple_build_omp_scan): New function.
(gimple_copy): Handle GIMPLE_OMP_SCAN.
* gimple-walk.c (walk_gimple_op, walk_gimple_stmt): Likewise.
* gimple-pretty-print.c (dump_gimple_omp_block): Don't handle
GIMPLE_OMP_TASKGROUP.
(dump_gimple_omp_scan): New function.
(pp_gimple_stmt_1): Handle GIMPLE_OMP_SCAN.
* gimple-low.c (lower_stmt): Handle GIMPLE_OMP_SCAN.
* tree-inline.c (remap_gimple_stmt, estimate_num_insns): Likewise.
* gimplify.c (enum gimplify_omp_var_data): Add GOVD_REDUCTION_INSCAN.
(is_gimple_stmt): Handle OMP_SCAN.
(gimplify_scan_omp_clauses): Reject inscan reductions on constructs
other than OMP_FOR or OMP_SIMD.  Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
(gimplify_adjust_omp_clauses): Diagnose inscan reductions not
mentioned in nested #pragma omp scan.  Handle
OMP_CLAUSE_{IN,EX}CLUSIVE.
(gimplify_expr): Handle OMP_SCAN.
* omp-low.c (check_omp_nesting_restrictions): For parent context,
look through GIMPLE_OMP_SCAN context.  Allow #pragma omp scan in
simd constructs.
(scan_omp_1_stmt, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle
GIMPLE_OMP_SCAN.
c-family/
* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCAN.
* c-pragma.c (omp_pragmas_simd): Add #pragma omp scan.
* c-omp.c (c_omp_split_clauses): Diagnose inscan reductions on
combined/composite constructs where it is not allowed.  Copy over
OMP_CLAUSE_REDUCTION_INSCAN.
c/
* c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN.
(c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions.
(c_parser_omp_scan_loop_body): New function.
(c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are
inscan reduction clauses.
* c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with
non-inscan reductions on the same construct, or inscan reductions with
ordered or schedule clauses, or inscan array reductions.
cp/
* parser.c (cp_parser_omp_clause_reduction): Don't sorry_at on inscan
reductions.
(cp_parser_omp_scan_loop_body): New function.
(cp_parser_omp_for_loop): Call cp_parser_omp_scan_loop_body if there
are inscan reduction clauses.
(cp_parser_pragma): Reject PRAGMA_OMP_SCAN.
* semantics.c (finish_omp_clauses): Reject mixing inscan with
non-inscan reductions on the same construct, or inscan reductions with
ordered or schedule clauses, or inscan array reductions.
* pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
(tsubst_expr): Handle OMP_SCAN.
testsuite/
* c-c++-common/gomp/scan-1.c: New test.
* c-c++-common/gomp/scan-2.c: New test.
* c-c++-common/gomp/scan-3.c: New test.
* c-c++-common/gomp/scan-4.c: New test.

From-SVN: r272117

32 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-omp.c
gcc/c-family/c-pragma.c
gcc/c-family/c-pragma.h
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.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-low.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/gomp/scan-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/scan-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/scan-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/scan-4.c [new file with mode: 0644]
gcc/tree-core.h
gcc/tree-inline.c
gcc/tree-nested.c
gcc/tree-pretty-print.c
gcc/tree.c
gcc/tree.def
gcc/tree.h

index e93db0a1b7bb8bbdf2bdf8cec7e2289295e6c3f5..d5181995757dac6b31208a0fff88f27ba645df43 100644 (file)
@@ -1,8 +1,55 @@
+2019-06-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree.def (OMP_SCAN): New tree code.
+       * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_INCLUSIVE and
+       OMP_CLAUSE_EXCLUSIVE.
+       * tree.h (OMP_CLAUSES): Use OMP_SCAN instead of OMP_TASKGROUP.
+       (OMP_SCAN_BODY, OMP_SCAN_CLAUSES): Define.
+       * tree.c (omp_clause_num_ops, omp_clause_code_name): Add entries for
+       OMP_CLAUSE_{IN,EX}CLUSIVE.
+       (walk_tree_1): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+       * tree-nested.c (convert_nonlocal_reference_stmt,
+       convert_local_reference_stmt, convert_gimple_call): Handle
+       GIMPLE_OMP_SCAN.
+       * tree-pretty-print.c (dump_omp_clause): Handle
+       OMP_CLAUSE_{IN,EX}CLUSIVE.
+       (dump_generic_node): Handle OMP_SCAN.
+       * gimple.def (GIMPLE_OMP_SCAN): New gimple code.
+       * gimple.h (gomp_scan): New type.
+       (is_a_helper <gomp_scan *>::test,
+       is_a_helper <const gomp_scan *>::test): New templates.
+       (gimple_build_omp_scan): Declare.
+       (gimple_omp_scan_clauses, gimple_omp_scan_clauses_ptr,
+       gimple_omp_scan_set_clauses): New inline functions.
+       (CASE_GIMPLE_OMP): Add case GIMPLE_OMP_SCAN:.
+       * gimple.c (gimple_build_omp_scan): New function.
+       (gimple_copy): Handle GIMPLE_OMP_SCAN.
+       * gimple-walk.c (walk_gimple_op, walk_gimple_stmt): Likewise.
+       * gimple-pretty-print.c (dump_gimple_omp_block): Don't handle
+       GIMPLE_OMP_TASKGROUP.
+       (dump_gimple_omp_scan): New function.
+       (pp_gimple_stmt_1): Handle GIMPLE_OMP_SCAN.
+       * gimple-low.c (lower_stmt): Handle GIMPLE_OMP_SCAN.
+       * tree-inline.c (remap_gimple_stmt, estimate_num_insns): Likewise.
+       * gimplify.c (enum gimplify_omp_var_data): Add GOVD_REDUCTION_INSCAN.
+       (is_gimple_stmt): Handle OMP_SCAN.
+       (gimplify_scan_omp_clauses): Reject inscan reductions on constructs
+       other than OMP_FOR or OMP_SIMD.  Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+       (gimplify_adjust_omp_clauses): Diagnose inscan reductions not
+       mentioned in nested #pragma omp scan.  Handle
+       OMP_CLAUSE_{IN,EX}CLUSIVE.
+       (gimplify_expr): Handle OMP_SCAN.
+       * omp-low.c (check_omp_nesting_restrictions): For parent context,
+       look through GIMPLE_OMP_SCAN context.  Allow #pragma omp scan in
+       simd constructs.
+       (scan_omp_1_stmt, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle
+       GIMPLE_OMP_SCAN.
+
 2019-06-10  Martin Liska  <mliska@suse.cz>
 
        * ipa-cp.c (ignore_edge_p): New function.
        (build_toporder_info): Use it.
-       * ipa-inline.c (ignore_edge_p): New function/
+       * ipa-inline.c (ignore_edge_p): New function.
        (inline_small_functions): Use it.
        * ipa-pure-const.c (ignore_edge_for_nothrow):
        Verify opt_for_fn for caller and callee.
index 179e376fb910a2384f4e01c754803042738fb95c..589e4a12932faaa63aaa9b23a49d2fb1c7e5917a 100644 (file)
@@ -1,3 +1,11 @@
+2019-06-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCAN.
+       * c-pragma.c (omp_pragmas_simd): Add #pragma omp scan.
+       * c-omp.c (c_omp_split_clauses): Diagnose inscan reductions on
+       combined/composite constructs where it is not allowed.  Copy over
+       OMP_CLAUSE_REDUCTION_INSCAN.
+
 2019-06-05  Martin Sebor  <msebor@redhat.com>
 
        * c-attribs.c (handle_mode_attribute): Adjust quoting and hyphenation.
index 5645e9d4fda9fb0fbdfa1c583cce0752deb4fe14..96b2e45ae7a94c1751cfeb44439f1c090a9795e2 100644 (file)
@@ -1659,6 +1659,18 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
                  OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
                }
            }
+         if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
+             && ((mask & ((OMP_CLAUSE_MASK_1
+                           << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
+                          | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
+                 != 0))
+           {
+             error_at (OMP_CLAUSE_LOCATION (clauses),
+                       "%<inscan%> %<reduction%> clause on construct other "
+                       "than %<for%>, %<simd%>, %<for simd%>, "
+                       "%<parallel for%>, %<parallel for simd%>");
+             OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
+           }
          if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
            {
              if (code == OMP_SIMD)
@@ -1672,6 +1684,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
                    = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
                  OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
                    = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+                 OMP_CLAUSE_REDUCTION_INSCAN (c)
+                   = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
                  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
                  cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
                }
@@ -1687,6 +1701,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
                    = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
                  OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
                    = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+                 OMP_CLAUSE_REDUCTION_INSCAN (c)
+                   = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
                  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
                  cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
                  s = C_OMP_CLAUSE_SPLIT_PARALLEL;
@@ -1717,6 +1733,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
                    = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
                  OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
                    = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+                 OMP_CLAUSE_REDUCTION_INSCAN (c)
+                   = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
                  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
                  cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
                }
index 62b71d2e4c45d0dcb2b43cb9522ec6845bede2da..9af713d1b43f337fe3475fb3097842c3083abe11 100644 (file)
@@ -1320,6 +1320,7 @@ static const struct omp_pragma_def omp_pragmas_simd[] = {
   { "for", PRAGMA_OMP_FOR },
   { "ordered", PRAGMA_OMP_ORDERED },
   { "parallel", PRAGMA_OMP_PARALLEL },
+  { "scan", PRAGMA_OMP_SCAN },
   { "simd", PRAGMA_OMP_SIMD },
   { "target", PRAGMA_OMP_TARGET },
   { "taskloop", PRAGMA_OMP_TASKLOOP },
index 2bbb27975255624e84b06d268fa802b9e58f3fe6..ed6503686202cde3687a15897e6315ff3ad2be04 100644 (file)
@@ -56,6 +56,7 @@ enum pragma_kind {
   PRAGMA_OMP_ORDERED,
   PRAGMA_OMP_PARALLEL,
   PRAGMA_OMP_REQUIRES,
+  PRAGMA_OMP_SCAN,
   PRAGMA_OMP_SECTION,
   PRAGMA_OMP_SECTIONS,
   PRAGMA_OMP_SIMD,
index 5a0dabbd034c6a259cd9a3666c67c26e0552565a..103634eff73925ceeb8205e4dd9bc86975d0eba3 100644 (file)
@@ -1,3 +1,14 @@
+2019-06-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN.
+       (c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions.
+       (c_parser_omp_scan_loop_body): New function.
+       (c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are
+       inscan reduction clauses.
+       * c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with
+       non-inscan reductions on the same construct, or inscan reductions with
+       ordered or schedule clauses, or inscan array reductions.
+
 2019-06-05  Martin Sebor  <msebor@redhat.com>
 
        PR c/90737
index 84ee576866e6d79c2a2ce4d4e1dc6f30755fd9d8..df1a304227696f6186d40c3af6f44589e8b7465d 100644 (file)
@@ -11494,6 +11494,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
       c_parser_omp_end_declare_target (parser);
       return false;
 
+    case PRAGMA_OMP_SCAN:
+      error_at (c_parser_peek_token (parser)->location,
+               "%<#pragma omp scan%> may only be used in "
+               "a loop construct with %<inscan%> %<reduction%> clause");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+
     case PRAGMA_OMP_SECTION:
       error_at (c_parser_peek_token (parser)->location,
                "%<#pragma omp section%> may only be used in "
@@ -13558,11 +13565,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
              if (strcmp (p, "task") == 0)
                task = true;
              else if (strcmp (p, "inscan") == 0)
-               {
-                 inscan = true;
-                 sorry ("%<inscan%> modifier on %<reduction%> clause "
-                        "not supported yet");
-               }
+               inscan = true;
              if (task || inscan)
                {
                  c_parser_consume_token (parser);
@@ -16738,6 +16741,71 @@ c_parser_omp_flush (c_parser *parser)
   c_finish_omp_flush (loc, mo);
 }
 
+/* OpenMP 5.0:
+
+   scan-loop-body:
+     { structured-block scan-directive structured-block }  */
+
+static void
+c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
+{
+  tree substmt;
+  location_t loc;
+  tree clauses = NULL_TREE;
+
+  loc = c_parser_peek_token (parser)->location;
+  if (!open_brace_parsed
+      && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      /* Avoid skipping until the end of the block.  */
+      parser->error = false;
+      return;
+    }
+
+  substmt = c_parser_omp_structured_block (parser, NULL);
+  substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+  SET_EXPR_LOCATION (substmt, loc);
+  add_stmt (substmt);
+
+  loc = c_parser_peek_token (parser)->location;
+  if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
+    {
+      enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+      c_parser_consume_pragma (parser);
+
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         const char *p
+           = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+         if (strcmp (p, "inclusive") == 0)
+           clause = OMP_CLAUSE_INCLUSIVE;
+         else if (strcmp (p, "exclusive") == 0)
+           clause = OMP_CLAUSE_EXCLUSIVE;
+       }
+      if (clause != OMP_CLAUSE_ERROR)
+       {
+         c_parser_consume_token (parser);
+         clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
+       }
+      else
+       c_parser_error (parser, "expected %<inclusive%> or "
+                               "%<exclusive%> clause");
+      c_parser_skip_to_pragma_eol (parser);
+    }
+  else
+    error ("expected %<#pragma omp scan%>");
+
+  clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
+  substmt = c_parser_omp_structured_block (parser, NULL);
+  substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
+  SET_EXPR_LOCATION (substmt, loc);
+  add_stmt (substmt);
+
+  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+                            "expected %<}%>");
+}
+
 /* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
    The real trick here is to determine the loop control variable early
    so that we can push a new decl if necessary to make it private.
@@ -16756,6 +16824,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
   int i, collapse = 1, ordered = 0, count, nbraces = 0;
   location_t for_loc;
   bool tiling = false;
+  bool inscan = false;
   vec<tree, va_gc> *for_block = make_tree_vector ();
 
   for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
@@ -16772,6 +16841,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
        ordered_cl = cl;
        ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
       }
+    else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+            && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+            && (code == OMP_SIMD || code == OMP_FOR))
+      inscan = true;
 
   if (ordered && ordered < collapse)
     {
@@ -16992,7 +17065,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
   c_cont_label = NULL_TREE;
   body = push_stmt_list ();
 
-  if (open_brace_parsed)
+  if (inscan)
+    c_parser_omp_scan_loop_body (parser, open_brace_parsed);
+  else if (open_brace_parsed)
     {
       location_t here = c_parser_peek_token (parser)->location;
       stmt = c_begin_compound_stmt (true);
index 0dd86f074b91108b5563ce4e55f7396a7d2a9cd3..6abfd101f3016119b0d0904138fe604ba34f8dea 100644 (file)
@@ -13661,13 +13661,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   bool copyprivate_seen = false;
   bool linear_variable_step_check = false;
   tree *nowait_clause = NULL;
-  bool ordered_seen = false;
+  tree ordered_clause = NULL_TREE;
   tree schedule_clause = NULL_TREE;
   bool oacc_async = false;
   tree last_iterators = NULL_TREE;
   bool last_iterators_remove = false;
   tree *nogroup_seen = NULL;
-  bool reduction_seen = false;
+  /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+     has been seen, -2 if mixed inscan/normal reduction diagnosed.  */
+  int reduction_seen = 0;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13706,7 +13708,17 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          goto check_dup_generic;
 
        case OMP_CLAUSE_REDUCTION:
-         reduction_seen = true;
+         if (reduction_seen == 0)
+           reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+         else if (reduction_seen != -2
+                  && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+                                        ? -1 : 1))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+                       "on the same construct");
+             reduction_seen = -2;
+           }
          /* FALLTHRU */
        case OMP_CLAUSE_IN_REDUCTION:
        case OMP_CLAUSE_TASK_REDUCTION:
@@ -13721,6 +13733,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                }
 
              t = OMP_CLAUSE_DECL (c);
+             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                 && OMP_CLAUSE_REDUCTION_INSCAN (c))
+               {
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%<inscan%> %<reduction%> clause with array "
+                           "section");
+                 remove = true;
+                 break;
+               }
            }
          t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
          if (t == error_mark_node)
@@ -14661,7 +14682,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          continue;
 
        case OMP_CLAUSE_ORDERED:
-         ordered_seen = true;
+         ordered_clause = c;
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
@@ -14688,6 +14709,20 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
+         need_complete = true;
+         need_implicitly_determined = true;
+         t = OMP_CLAUSE_DECL (c);
+         if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE is not a variable in clause %qs", t,
+                       omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             remove = true;
+           }
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -14760,7 +14795,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        = OMP_CLAUSE_SAFELEN_EXPR (safelen);
     }
 
-  if (ordered_seen
+  if (ordered_clause
       && schedule_clause
       && (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause)
          & OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
@@ -14774,7 +14809,23 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
           & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
     }
 
-  if (linear_variable_step_check)
+  if (reduction_seen < 0 && ordered_clause)
+    {
+      error_at (OMP_CLAUSE_LOCATION (ordered_clause),
+               "%qs clause specified together with %<inscan%> "
+               "%<reduction%> clause", "ordered");
+      reduction_seen = -2;
+    }
+
+  if (reduction_seen < 0 && schedule_clause)
+    {
+      error_at (OMP_CLAUSE_LOCATION (schedule_clause),
+               "%qs clause specified together with %<inscan%> "
+               "%<reduction%> clause", "schedule");
+      reduction_seen = -2;
+    }
+
+  if (linear_variable_step_check || reduction_seen == -2)
     for (pc = &clauses, c = clauses; c ; c = *pc)
       {
        bool remove = false;
@@ -14789,6 +14840,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                      OMP_CLAUSE_LINEAR_STEP (c));
            remove = true;
          }
+       else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+         OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
 
        if (remove)
          *pc = OMP_CLAUSE_CHAIN (c);
index c0720404b75fb3bc591d7b27b8f7b22a61259d9c..188752c5ed7d600e95d41da39fb116f0892ef949 100644 (file)
@@ -1,3 +1,17 @@
+2019-06-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * parser.c (cp_parser_omp_clause_reduction): Don't sorry_at on inscan
+       reductions.
+       (cp_parser_omp_scan_loop_body): New function.
+       (cp_parser_omp_for_loop): Call cp_parser_omp_scan_loop_body if there
+       are inscan reduction clauses.
+       (cp_parser_pragma): Reject PRAGMA_OMP_SCAN.
+       * semantics.c (finish_omp_clauses): Reject mixing inscan with
+       non-inscan reductions on the same construct, or inscan reductions with
+       ordered or schedule clauses, or inscan array reductions.
+       * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+       (tsubst_expr): Handle OMP_SCAN.
+
 2019-06-07  Jason Merrill  <jason@redhat.com>
 
        * constexpr.c (cxx_eval_constant_expression): Call
index 308b2d4ad700e3656c5df23d213bc1bc96c0cb4d..e699fbc6b2564ce111a08d7d011b7250c24f53b4 100644 (file)
@@ -33773,11 +33773,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
          if (strcmp (p, "task") == 0)
            task = true;
          else if (strcmp (p, "inscan") == 0)
-           {
-             inscan = true;
-             sorry ("%<inscan%> modifier on %<reduction%> clause "
-                    "not supported yet");
-           }
+           inscan = true;
          if (task || inscan)
            {
              cp_lexer_consume_token (parser->lexer);
@@ -36820,6 +36816,63 @@ cp_finish_omp_range_for (tree orig, tree begin)
     cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
 }
 
+/* OpenMP 5.0:
+
+   scan-loop-body:
+     { structured-block scan-directive structured-block }  */
+
+static void
+cp_parser_omp_scan_loop_body (cp_parser *parser)
+{
+  tree substmt, clauses = NULL_TREE;
+
+  matching_braces braces;
+  if (!braces.require_open (parser))
+    return;
+
+  substmt = cp_parser_omp_structured_block (parser, NULL);
+  substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+  add_stmt (substmt);
+
+  cp_token *tok = cp_lexer_peek_token (parser->lexer);
+  if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
+    {
+      enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+      cp_lexer_consume_token (parser->lexer);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+       {
+         tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+         const char *p = IDENTIFIER_POINTER (id);
+         if (strcmp (p, "inclusive") == 0)
+           clause = OMP_CLAUSE_INCLUSIVE;
+         else if (strcmp (p, "exclusive") == 0)
+           clause = OMP_CLAUSE_EXCLUSIVE;
+       }
+      if (clause != OMP_CLAUSE_ERROR)
+       {
+         cp_lexer_consume_token (parser->lexer);
+         clauses = cp_parser_omp_var_list (parser, clause, NULL_TREE);
+       }
+      else
+       cp_parser_error (parser, "expected %<inclusive%> or "
+                                "%<exclusive%> clause");
+
+      cp_parser_require_pragma_eol (parser, tok);
+    }
+  else
+    error ("expected %<#pragma omp scan%>");
+
+  clauses = finish_omp_clauses (clauses, C_ORT_OMP);
+  substmt = cp_parser_omp_structured_block (parser, NULL);
+  substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
+                       clauses);
+  add_stmt (substmt);
+
+  braces.require_close (parser);
+}
+
 /* Parse the restricted form of the for statement allowed by OpenMP.  */
 
 static tree
@@ -36836,6 +36889,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
   releasing_vec for_block;
   auto_vec<tree, 4> orig_inits;
   bool tiling = false;
+  bool inscan = false;
 
   for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
     if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
@@ -36851,6 +36905,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
        ordered_cl = cl;
        ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
       }
+    else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+            && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+            && (code == OMP_SIMD || code == OMP_FOR))
+      inscan = true;
 
   if (ordered && ordered < collapse)
     {
@@ -37179,7 +37237,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
     }
   else
     body = push_stmt_list ();
-  cp_parser_statement (parser, NULL_TREE, false, if_p);
+  if (inscan)
+    cp_parser_omp_scan_loop_body (parser);
+  else
+    cp_parser_statement (parser, NULL_TREE, false, if_p);
   if (orig_declv)
     body = finish_omp_structured_block (body);
   else
@@ -41044,6 +41105,12 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
       cp_parser_omp_end_declare_target (parser, pragma_tok);
       return false;
 
+    case PRAGMA_OMP_SCAN:
+      error_at (pragma_tok->location,
+               "%<#pragma omp scan%> may only be used in "
+               "a loop construct with %<inscan%> %<reduction%> clause");
+      break;
+
     case PRAGMA_OMP_SECTION:
       error_at (pragma_tok->location, 
                "%<#pragma omp section%> may only be used in "
index d2cf3458253a2760fc4eb35136c99e9d8abf50f1..ebaab27f09c148ae1458e9ce41cc327448583508 100644 (file)
@@ -16323,6 +16323,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
        case OMP_CLAUSE_NONTEMPORAL:
        case OMP_CLAUSE_USE_DEVICE_PTR:
        case OMP_CLAUSE_IS_DEVICE_PTR:
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
          OMP_CLAUSE_DECL (nc)
            = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
                                      in_decl, iterator_cache);
@@ -16443,6 +16445,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
          case OMP_CLAUSE_TASK_REDUCTION:
          case OMP_CLAUSE_USE_DEVICE_PTR:
          case OMP_CLAUSE_IS_DEVICE_PTR:
+         case OMP_CLAUSE_INCLUSIVE:
+         case OMP_CLAUSE_EXCLUSIVE:
            /* tsubst_expr on SCOPE_REF results in returning
               finish_non_static_data_member result.  Undo that here.  */
            if (TREE_CODE (OMP_CLAUSE_DECL (oc)) == SCOPE_REF
@@ -17639,6 +17643,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
     case OMP_TEAMS:
     case OMP_CRITICAL:
     case OMP_TASKGROUP:
+    case OMP_SCAN:
       r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS
                                          && OMP_TEAMS_COMBINED (t));
       tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_OMP, args, complain,
index fc5edde89c37ce28087f436b6efe251cf914566b..8e354a2990cb2137b45d15426abdaa334f1d7d4d 100644 (file)
@@ -6126,10 +6126,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   bool branch_seen = false;
   bool copyprivate_seen = false;
   bool ordered_seen = false;
+  bool schedule_seen = false;
   bool oacc_async = false;
   tree last_iterators = NULL_TREE;
   bool last_iterators_remove = false;
-  bool reduction_seen = false;
+  /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+     has been seen, -2 if mixed inscan/normal reduction diagnosed.  */
+  int reduction_seen = 0;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -6164,7 +6167,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
          goto check_dup_generic;
        case OMP_CLAUSE_REDUCTION:
-         reduction_seen = true;
+         if (reduction_seen == 0)
+           reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+         else if (reduction_seen != -2
+                  && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+                                        ? -1 : 1))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+                       "on the same construct");
+             reduction_seen = -2;
+           }
          /* FALLTHRU */
        case OMP_CLAUSE_IN_REDUCTION:
        case OMP_CLAUSE_TASK_REDUCTION:
@@ -6177,6 +6190,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  remove = true;
                  break;
                }
+             if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                 && OMP_CLAUSE_REDUCTION_INSCAN (c))
+               {
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%<inscan%> %<reduction%> clause with array "
+                           "section");
+                 remove = true;
+                 break;
+               }
              if (TREE_CODE (t) == TREE_LIST)
                {
                  while (TREE_CODE (t) == TREE_LIST)
@@ -6684,6 +6706,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                }
              OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
            }
+         if (!remove)
+           schedule_seen = true;
          break;
 
        case OMP_CLAUSE_SIMDLEN:
@@ -7583,6 +7607,37 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          branch_seen = true;
          break;
 
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
+         t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+         if (!t)
+           t = OMP_CLAUSE_DECL (c);
+         if (t == current_class_ptr)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%<this%> allowed in OpenMP only in %<declare simd%>"
+                       " clauses");
+             remove = true;
+             break;
+           }
+         if (!VAR_P (t)
+             && TREE_CODE (t) != PARM_DECL
+             && TREE_CODE (t) != FIELD_DECL)
+           {
+             if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+               break;
+             if (DECL_P (t))
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD is not a variable in clause %qs", t,
+                         omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             else
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qE is not a variable in clause %qs", t,
+                         omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+             remove = true;
+           }
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -7593,6 +7648,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        pc = &OMP_CLAUSE_CHAIN (c);
     }
 
+  if (reduction_seen < 0 && (ordered_seen || schedule_seen))
+    reduction_seen = -2;
+
   for (pc = &clauses, c = clauses; c ; c = *pc)
     {
       enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
@@ -7628,8 +7686,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_REDUCTION:
+         if (reduction_seen == -2)
+           OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+         need_implicitly_determined = true;
+         break;
        case OMP_CLAUSE_IN_REDUCTION:
        case OMP_CLAUSE_TASK_REDUCTION:
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
          need_implicitly_determined = true;
          break;
        case OMP_CLAUSE_LINEAR:
@@ -7680,6 +7744,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  (OMP_CLAUSE_SCHEDULE_KIND (c)
                   & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
            }
+         if (reduction_seen == -2)
+           error_at (OMP_CLAUSE_LOCATION (c),
+                     "%qs clause specified together with %<inscan%> "
+                     "%<reduction%> clause", "schedule");
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
        case OMP_CLAUSE_NOGROUP:
@@ -7693,6 +7761,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            }
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
+       case OMP_CLAUSE_ORDERED:
+         if (reduction_seen == -2)
+           error_at (OMP_CLAUSE_LOCATION (c),
+                     "%qs clause specified together with %<inscan%> "
+                     "%<reduction%> clause", "ordered");
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
        case OMP_CLAUSE_NOWAIT:
          if (copyprivate_seen)
            {
index 1ae3db0e59687924ec440bc6880cad7f55abe40d..961b7f42c5be6c6282cdeffe8595c75d920f759e 100644 (file)
@@ -336,6 +336,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_OMP_RETURN:
     case GIMPLE_OMP_ATOMIC_LOAD:
index 4243eb74d48c4a003ebf08c7c4bca13a3366348f..0ccbd6c6352793a9179b70c03dfaf010546759be 100644 (file)
@@ -1799,9 +1799,6 @@ dump_gimple_omp_block (pretty_printer *buffer, gimple *gs, int spc,
        case GIMPLE_OMP_MASTER:
          pp_string (buffer, "#pragma omp master");
          break;
-       case GIMPLE_OMP_TASKGROUP:
-         pp_string (buffer, "#pragma omp taskgroup");
-         break;
        case GIMPLE_OMP_SECTION:
          pp_string (buffer, "#pragma omp section");
          break;
@@ -1880,6 +1877,34 @@ dump_gimple_omp_ordered (pretty_printer *buffer, gomp_ordered *gs,
     }
 }
 
+/* Dump a GIMPLE_OMP_SCAN tuple on the pretty_printer BUFFER.  */
+
+static void
+dump_gimple_omp_scan (pretty_printer *buffer, gomp_scan *gs,
+                     int spc, dump_flags_t flags)
+{
+  if (flags & TDF_RAW)
+    dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs,
+                    gimple_omp_body (gs));
+  else
+    {
+      if (gimple_omp_scan_clauses (gs))
+       {
+         pp_string (buffer, "#pragma omp scan");
+         dump_omp_clauses (buffer, gimple_omp_scan_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_RETURN tuple on the pretty_printer BUFFER.  */
 
 static void
@@ -2652,6 +2677,11 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc,
                               flags);
       break;
 
+    case GIMPLE_OMP_SCAN:
+      dump_gimple_omp_scan (buffer, as_a <gomp_scan *> (gs), spc,
+                           flags);
+      break;
+
     case GIMPLE_OMP_CRITICAL:
       dump_gimple_omp_critical (buffer, as_a <gomp_critical *> (gs), spc,
                                flags);
index 29f33b005e11c95b7ad64dfd0737fc17286d1bef..2b8f1e0b5c8c7850c0efa792c12f4b295453e8e4 100644 (file)
@@ -336,6 +336,16 @@ walk_gimple_op (gimple *stmt, walk_tree_fn callback_op,
       }
       break;
 
+    case GIMPLE_OMP_SCAN:
+      {
+       gomp_scan *scan_stmt = as_a <gomp_scan *> (stmt);
+       ret = walk_tree (gimple_omp_scan_clauses_ptr (scan_stmt),
+                        callback_op, wi, pset);
+       if (ret)
+         return ret;
+      }
+      break;
+
     case GIMPLE_OMP_FOR:
       ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
                       pset);
@@ -650,6 +660,7 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
index 8fae60fb848b60317e46532f8672f9fa7d4b2ad8..63c8d5e85ae36fa72e402e614ad198fed12f134b 100644 (file)
@@ -1108,6 +1108,25 @@ gimple_build_omp_return (bool wait_p)
 }
 
 
+/* Build a GIMPLE_OMP_SCAN statement.
+
+   BODY is the sequence of statements to be executed by the scan
+   construct.
+   CLAUSES are any of the construct's clauses.  */
+
+gomp_scan *
+gimple_build_omp_scan (gimple_seq body, tree clauses)
+{
+  gomp_scan *p
+    = as_a <gomp_scan *> (gimple_alloc (GIMPLE_OMP_SCAN, 0));
+  gimple_omp_scan_set_clauses (p, clauses);
+  if (body)
+    gimple_omp_set_body (p, body);
+
+  return p;
+}
+
+
 /* Build a GIMPLE_OMP_SECTIONS statement.
 
    BODY is a sequence of section statements.
@@ -1943,6 +1962,12 @@ gimple_copy (gimple *stmt)
          gimple_omp_ordered_set_clauses (as_a <gomp_ordered *> (copy), t);
          goto copy_omp_body;
 
+       case GIMPLE_OMP_SCAN:
+         t = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt));
+         t = unshare_expr (t);
+         gimple_omp_scan_set_clauses (as_a <gomp_scan *> (copy), t);
+         goto copy_omp_body;
+
        case GIMPLE_OMP_TASKGROUP:
          t = unshare_expr (gimple_omp_taskgroup_clauses (stmt));
          gimple_omp_taskgroup_set_clauses (copy, t);
index 78e3467f762cdd7142bc564dcfdcb816d708453d..dd64419e8eb6fc00f11f6433010eb848a5337570 100644 (file)
@@ -331,6 +331,11 @@ DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK)
 /* OMP_RETURN marks the end of an OpenMP directive.  */
 DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
 
+/* GIMPLE_OMP_SCAN <BODY, CLAUSES> represents #pragma omp scan
+   BODY is the sequence of statements inside the single section.
+   CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
+DEFGSCODE(GIMPLE_OMP_SCAN, "gimple_omp_scan", 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 8b5c9e2190a456278fd18245e4f0790f5cfe4c57..47070e7f4099aedf5159c7a26fb1da5021916eb3 100644 (file)
@@ -741,7 +741,8 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
   tree control_use;
 };
 
-/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP.  */
+/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP,
+   GIMPLE_OMP_SCAN.  */
 
 struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
   gimple_statement_omp_single_layout : public gimple_statement_omp
@@ -773,6 +774,13 @@ struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
         stmt->code == GIMPLE_OMP_ORDERED.  */
 };
 
+struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
+  gomp_scan : public gimple_statement_omp_single_layout
+{
+    /* No extra fields; adds invariant:
+        stmt->code == GIMPLE_OMP_SCAN.  */
+};
+
 
 /* GIMPLE_OMP_ATOMIC_LOAD.
    Note: This is based on gimple, not g_s_omp, because g_s_omp
@@ -1112,6 +1120,14 @@ is_a_helper <gomp_ordered *>::test (gimple *gs)
   return gs->code == GIMPLE_OMP_ORDERED;
 }
 
+template <>
+template <>
+inline bool
+is_a_helper <gomp_scan *>::test (gimple *gs)
+{
+  return gs->code == GIMPLE_OMP_SCAN;
+}
+
 template <>
 template <>
 inline bool
@@ -1330,6 +1346,14 @@ is_a_helper <const gomp_ordered *>::test (const gimple *gs)
   return gs->code == GIMPLE_OMP_ORDERED;
 }
 
+template <>
+template <>
+inline bool
+is_a_helper <const gomp_scan *>::test (const gimple *gs)
+{
+  return gs->code == GIMPLE_OMP_SCAN;
+}
+
 template <>
 template <>
 inline bool
@@ -1475,6 +1499,7 @@ gimple *gimple_build_omp_taskgroup (gimple_seq, tree);
 gomp_continue *gimple_build_omp_continue (tree, tree);
 gomp_ordered *gimple_build_omp_ordered (gimple_seq, tree);
 gimple *gimple_build_omp_return (bool);
+gomp_scan *gimple_build_omp_scan (gimple_seq, tree);
 gomp_sections *gimple_build_omp_sections (gimple_seq, tree);
 gimple *gimple_build_omp_sections_switch (void);
 gomp_single *gimple_build_omp_single (gimple_seq, tree);
@@ -4946,6 +4971,35 @@ gimple_omp_ordered_set_clauses (gomp_ordered *ord_stmt, tree clauses)
 }
 
 
+/* Return the clauses associated with OMP_SCAN statement SCAN_STMT.  */
+
+static inline tree
+gimple_omp_scan_clauses (const gomp_scan *scan_stmt)
+{
+  return scan_stmt->clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP scan statement
+   ORD_STMT.  */
+
+static inline tree *
+gimple_omp_scan_clauses_ptr (gomp_scan *scan_stmt)
+{
+  return &scan_stmt->clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP scan statement
+   ORD_STMT.  */
+
+static inline void
+gimple_omp_scan_set_clauses (gomp_scan *scan_stmt, tree clauses)
+{
+  scan_stmt->clauses = clauses;
+}
+
+
 /* Return the clauses associated with OMP_TASKGROUP statement GS.  */
 
 static inline tree
@@ -6379,6 +6433,7 @@ gimple_return_set_retval (greturn *gs, tree retval)
     case GIMPLE_OMP_TASKGROUP:                 \
     case GIMPLE_OMP_ORDERED:                   \
     case GIMPLE_OMP_CRITICAL:                  \
+    case GIMPLE_OMP_SCAN:                      \
     case GIMPLE_OMP_RETURN:                    \
     case GIMPLE_OMP_ATOMIC_LOAD:               \
     case GIMPLE_OMP_ATOMIC_STORE:              \
index 0f3e917bc2238ddb707b1ac152672f6f22a2c204..3b4fdc7a5099d6e33981c81a985d3370458af142 100644 (file)
@@ -118,6 +118,9 @@ enum gimplify_omp_var_data
 
   GOVD_CONDTEMP = 0x1000000,
 
+  /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause.  */
+  GOVD_REDUCTION_INSCAN = 0x2000000,
+
   GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
                           | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
                           | GOVD_LOCAL)
@@ -5492,6 +5495,7 @@ is_gimple_stmt (tree t)
     case OMP_SIMD:
     case OMP_DISTRIBUTE:
     case OACC_LOOP:
+    case OMP_SCAN:
     case OMP_SECTIONS:
     case OMP_SECTION:
     case OMP_SINGLE:
@@ -8119,13 +8123,13 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
              case OMP_DISTRIBUTE:
                error_at (OMP_CLAUSE_LOCATION (c),
                          "conditional %<lastprivate%> clause on "
-                         "%<distribute%> construct");
+                         "%qs construct", "distribute");
                OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
                break;
              case OMP_TASKLOOP:
                error_at (OMP_CLAUSE_LOCATION (c),
                          "conditional %<lastprivate%> clause on "
-                         "%<taskloop%> construct");
+                         "%qs construct", "taskloop");
                OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
                break;
              default:
@@ -8242,6 +8246,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
                  OMP_CLAUSE_REDUCTION_TASK (c) = 0;
                }
            }
+         if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+           switch (code)
+             {
+             case OMP_SECTIONS:
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%<inscan%> %<reduction%> clause on "
+                         "%qs construct", "sections");
+               OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+               break;
+             case OMP_PARALLEL:
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%<inscan%> %<reduction%> clause on "
+                         "%qs construct", "parallel");
+               OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+               break;
+             case OMP_TEAMS:
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%<inscan%> %<reduction%> clause on "
+                         "%qs construct", "teams");
+               OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+               break;
+             case OMP_TASKLOOP:
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%<inscan%> %<reduction%> clause on "
+                         "%qs construct", "taskloop");
+               OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+               break;
+             default:
+               break;
+             }
          /* FALLTHRU */
        case OMP_CLAUSE_IN_REDUCTION:
        case OMP_CLAUSE_TASK_REDUCTION:
@@ -9290,6 +9324,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
          ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
          break;
 
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
+         decl = OMP_CLAUSE_DECL (c);
+         {
+           splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
+                                                  (splay_tree_key) decl);
+           if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
+             {
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "%qD specified in %qs clause but not in %<inscan%> "
+                         "%<reduction%> clause on the containing construct",
+                         decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+               remove = true;
+             }
+           else
+             {
+               n->value |= GOVD_REDUCTION_INSCAN;
+               if (outer_ctx->region_type == ORT_SIMD
+                   && outer_ctx->outer_context
+                   && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
+                 {
+                   n = splay_tree_lookup (outer_ctx->outer_context->variables,
+                                          (splay_tree_key) decl);
+                   if (n && (n->value & GOVD_REDUCTION) != 0)
+                     n->value |= GOVD_REDUCTION_INSCAN;
+                 }
+             }
+         }
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -9683,7 +9747,9 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
                             enum tree_code code)
 {
   struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+  tree *orig_list_p = list_p;
   tree c, decl;
+  bool has_inscan_reductions = false;
 
   if (body)
     {
@@ -10024,6 +10090,21 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
          break;
 
        case OMP_CLAUSE_REDUCTION:
+         if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+           {
+             decl = OMP_CLAUSE_DECL (c);
+             n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+             if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
+               {
+                 remove = true;
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qD specified in %<inscan%> %<reduction%> clause "
+                           "but not in %<scan%> directive clause", decl);
+                 break;
+               }
+             has_inscan_reductions = true;
+           }
+         /* FALLTHRU */
        case OMP_CLAUSE_IN_REDUCTION:
        case OMP_CLAUSE_TASK_REDUCTION:
          decl = OMP_CLAUSE_DECL (c);
@@ -10105,6 +10186,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
        case OMP_CLAUSE_TILE:
        case OMP_CLAUSE_IF_PRESENT:
        case OMP_CLAUSE_FINALIZE:
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
          break;
 
        default:
@@ -10123,6 +10206,18 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
   data.pre_p = pre_p;
   splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
 
+  if (has_inscan_reductions)
+    for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
+      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+         && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
+       {
+         error_at (OMP_CLAUSE_LOCATION (c),
+                   "%<inscan%> %<reduction%> clause used together with "
+                   "%<linear%> clause for a variable other than loop "
+                   "iterator");
+         break;
+       }
+
   gimplify_omp_ctxp = ctx->outer_context;
   delete_omp_context (ctx);
 }
@@ -13124,6 +13219,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        case OMP_MASTER:
        case OMP_ORDERED:
        case OMP_CRITICAL:
+       case OMP_SCAN:
          {
            gimple_seq body = NULL;
            gimple *g;
@@ -13150,6 +13246,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                                               OMP_CRITICAL_NAME (*expr_p),
                                               OMP_CRITICAL_CLAUSES (*expr_p));
                break;
+             case OMP_SCAN:
+               gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
+                                          pre_p, ORT_WORKSHARE, OMP_SCAN);
+               gimplify_adjust_omp_clauses (pre_p, body,
+                                            &OMP_SCAN_CLAUSES (*expr_p),
+                                            OMP_SCAN);
+               g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
+               break;
              default:
                gcc_unreachable ();
              }
@@ -13514,6 +13618,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
                  && code != OMP_TASKGROUP
                  && code != OMP_ORDERED
                  && code != OMP_PARALLEL
+                 && code != OMP_SCAN
                  && code != OMP_SECTIONS
                  && code != OMP_SECTION
                  && code != OMP_SINGLE);
index a7f35ffe416764b777ed30b9a869c3b89626fcbd..962eadae02f1d408ee5e5fdd386b8290022dacbc 100644 (file)
@@ -2574,6 +2574,10 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
 
   if (ctx != NULL)
     {
+      if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN
+         && ctx->outer
+         && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
+       ctx = ctx->outer;
       if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
          && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
        {
@@ -2600,7 +2604,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
                }
            }
          else if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
-                  || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)
+                  || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE
+                  || gimple_code (stmt) == GIMPLE_OMP_SCAN)
            return true;
          error_at (gimple_location (stmt),
                    "OpenMP constructs other than %<#pragma omp ordered simd%>"
@@ -3328,6 +3333,7 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
     case GIMPLE_OMP_CRITICAL:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_GRID_BODY:
       ctx = new_omp_context (stmt, ctx);
       scan_omp (gimple_omp_body_ptr (stmt), ctx);
@@ -10834,6 +10840,15 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
       gcc_assert (ctx);
       lower_omp_ordered (gsi_p, ctx);
       break;
+    case GIMPLE_OMP_SCAN:
+      ctx = maybe_lookup_ctx (stmt);
+      gcc_assert (ctx);
+      gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT);
+      if (gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)))
+       sorry_at (gimple_location (stmt),
+                 "%<#pragma omp scan%> not supported yet");
+      gsi_replace (gsi_p, gimple_build_nop (), true);
+      break;
     case GIMPLE_OMP_CRITICAL:
       ctx = maybe_lookup_ctx (stmt);
       gcc_assert (ctx);
@@ -10925,6 +10940,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
              || gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL
              || gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP
              || gimple_code (up->stmt) == GIMPLE_OMP_SECTION
+             || gimple_code (up->stmt) == GIMPLE_OMP_SCAN
              || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
                  && (gimple_omp_target_kind (up->stmt)
                      == GF_OMP_TARGET_KIND_DATA)))
@@ -11195,6 +11211,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_OMP_TARGET:
     case GIMPLE_OMP_TEAMS:
@@ -11255,6 +11272,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_OMP_TARGET:
     case GIMPLE_OMP_TEAMS:
index 072884dac2a5fc0e639d6b0547cdfd2eb1b3e62c..191fec2f7b029f2d22a4a2a6e965641e26a6db0c 100644 (file)
@@ -1,3 +1,10 @@
+2019-06-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-c++-common/gomp/scan-1.c: New test.
+       * c-c++-common/gomp/scan-2.c: New test.
+       * c-c++-common/gomp/scan-3.c: New test.
+       * c-c++-common/gomp/scan-4.c: New test.
+
 2019-06-10  Martin Liska  <mliska@suse.cz>
 
        * gcc.dg/no_profile_instrument_function-attr-1.c: Fix
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-1.c b/gcc/testsuite/c-c++-common/gomp/scan-1.c
new file mode 100644 (file)
index 0000000..17804e3
--- /dev/null
@@ -0,0 +1,209 @@
+int a, b;
+
+void
+f1 (void)
+{
+  #pragma omp scan inclusive (a)       /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+  #pragma omp scan exclusive (b)       /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+}
+
+void
+f2 (int *c, int *d, int *e, int *f)
+{
+  int i, l = 1;
+  #pragma omp for reduction (inscan, +: a) reduction (+: b)    /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */
+  for (i = 0; i < 64; i++)
+    {
+      { b++; a += c[i]; }
+      #pragma omp scan inclusive (a)                           /* { dg-error "" } */
+      d[i] = a;
+    }
+  #pragma omp for reduction (+: a) reduction (inscan, +: b)    /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */
+  for (i = 0; i < 64; i++)
+    {
+      { a++; b += c[i]; }
+      #pragma omp scan inclusive (b)                           /* { dg-error "" } */
+      d[i] = b;
+    }
+  #pragma omp for reduction (inscan, +: e[:2])                 /* { dg-error "'inscan' 'reduction' clause with array section" } */
+  for (i = 0; i < 64; ++i)
+    {
+      { e[0] += c[i]; e[1] += c[i]; }
+      #pragma omp scan inclusive (a, e[:2])                    /* { dg-error "" } */
+      { d[i] = e[0]; f[i] = e[1]; }
+    }
+  #pragma omp for reduction (inscan, +: a) ordered             /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      a += c[i];
+      #pragma omp scan inclusive (a)                           /* { dg-error "" } */
+      d[i] = a;
+    }
+  #pragma omp for reduction (inscan, +: a) ordered(1)          /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      a += c[i];
+      #pragma omp scan inclusive (a)                           /* { dg-error "" } */
+      d[i] = a;
+    }
+  #pragma omp for reduction (inscan, +: a) schedule(static)    /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      a += c[i];
+      #pragma omp scan inclusive (a)                           /* { dg-error "" } */
+      d[i] = a;
+    }
+  #pragma omp for reduction (inscan, +: a) schedule(static, 2) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      a += c[i];
+      #pragma omp scan inclusive (a)                           /* { dg-error "" } */
+      d[i] = a;
+    }
+  #pragma omp for reduction (inscan, +: a) schedule(nonmonotonic: dynamic, 2)  /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      a += c[i];
+      #pragma omp scan inclusive (a)                           /* { dg-error "" } */
+      d[i] = a;
+    }
+  #pragma omp for reduction (inscan, +: a) linear (l)          /* { dg-error "'inscan' 'reduction' clause used together with 'linear' clause for a variable other than loop iterator" } */
+  for (i = 0; i < 64; i++)
+    {
+      { a += c[i]; ++l; }
+      #pragma omp scan inclusive (a)
+      d[i] = a;
+    }
+}
+
+void
+f3 (int *c, int *d)
+{
+  int i;
+  #pragma omp teams reduction (inscan, +: a)   /* { dg-error "'inscan' 'reduction' clause on 'teams' construct" } */
+  ;
+  #pragma omp parallel reduction (inscan, +: a)        /* { dg-error "'inscan' 'reduction' clause on 'parallel' construct" } */
+  ;
+  #pragma omp sections reduction (inscan, +: a)        /* { dg-error "'inscan' 'reduction' clause on 'sections' construct" } */
+  {
+    #pragma omp section
+    ;
+  }
+  #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++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a)   /* { dg-error "" } */
+      a += c[i];
+    }
+  #pragma omp teams
+  {
+  #pragma omp distribute parallel for reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a)   /* { dg-error "" } */
+      a += c[i];
+    }
+  #pragma omp distribute parallel for simd reduction (inscan, +: a)    /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a)   /* { dg-error "" } */
+      a += c[i];
+    }
+  }
+}
+
+void
+f4 (int *c, int *d)
+{
+  int i;
+  #pragma omp taskloop reduction (inscan, +: a)        /* { dg-error "'inscan' 'reduction' clause on 'taskloop' construct" } */
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a)   /* { dg-error "" } */
+      a += c[i];
+    }
+}
+
+void
+f5 (int *c, int *d)
+{
+  int i;
+  #pragma omp simd reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a, b)        /* { dg-error "'b' specified in 'exclusive' clause but not in 'inscan' 'reduction' clause on the containing construct" } */
+      a += c[i];
+    }
+}
+
+void
+f6 (int *c, int *d)
+{
+  int i;
+  #pragma omp simd reduction (inscan, +: a, b) /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a)
+      a += c[i];
+    }
+}
+
+void
+f7 (void)
+{
+  int i;
+  #pragma omp simd reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      if (i == 23)     /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+       continue;       /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */
+      else if (i == 27)
+       goto l1;        /* { dg-error "invalid branch to/from OpenMP structured block" } */
+      #pragma omp scan exclusive (a)
+      {
+       l1: a = 0;      /* { dg-error "jump to label 'l1'" "" { target c++ } } */
+       if (i == 33)    /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+         continue;     /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */
+      }
+  }
+}
+
+void
+f8 (int *c, int *d, int *e, int *f)
+{
+  int i;
+  #pragma omp for reduction (inscan, +: a, b)          /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      { a += c[i]; b += d[i]; }
+      #pragma omp scan inclusive (a) inclusive (b)     /* { dg-error "expected end of line before 'inclusive'" } */
+      { e[i] = a; f[i] = b; }
+    }
+  #pragma omp for reduction (inscan, +: a, b)          /* { dg-error "'.' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+  for (i = 0; i < 64; i++)
+    {
+      { a += c[i]; b += d[i]; }
+      #pragma omp scan                                 /* { dg-error "expected 'inclusive' or 'exclusive' clause before end of line" } */
+      { e[i] = a; f[i] = b; }
+    }
+}
+
+void
+f9 (void)
+{
+  int i;
+  #pragma omp simd reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      if (i == 23)     /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+       break;          /* { dg-error "break statement used with OpenMP for loop" "" { target c } } */
+      #pragma omp scan exclusive (a)
+      a++;
+    }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-2.c b/gcc/testsuite/c-c++-common/gomp/scan-2.c
new file mode 100644 (file)
index 0000000..14b74a5
--- /dev/null
@@ -0,0 +1,14 @@
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+  int i;
+  #pragma omp simd reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a)           /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */
+      a += c[i];
+    }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-3.c b/gcc/testsuite/c-c++-common/gomp/scan-3.c
new file mode 100644 (file)
index 0000000..4865e08
--- /dev/null
@@ -0,0 +1,14 @@
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+  int i;
+  #pragma omp for reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan inclusive (a)           /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */
+      a += c[i];
+    }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-4.c b/gcc/testsuite/c-c++-common/gomp/scan-4.c
new file mode 100644 (file)
index 0000000..32d4006
--- /dev/null
@@ -0,0 +1,14 @@
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+  int i;
+  #pragma omp for simd reduction (inscan, +: a)
+  for (i = 0; i < 64; i++)
+    {
+      d[i] = a;
+      #pragma omp scan exclusive (a)           /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */
+      a += c[i];
+    }
+}
index 26cfa7ea19f1d1bc03c12924e5cdced1a4eec182..977b768128ed0870ddc8041c220cda2f11fe4327 100644 (file)
@@ -306,13 +306,19 @@ enum omp_clause_code {
      OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list).  */
   OMP_CLAUSE_MAP,
 
-  /* OpenACC clause: use_device (variable_list).
+  /* OpenACC clause: use_device (variable-list).
      OpenMP clause: use_device_ptr (variable-list).  */
   OMP_CLAUSE_USE_DEVICE_PTR,
 
   /* OpenMP clause: is_device_ptr (variable-list).  */
   OMP_CLAUSE_IS_DEVICE_PTR,
 
+  /* OpenMP clause: inclusive (variable-list).  */
+  OMP_CLAUSE_INCLUSIVE,
+
+  /* OpenMP clause: exclusive (variable-list).  */
+  OMP_CLAUSE_EXCLUSIVE,
+
   /* Internal structure to hold OpenACC cache directive's variable-list.
      #pragma acc cache (variable-list).  */
   OMP_CLAUSE__CACHE_,
index 719846ac9a2e45c1a0407290a559e84e0966cc5f..52f45a73b1d71e7a5ac63dd6f1f60e7f9c96cc70 100644 (file)
@@ -1638,6 +1638,12 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
                    gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt)));
          break;
 
+       case GIMPLE_OMP_SCAN:
+         s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+         copy = gimple_build_omp_scan
+                  (s1, gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)));
+         break;
+
        case GIMPLE_OMP_SECTION:
          s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
          copy = gimple_build_omp_section (s1);
@@ -4365,6 +4371,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
index 5cf2e3dbdfde8029a90be607a7de5e9683d4b3e8..22aa64237563c7aafde19f4d2f7119f4d012753a 100644 (file)
@@ -1619,6 +1619,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       break;
@@ -2322,6 +2323,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_SECTION:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
                 info, gimple_omp_body_ptr (stmt));
       break;
@@ -2831,6 +2833,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_TASKGROUP:
     case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SCAN:
     case GIMPLE_OMP_CRITICAL:
       walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
       break;
index 455579c12903bbf03499cf857d7849d6d8ed2fd1..1e6c96813bbb59d82b77513aa32ec8ec149c6fb1 100644 (file)
@@ -467,6 +467,12 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
     case OMP_CLAUSE_IS_DEVICE_PTR:
       name = "is_device_ptr";
       goto print_remap;
+    case OMP_CLAUSE_INCLUSIVE:
+      name = "inclusive";
+      goto print_remap;
+    case OMP_CLAUSE_EXCLUSIVE:
+      name = "exclusive";
+      goto print_remap;
     case OMP_CLAUSE__LOOPTEMP_:
       name = "_looptemp_";
       goto print_remap;
@@ -3308,6 +3314,14 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
       pp_string (pp, "#pragma omp section");
       goto dump_omp_body;
 
+    case OMP_SCAN:
+      if (OMP_SCAN_CLAUSES (node))
+       {
+         pp_string (pp, "#pragma omp scan");
+         dump_omp_clauses (pp, OMP_SCAN_CLAUSES (node), spc, flags);
+       }
+      goto dump_omp_body;
+
     case OMP_MASTER:
       pp_string (pp, "#pragma omp master");
       goto dump_omp_body;
index 43ce44fcee46fa5cdadebb35311450047a4dfd66..5d955535accd8f3681dac9dc35747c7ad0fe2cb9 100644 (file)
@@ -300,6 +300,8 @@ unsigned const char omp_clause_num_ops[] =
   2, /* OMP_CLAUSE_MAP  */
   1, /* OMP_CLAUSE_USE_DEVICE_PTR  */
   1, /* OMP_CLAUSE_IS_DEVICE_PTR  */
+  1, /* OMP_CLAUSE_INCLUSIVE  */
+  1, /* OMP_CLAUSE_EXCLUSIVE  */
   2, /* OMP_CLAUSE__CACHE_  */
   2, /* OMP_CLAUSE_GANG  */
   1, /* OMP_CLAUSE_ASYNC  */
@@ -378,6 +380,8 @@ const char * const omp_clause_code_name[] =
   "map",
   "use_device_ptr",
   "is_device_ptr",
+  "inclusive",
+  "exclusive",
   "_cache_",
   "gang",
   "async",
@@ -12295,6 +12299,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_LINK:
        case OMP_CLAUSE_USE_DEVICE_PTR:
        case OMP_CLAUSE_IS_DEVICE_PTR:
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
        case OMP_CLAUSE__LOOPTEMP_:
        case OMP_CLAUSE__REDUCTEMP_:
        case OMP_CLAUSE__CONDTEMP_:
index 1d6ddedd9657191e67917dcff8b7f3d681cd8e1c..10a14fc23b0c19a6ef4e405c230fa68850bdf596 100644 (file)
@@ -1191,6 +1191,11 @@ DEFTREECODE (OMP_SINGLE, "omp_single", tcc_statement, 2)
    Operand 1: OMP_SINGLE_CLAUSES: List of clauses.  */
 DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 2)
 
+/* OpenMP - #pragma omp scan
+   Operand 0: OMP_SCAN_BODY: Scan body.
+   Operand 1: OMP_SCAN_CLAUSES: List of clauses.  */
+DEFTREECODE (OMP_SCAN, "omp_scan", tcc_statement, 2)
+
 /* OpenMP - #pragma omp section
    Operand 0: OMP_SECTION_BODY: Section body.  */
 DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1)
index 5b50941aa8371664aeec02dbe3417106ab18115c..d45a391428e55e1588957c54190049d280ff8053 100644 (file)
@@ -1344,7 +1344,7 @@ class auto_suppress_location_wrappers
 #define OMP_BODY(NODE) \
   TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_MASTER), 0)
 #define OMP_CLAUSES(NODE) \
-  TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_TASKGROUP), 1)
+  TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_SCAN), 1)
 
 /* Generic accessors for OMP nodes that keep clauses as operand 0.  */
 #define OMP_STANDALONE_CLAUSES(NODE) \
@@ -1435,6 +1435,9 @@ class auto_suppress_location_wrappers
 #define OMP_TARGET_EXIT_DATA_CLAUSES(NODE)\
   TREE_OPERAND (OMP_TARGET_EXIT_DATA_CHECK (NODE), 0)
 
+#define OMP_SCAN_BODY(NODE)    TREE_OPERAND (OMP_SCAN_CHECK (NODE), 0)
+#define OMP_SCAN_CLAUSES(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 1)
+
 #define OMP_CLAUSE_SIZE(NODE)                                          \
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
                                              OMP_CLAUSE_FROM,          \